Redis集群搭建及選舉原理


本文轉載自:https://www.cnblogs.com/nijunyang/p/12508098.html

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服務,我這里使用三個一主一從來搭建。因此先將6redis服務使用指定的配置文件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,上面一共6redis節點,因此會構建三個一主一從。

 

執行命令之前,如果你的redis環境以前搭建過主從或者哨兵之類的,數據不干凈可能會報錯,最好將持久化文件刪掉,然后flushdb,將以前臟數據清理掉,否則可能出現如下錯誤:

 

 

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

 

 

 

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

 

 

 

 至此集群搭建完畢

4.集群操作

以集群方式連接redis客戶端通過cluster info查看集群信息,通過cluster nodes查看節點信息

src/redis-cli -a 密碼 -c   集群方式連接

 

 

 

 我們設置set abc 123一個值 會看見客戶點會計算abcslot7638 然后重定向到對應的主從的master上面去寫數據

 

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

 

 

 

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

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

 

集中式集群和分片式集群

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

 

gossip協議包含多種消息,包括pingpongmeetfail等等。

 

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

 

pong: 返回pingmeet,包含自己的狀態和其他信息,也可以用於信息廣播和更新;

 

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

 

延遲計算公式:

 

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

 

•SLAVE_RANK表示此slave已經從master復制數據的總量的rankRank越小代表已復制的數據越新。這種方式下,持有最新數據的slave將會首先發起選舉(理論上)。

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM