1. 程式人生 > >Redis叢集搭建及選舉原理

Redis叢集搭建及選舉原理

redis叢集簡述

哨兵模式中如果主從中master宕機了,是通過哨兵來選舉出新的master,在這個選舉切換主從的過程,整個redis服務是不可用的。而且哨兵模式中只有一個主節點對外提供服務,因此沒法支援更高的併發。而且當個主節點的記憶體設定也不宜過大。否則會導致持久化檔案過大,影響資料恢復或主從同步的效率。

 

redis叢集是由一系列的主從節點群組成的分散式伺服器群,它具有複製、高可用和分片特性。Redis叢集不需要 sentinel哨兵也能完成節點移除和故障轉移的功能。需要將每個節點設定成叢集模式,這種叢集模式沒有中心節點,客戶端通過CRC16演算法對key進行hash

得到一個值,來判斷該key儲存在哪個主從服務上面,因此就算是某一個主從整個宕機,redis叢集也是部分可用的。方便水平擴充套件,可以根據業務規模可以隨時加減配置。據官方文件稱可以線性擴充套件到上萬個節點(但是官方推薦不超過1000個節點)。redis叢集的效能和高可用性均優於哨兵模式。

 

 

 

Redis叢集搭建

 

 

 

1.修改redis.conf配置檔案

  1. daemonize yes                    後臺啟動   
  2. cluster-enabled yes                開啟叢集模式
  3. cluster-config-file nodes-6379.conf   叢集配置資訊存放檔名
  4. cluster-node-timeout 5000          節點離線時間限制,到達此值時發起某個主從重新選舉master
  5. protected-mode no                關閉保護模式
  6. requirepass xxx                   設定本機密碼
  7. masterauth xxx                    設定訪問別的機器的密碼

2.注意關閉伺服器的防火牆,否則可能造成節點之間無法通訊,無法搭建叢集

使用修改好的配置檔案啟動redis服務,我這裡使用三個一主一從來搭建。因此先將6個redis服務使用指定的配置檔案redis-master.conf啟動起來:src/redis-server redis-master.conf

3.搭建叢集服務

為了保險起見最好先檢查下每臺機器的redis服務是否正常啟動了ps -ef|grep redis

可以看見redis服務程序後面有個cluster的標誌,普通啟動的redis服務是沒有這個標誌的

 

 

5.0版本可以直接使用C語言客戶端提供的指令去構建叢集:

src/redis-cli -a xxx --cluster create --cluster-replicas 1 192.168.0.67:6379 192.168.0.68:6379 192.168.0.69:6379 192.168.0.70:6379 192.168.0.71:6379 192.168.0.72:6379

-a  配置的密碼

--cluster create  表示叢集建立

--cluster-replicas   表示每個master幾個slave,上面一共6個redis節點,因此會構建三個一主一從。

 

執行命令之前,如果你的redis環境以前搭建過主從或者哨兵之類的,資料不乾淨可能會報錯,最好將持久化檔案刪掉,然後flushdb,將以前髒資料清理掉,否則可能出現如下錯誤:

 

 

 正常執行會返回一個叢集分配計劃,我們按照它的計劃即可:

 

 

 

 

 

 然後節點之間就開始通訊構建叢集,最後會看見16384個slots分配完畢,可以看見構建計劃中有三個master,每個master都是有指定槽位的。意思就是存入的key經過crc16 hash演算法之後得到的值,在哪個範圍內,就儲存到那個redis主從上面去,這就是redis的分片叢集模式。

 

 至此叢集搭建完畢

4.叢集操作

以叢集方式連線redis客戶端通過cluster info檢視叢集資訊,通過cluster nodes檢視節點資訊

src/redis-cli -a 密碼 -c   叢集方式連線

 

 我們設定set abc 123一個值 會看見客戶點會計算abc的slot是7638, 然後重定向到對應的主從的master上面去寫資料

 

 現在我看下java客戶端的jedis裡面的key值計算redis.clients.util.JedisClusterCRC16#getSlot(java.lang.String):

 

 

 

最後計算結果就會落到0-16383之間去。

當 Redis Cluster 的客戶端來連線叢集時,它也會得到一份叢集的槽位配置資訊並將其快取在客戶端本地。這樣當客戶 端要查詢某個 key 時,可以直接定位到目標節點。同時因為槽位的資訊可能會存在客戶端與伺服器不一致的情況,還需 要糾正機制來實現槽位資訊的校驗調整。

 

 

集中式叢集和分片式叢集

Redis節點之間使用的是gossip協議進行通訊,每個節點之間都會互相通訊。

 

gossip協議包含多種訊息,包括ping,pong,meet,fail等等。

 

ping:每個節點都會頻繁給其他節點發送ping,其中包含自己的狀態還有自己維護的叢集元資料,互相通過ping交換元資料;

 

pong: 返回ping和meet,包含自己的狀態和其他資訊,也可以用於資訊廣播和更新;

 

fail: 某個節點判斷另一個節點fail之後,就傳送fail給其他節點,通知其他節點,指定的節點宕機了。

 

meet:某個節點發送meet給新加入的節點,讓新節點加入叢集中,然後新節點就會開始與其他節點進行通訊,不需要傳送形成網路的所需的所有CLUSTER MEET命令。傳送CLUSTER MEET訊息以便每個節點能夠達到其他每個節點只需通 過一條已知的節點鏈就夠了。由於在心跳包中會交換gossip資訊,將會建立節點間缺失的連結。

 

 

 

gossip協議的優點在於元資料的更新比較分散,不是集中在一個地方,更新請求會陸陸續續,打到所有節點上去更新, 有一定的延時,降低了壓力;缺點在於元資料更新有延時可能導致叢集的一些操作會有一些滯後。

 

就是自己提供服務的埠號+10000,比如6379,那麼用於節點間通訊 的就是16379埠。 每個節點每隔一段時間都會往另外幾個節點發送ping訊息,同時其他幾點接收到ping訊息之後返回pong訊息。

 

 

 

還有就是集中式的,比如ZK叢集

 

集中式的有點在於資料的更新和讀取,時效性非常好,一旦元資料出現變更立即就會更新到集中式(master)的儲存中,其他節點讀取的 時候立即就可以立即感知到;不足在於所有的元資料的更新壓力全部集中在一個地方,可能導致元資料的儲存壓力。

 

 

 

 

Redis叢集選舉機制

 

當slave發現自己的master變為FAIL狀態時,便嘗試發起選舉,以期成為新的master。由於掛掉的master可能會有多個slave,從而存在多個slave競爭成為master節點的過程, 其過程如下:

 

1.slave發現自己的master變為FAIL

 

2.將自己記錄的叢集currentEpoch(選舉輪次標記)加1,並廣播資訊給叢集中其他節點

 

3.其他節點收到該資訊,只有master響應,判斷請求者的合法性,併發送結果

 

4.嘗試選舉的slave收集master返回的結果,收到超過半數master的統一後變成新Master

 

5.廣播Pong訊息通知其他叢集節點。

 

如果這次選舉不成功,比如三個小的主從A,B,C組成的叢集,A的master掛了,A的兩個小弟發起選舉,結果B的master投給A的小弟A1,C的master投給了A的小弟A2,這樣就會發起第二次選舉,選舉輪次標記+1繼續上面的流程。事實上從節點並不是在主節點一進入 FAIL 狀態就馬上嘗試發起選舉,而是有一定延遲,一定的延遲確保我們等待FAIL狀態在叢集中傳播,slave如果立即嘗試選舉,其它masters或許尚未意識到FAIL狀態,可能會拒絕投票。 同時下面公式裡面的隨機數,也可以有效避免slave同時發起選舉,導致的平票情況。

 

•延遲計算公式:

 

DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms

 

•SLAVE_RANK表示此slave已經從master複製資料的總量的rank。Rank越小代表已複製的資料越新。這種方式下,持有最新資料的slave將會首先發起選舉(理論上)。

 

 

 

前面說到這種分片的叢集模式的叢集可以部分提供服務,當redis.conf的配置cluster-require-full-coverage為no時,表示當一個小主從整體掛掉的時候叢集也可以用,也是說0-16383個槽位中,落在該主從對應的slots上面的key是用不了的,但是如果key落在其他的範圍是仍然可用的。

 

 

 

 

 

&n