Redis集羣的數據一致性

Redis 並不能保證數據的強一致性

一般所說的redis集羣概念有3種:

  1. 主從(主從全量)
  2. 哨兵模式(主從全量,其中一個node監控集羣狀態)
  3. redis-cluster (數據分片存儲,分佈到各個分區,每個分區可以有多個node再主從全量)

Redis-cluster集羣概念

(1)由多個Redis服務器組成的分佈式網絡服務集羣;

(2)集羣之中有多個Master主節點,每一個主節點都可讀可寫;

(3)節點之間會互相通信,兩兩相連;

(4)Redis集羣無中心節點。

在很多集羣架構中爲了保證集羣數據的一致性,都會使用一致性哈希算法,因爲一致性哈希算法可以保證無論是增加節點還是減少節點,被影響的數據都是一小部分數據。

Redis 集羣沒有使用一致性哈希,取而代之的是引入了哈希槽的概念。

Redis 集羣沒有使用一致性哈希,取而代之的是引入了哈希槽的概念

Redis 集羣有16384個哈希槽,每個要保存到Redis的鍵值對,都會先通過CRC16函數計算,然後再對16384取模,來決定這個鍵值對要被放置哪個槽。

客戶端可以請求任意一個節點,每個節點中都會保存所有16384個slot對應到哪一個節點的信息。如果一個key所屬的slot正好由被請求的節點提供服務,則直接處理並返回結果,否則返回MOVED重定向信息,如下:

GET key
一MOVED slot IP:PORT

客戶端處理該重定向信息,並且向擁有該key的節點發起請求。實際應用中Redis客戶端可以通過向集羣請求slot和節點的映射關係並緩存,然後通過本地計算要操作的key所屬的slot,查詢映射關係並直接向正確的節點發起請求,這樣可以獲得幾乎等價於單節點部署的性能。

哈希槽

集羣的每個節點都會負責一部分哈希槽

舉個例子,如果當前集羣有3個節點M1、M2、M3,那麼:

  • 節點 M1可能 包含 0 到 5500號哈希槽
  • 節點 M2可能 包含5501 到 11000 號哈希槽
  • 節點 M3可能包含11001 到 16384號哈希槽

由於Redis集羣始終包含16384個哈希操作,因此它很容易添加或者刪除節點。如果我想新添加個節點M4,那我只需要從節點 M1,M2,M3中得到部分槽,然後遷移到M4上即可。

或者,如果我想移除節點M4,那我們只需要將M4中的槽移到M1、M2和M3節點上,最後將沒有任何槽的M4節點從集羣中移除即可

由於從一個節點將哈希槽移動到另一個節點並不會停止服務,所以無論添加、刪除或者改變某個節點的哈希槽數量都不會造成集羣不可用的狀態。

存入到Redis集羣中的每個Key是通過CRC16函數計算後取模再映射到不同的哈希槽中的,但CRC16函數的結果是一個16bit的數,也就是說它的最大值是2**16=65536

在Redis集羣中每個節點每秒都會向集羣中其他節點發送 ping 消息,以檢測其它節點的狀態。

在消息頭中最佔空間的是保存哈希槽位置的bitmap大小。Bitmap的每一個位代表一個槽,如果該位爲1,則表示這個槽是屬於這個節點的。所以如果哈希槽總數設置爲65536,那這個bitmap的大小最大將達到65536/(8*1024)= 8k。

另外,消息體中還會攜帶有約爲集羣總節點數量的1/10(至少攜帶3個)的節點的信息。這樣節點數量越多,消息體內容越大。

所以,爲降低由於消息過大而造成的通信阻塞影響,Redis的作者將Redis的節點數限制在1000,將哈希槽數限制在16384。

Redis集羣的主從架構

爲了使在部分節點失敗或者大部分節點無法通信的情況下集羣仍然可用,所以集羣使用了主從複製模型,每個節點都會有N-1個複製品。

./redis-trib.rb create --replicas 1 192.168.159.10:7001 192.168.159.10:7002 192.168.159.10:7003 192.168.159.10:7004 192.168.159.10:7005 192.168.159.10:7006

例如有A,B,C三個節點的集羣,在沒有複製模型的情況下,如果節點B失敗了,那麼整個集羣就會以爲缺少B節點所承擔的哈希槽這個範圍的槽而不可用。默認情況的整個集羣也是不能使用的,不過我們可以改

cluster-require-full-coverage

當cluster-require-full-coverage爲no時,表示當負責一個插槽的主庫下線且沒有相應的從庫進行故障恢復時集羣仍然可用。

集羣節點複製

在Redis-Cluster集羣中,可以給每一個主節點添加從節點,主節點和從節點直接遵循主從模型的特性。

當用戶需要處理更多讀請求的時候,添加從節點可以擴展系統的讀性能。

故障轉移

Redis集羣的主節點內置了類似Redis Sentinel的節點故障檢測和自動故障轉移功能,當集羣中的某個主節點下線時,集羣中的其他在線主節點會注意到這一點並對已下線的主節點進行故障轉移。

集羣分片策略

Redis-cluster分片策略是用來解決key存儲位置的。

集羣將整個數據庫分爲16384個槽位slot,所有key-value數據都存儲在這些slot中的某一個。一個slot槽位可以存放多個數據,key的槽位計算公式爲:slot_number=crc16(key)%16384,其中crc16爲16位的循環冗餘校驗和函數。

集羣中的每個主節點都可以處理0個至16383個槽,當16384個槽都有某個節點在負責處理時,集羣進入上線狀態並開始處理客戶端發送的數據命令請求。

集羣分片策略

集羣redirect轉向

由於Redis集羣無中心節點,請求會隨機發給任意主節點;

主節點只會處理自己負責槽位的命令請求,其它槽位的命令請求該主節點會返回客戶端一個轉向錯誤;

客戶端根據錯誤中包含的地址和端口重新向正確的負責的主節點發起命令請求。

Redis6.0推出集羣代理:redis-cluster-proxy

https://github.com/RedisLabs/redis-cluster-proxy

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章