redis叢集之分片叢集的原理和常用代理環境部署

2022-12-01 12:00:51

上篇文章剛剛介紹完redis的主從複製叢集,但主從複製叢集主要是為了解決redis叢集的單點故障問題,通過整合哨兵能實現叢集的高可用;但是卻無法解決資料容量以及單節點的壓力問題,所以本文繼續介紹redis的分片叢集;分片叢集即將不同的資料分發到不同的redis範例(或者主從叢集),每個redis範例沒有關聯,這樣當資料量過大時就做到了資料的分治,如果某個範例故障也不至於丟失所有的資料;下面我會首先解決分片叢集的常用實現方案,然後介紹如何搭建Twitter和predixy兩種代理實現的redis叢集,正常情況,按照我的步驟做完就能夠搭建一套可以的redis叢集了;下面開始

一、分片叢集的解決方案

這裡我們不單一討論redis,我們從分片叢集的根本出發,分片即將資料分發到不同的後端服務上去,那麼顯然我們可以從使用者端和伺服器端這兩個方面下手;

1、使用者端實現

(1)、通過業務分類

  • 可以根據業務分類,由使用者端控制,將不同業務線的資料打到不同的範例

(2)、hash+取模(modula)

  • 思路:通過對key進行hash+取模然後根據結果打到不同的範例上;模幾取決於redis叢集的範例數量;
  • 缺點:模數是固定的,如果叢集拓展時需要調整,且拓展前的資料就不好取到了;

(3)、通過亂數選擇redis範例(random)

  • 思路:資料到達時隨機往叢集中的某個範例扔資料,這樣存資料是容易了但是取資料難
  • 使用場景:這種情況適用於實現訊息佇列,往不同的redis裡仍相同key的不同資料,使用者端消費叢集中的每個範例後就能獲取到完整資料

(4)、一致性雜湊環(ketama)

  • 思路:維護一個虛擬的環形結構,該環有N個點組成;將redis叢集中的所有範例通過一致性雜湊演演算法計算後對映到該雜湊環上,作為環中唯一的物理節點,如果叢集有三個範例,那麼環中就會有三個物理節點;當資料進來時,對key做雜湊運算最終也要落到這個雜湊環上,然後找出離自己最近的物理節點,再將資料打到該節點上即可
  • 缺點:
    • 由於每個範例參與計算的資訊不一樣,並不總能保證叢集的各節點在環上是均勻分佈的,所以為了解決資料傾斜的問題,可以將每個範例多對映幾份一起參與計算,這樣散在環上的節點變多了,也就一定程度上解決了資料傾斜的問題
    • 當有新的範例上線時,會丟失一定長度資料;可以通過改變尋找範例的邏輯解決,當key打到環上時,我們不再是找離它最近的一個節點,而是找離他最近的兩個節點取資料

2、伺服器端實現(redis cluster)

(1)、基本概念介紹(概念摘自redis官網)

  • Redis叢集是一個提供在多個Redis間節點間共用資料的程式集,能夠自動分發資料到不同範例;其並沒有使用一致性雜湊演演算法,而是引入了雜湊槽的概念;Redis叢集有16384個雜湊槽,每個key通過CRC16校驗後對16384取模來決定放置哪個槽.叢集的每個節點負責一部分hash槽,舉個例子,比如當前叢集有3個節點,那麼:
    • 節點 A 包含 0 到 5500號雜湊槽.
    • 節點 B 包含5501 到 11000 號雜湊槽.
    • 節點 C 包含11001 到 16384號雜湊槽.

這種結構很容易新增或者刪除節點. 比如如果我想新新增個節點D, 我需要從節點 A, B, C中得部分槽到D上. 如果我想移除節點A,需要將A中的槽移到B和C節點上,然後將沒有任何槽的A節點從叢集中移除即可. 由於從一個節點將雜湊槽移動到另一個節點並不會停止服務,所以無論新增刪除或者改變某個節點的雜湊槽的數量都不會造成叢集不可用的狀態.

(2)、redis的叢集搭建

  • 這裡的搭建很簡單,按照中文官網的步驟往下走就行了,這裡就不一一介紹了,需要搭建的可以移步http://redis.cn/topics/cluster-tutorial.html

二、通過Twitter的twemproxy代理搭建redis叢集

twemproxy是由Twitter開源的一套代理分片服務,可以接受多個使用者端的存取然後根據設定的演演算法將資料分配到不同的redis節點,再按原路返回;不支援redis的watch、multi等命令

  • 1、mkdir twemproxy 在/root目錄建立一個twemproxy用來存放twemproxy的原始碼

  • 2、安裝git yum install git

  • 3、克隆twemproxy的程式碼

  • 4、進入原始碼目錄,cd twemproxy

  • 5、安裝automake和libtool

    • yum install automake libtool -y
  • 6、安裝configure,執行autoreconf -fvi

  • 7、執行 ./configure

  • 8、執行make編譯原始碼,編譯完正常會有可執行程式出現

  • 9、進入原始碼的/scripts目錄,將組態檔拷貝至/etc/init.d/twemproxy目錄

    • cp nutcracker.init /etc/init.d/twemproxy
  • 10、進入init.d檔案, 執行chmod +x twemproxy給twemproxy賦權

  • 11、建立組態檔所在的目錄

    • mkdir /etc/nutcracker
  • 12、進入原始碼安裝目錄的conf目錄,將conf目錄下的組態檔拷貝到11步建立的資料夾下

    • cd ~/soft/twemproxy/twemproxy/conf
    • cp ./* /etc/nutcracker/
  • 13、進入原始碼安裝目錄的src目錄,將編譯完的可執行程式複製到/usr/bin目錄下,這樣在系統任意位置都可以執行nutcracker

    • cd ~/soft/twemproxy/twemproxy/src/
    • cp nutcracker /usr/bin
  • 14、進入nutcracker目錄,修改組態檔

    • cd /etc/nutcracker/
    • cp nutcracker.yml nutcracker.yml.bak 穩妥起見,先備份
    • vi nutcracker.yml 編輯組態檔
  • 15、啟動兩個redis範例

    • redis-server ~/testRedis/6379.conf
    • redis-server ~/testRedis/6380.conf
  • 16、啟動nutcracker

    • service twemproxy start
  • 17、啟動redis使用者端連線nutcracker對外暴露的埠

    • redis-cli -p 22121 連線成功後如圖,即可對redis進行操作

    我們通過22121埠的代理就可以直接存取redis叢集,可以設定資料,但是由於資料分治了,所以例如keys 、watch、multi等這種聚合的命令在代理裡是不支援的;至此,通過twemproxy 代理的方式搭建的redis叢集就完成了,使用者端只需連結22121埠,至於後續的分片操作由代理服務進行轉發

三、通過predixy搭建redis叢集

predixy也是一款redis的代理服務,其即支援redis sentinel又支援redis cluster,在group只有一個的情況下,其還支援watch、multi等指令

  • 1、在~/soft目錄建立predixy目錄並且進入,用於下載原始碼;
    • mkdir predixy
    • cd predixy
  • 2、下載原始碼包
  • 3、解壓
    • tar xf predixy-1.0.5-bin-amd64-linux.tar.gz
  • 4、進入conf目錄,編輯predixy.conf檔案
    • vi predixy.conf
    • 將bind 127.0.0.1:7617的註釋放開
    • 將Include try.conf註釋,將Include sentinel.conf放開
  • 5、編輯sentinel.conf 檔案
    • vi sentinel.conf
    • 將SentinelServerPool設定的註釋放開,並按下圖進行設定

Sentinels{}裡填哨兵叢集的ip和埠

Group表示redis分組,shard001表示分組名稱;上圖設定表示一個哨兵叢集監控了兩套redis的主從叢集

注意:Group後面跟的名稱需要與哨兵組態檔裡的master名稱一致

  • 6、根據5中的注意,所以我們現在需要去修改哨兵的組態檔,將其監控的master名稱由預設的mymaster改為shard001,又因為我們需要哨兵監控兩個主從叢集,所以需要再加一個shard002的master設定,命令如下:

    • vi 26379.conf 、 vi 26380.conf 、 vi 26381.conf

    • 修改完的組態檔如下圖

    注意:上圖只擷取了26379的設定,26380和81與79除了port外其餘設定均一致

  • 7、啟動哨兵叢集

    • redis-server ./26379.conf --sentinel
    • redis-server ./26380.conf --sentinel
    • redis-server ./26381.conf --sentinel
  • 8、任意位置建立資料夾test,在裡面建立36379、80和46379、80的目錄

    • 進入36379目錄執行 redis-server --port 36379

    • 進入36380目錄執行 redis-server --port 36380 --replicaof 127.0.0.1 36379追隨36379

      這樣一個主從叢集就搭建起來了,46379和80與上面一致,只需更改對應埠即可,我這裡就不再贅述了

    至此,哨兵叢集與兩套redis主從複製叢集已啟動完畢

  • 9、進入predixy安裝的bin目錄啟動predixy

    • cd soft/predixy/predixy-1.0.5/bin
    • ./predixy ../conf/predixy.conf
    • 啟動成功如下圖:
  • 10、用redis使用者端測試

    雖然上面搭建廢了九牛二虎之力,但是對使用者端而言只需關注predixy對外暴露的服務連線即可:

    • redis-cli -p 7617

    連線成功後就可以操作redis了,predixy會自動分發到不同的redis叢集中去;設定如圖:

    • 然後連線36379可以發現,k1和設定了tag的key都分發到此了,如圖:
    • 再連線46379,發現k2被分發到46379了

predixy只支援單group下的事務、watch等操作,我們這裡設定了兩個group所以不支援;但是如果只設定一個group的話那麼能寫的也只有一個master,就失去了分片叢集的意義了