拆解Redis Cluster,怎麼實現“寫安全”這個重要特性?

本文由 dbaplus 社羣授權轉載。

Redis是非常流行的緩存。在Redis升級到3.0版本後,升級到 集羣 版本,被稱之爲 Redis Cluster 。在集羣版本中,會將數據分成多份,被保存到多個server中,從而保證集羣的水平擴展能力,加之每份數據保存多個副本,從而保證可用性,並且集羣版本保證一定程度的Write Safety。本文詳細介紹Redis Cluster的實現細節,從而分析Redis Cluster的Write Safety的保證程度。

一、接口和架構

1、接口

Redis Cluster的接口基本向前兼容,仍然是key-value類型。

2、架構

Redis Cluster包含server和client兩個組件。一個Redis Cluster可以包含多個server,可以包含多個客戶端。每個客戶端可以連接任意的server,讀取寫入數據。保存在Redis Cluster中的數據會被分成多份,分散地保存在多個server中,並且每一份數據也會保存多個副本。

二、實現

1、節點

在Redis Cluster中,數據會被保存到多個Redis server中,每個Redis server都是一個獨立的進程,具有獨立的IP和Port,也被稱之爲一個 實例 ,或者叫做 節點(Node) 。Client通過這個IP和Port連接到這個Node。

每個節點都有個 node id ,node id是一個全局唯一的標識,它是在集羣創建時隨機生成的。一個節點的id始終都不會變化的,但是node的IP和port是可以變化的。

2、Node table

一個Redis Cluster包含哪些節點,也就是這個集羣包含哪些節點的id,也就是 集羣成員關係 ,這個信息被保存在一個表結構中,被稱之爲 node table 。node table類似於:

id ip port
id1 xxx.xxx.xxx.xxx 3001
id2 xxx.xxx.xxx.xxx 3002

node table會在每個節點上都保存一份,Redis Cluster通過gossip協議把node table複製到所有的節點。後面會繼續講述node table的複製。

3、集羣成員關係變更

當添加一個節點或者刪除一個節點時,只需要將命令發給集羣中的任意一個節點,這個節點會修改本地的node table,並且這個修改會最終複製到所有的節點上去。添加節點的命令是CLUSTER MEET,刪除節點的命令是CLUSTER FORGET。

舉例來說明:

打算搭建一個3個master節點的集羣,當集羣創建以前,所有3個節點的node table都只包含自己。給其中的一個節點A發送命令,CLUSTER MEET NodeB,節點A修改自己的node table,將NodeB添加到自己的node table中,並且連接節點B,把自己的node table發送給節點B,節點B收到節點A發送過來的node table,會更新自己的node table,這時節點B就知道集羣中還有節點A存在。

這時,給節點A再發送CLUSTER MEET NodeC,節點A會把節點C添加到自己的node table,並且把自己的node table複製給節點B,節點B把接收到的node table更新自己的本地的node table,從而知道節點C的加入。同樣節點A會把自己的node table發給節點C,節點C會更新自己本地的node table,從而知道要加入的集羣中已經存在節點A和節點B。

4、槽

前面說過Redis Cluster會把數據分成多份,也就是把數據進行 分片 。Redis Cluster中的每一份數據被稱爲 Slot )。Redis Cluster將數據拆分成16384份,也就是說有16384個槽。

Redis Cluster採用 哈希Hash )機制來拆分數據。首先,數據的key通過CRC16算法計算出一個哈希值。這個哈希值再對16384取餘,這個餘數就是槽位,被稱爲 hash slot 。具體的CRC16算法可以參看Redis官方文檔。所有餘數相同的key都在一個slot中,也就是說,一個slot其實就是一批hash餘數相同的key。

每個hash slot都會保存在Redis Cluster一個節點中。具體哪個hash slot被保存在哪個實例中,就形成了類似於一個map的數據結構,被稱之爲 hash slot map 。hash slot map類似於:

1 -> NodeA
2 -> NodeB
...
16383 -> NodeN

與node table相同,hash slot map也會在每個節點上都會保存一份,Redis Cluster通過gossip協議把hash slot map複製到所有節點。同樣,後面還會講述hash slot map的複製。

5、數據分片變更

要修改數據分片關係,可以連接任意一個節點,給這個節點發送CLUSTER ADDSLOTS, CLUSTER SETSLOT, CLUSTER DELSLOT命令,修改這個節點上的hash slot map,該節點會把這個修改複製到所有其他節點,其他節點會用接收到的hash slot map更新自己的hash slot map。

CLUSTER ADDSLOTS、CLUSTER DELSLOTS、CLUSTER SETSLOT命令的使用如下:

CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]
CLUSTER DELSLOTS slot1 [slot2] ... [slotN]
CLUSTER SETSLOT slot NODE node

CLUSTER ADDSLOTS用來把多個slot分配給當前連接的節點。例如,連接到節點A執行:

CLUSTER ADDSLOTS 1 2 3

這個命令會把slot1、slot2、slot3分配給節點A。

CLUSTER DELSLOTS用來把多個slot從當前連接的節點刪除。例如,連接到節點A執行:

CLUSTER DELSLOTS 1 2 3

這個命令會把slot1、slot2、slot3從節點A上刪除。

CLUSTER SETSLOT用來把一個slot分配給指定的節點,可以不是當前連接的節點,另外這個命令還可以設定MIGRATING和IMPORTING兩個狀態,我們後面再講。例如,連接到節點A執行:

CLUSTER SETSLOT 1 nodeB

這個命令會把slot1分配給節點B。

6、Slave

一個slot會被保存多個副本,既一個slot會保存在多個節點上,也就是slot會複製到多個節點上。Redis Cluster的複製是以節點爲單位的,一個節點上的所有slot會採用相同的複製。

具體來說就是,其中一個節點會負責處理這個節點上所有slot的寫操作,這個節點被稱爲 master ,而其餘的節點被稱爲 slave 節點。一個master可以有多個slave。在同一個節點上的所有slot的所有的寫操作都會被從master節點異步複製到所有的slave節點。所以slave會具有與master相同的slot。

通過SLAVEOF命令來設置slave節點。SLAVEOF命令用來改變一個slave節點的複製設置。SLAVEOF命令有兩種格式:

  • SLAVEOF NO ONE
  • SLAVEOF host port

具體來講,SLAVEOF NO ONE命令會停止一個slave節點的複製,並且把這個slave節點變成master節點。SLAVEOF host port命令會停止一個slave節點的複製,丟棄數據集,開始從host和port指定的新master節點複製。

master和slave的關係會被記錄在hash slot table中,相當於一個slot會映射到多個節點上,其中一個節點是master,其他記錄的節點是slave。

加入了master/slave信息後的hash slot map類似於:

0 -> NodeA,NadeA1(slave)
1 -> NodeA,NadeA1(slave)
2 -> NodeB,NadeB1(slave)
...
16383 -> NodeN,NadeN1(slave)

作爲hash slot map的一部分,master/slave信息也會通過gossip協議複製到集羣中的每個節點。

7、Configuration

node table和hash slot map這兩個信息,被稱之爲 Configuration ,在其他的分佈式系統中,也被稱之爲元數據。

前面我們講過,hash slot map和node table在每個節點都會保存一份,並且對這兩個信息的任何改動,都會通過gossip協議 傳播(propogate) 到所有的節點。本文我們就不繼續展開gossip協議了,對Redis Cluster的gossip協議的實現感興趣的同學可以參看redis的文檔。

在某些分佈式系統中,元數據被存儲在一個單獨的架構組件中的。Redis Cluster並沒有這樣一個元數據存儲的組件,而是把元數據分散的存儲在所有的節點上。

hash slot map和node table在集羣創建時會被創建出來,並且會隨着後續的集羣變更(比如failover和擴容、縮容等運維操作,後面會講述)而跟隨着變更。變動會在一個Node上發起,通過gossip協議傳播到所有其他的節點。這兩個信息在所有節點都會保存,並且會最終達到一致。

8、集羣創建

創建Redis Cluster時,首先要以cluster模式運行多個redis server,redis server運行起來後,這些server的node id就已經生成了。但是這些redis server並沒有形成集羣,也就是server彼此之間並不知道相互的存在。接下來運行CLUSTER MEET命令,讓這些節點形成一個集羣。但是這時集羣仍然沒有處於運行狀態,需要分配slot,通過CLUSTER SLOTADD命令把slot分配給具體的節點之後,集羣就可以處理client的命令了。

9、客戶端的讀寫操作

客戶端要讀取、寫入數據時,雖然client可以連接任意server,但是實際中,client需要根據實際需求連接到server讀取、寫入數據。client需要先根據key計算出hash slot,連接到負責這個hash slot的節點進行讀寫操作。這樣的話,client就要需要知道hash slot -> node的映射關係,也就是需要知道hash slot map。

前面講過hash slot map被保存在server端的每個節點上。client可以從任意節點獲取hash slot map,並且把它緩存到client本地,下次操作時根據本地緩存直接進行操作,但是需要處理緩存信息過期的問題,如果client發現hash slot map發生變化(即client讀取寫入數據時server回錯誤,接下來會詳細講述),會重新從server端獲取新的hash slot map。通過hash slot map可以判斷某個key應該存在在哪個節點上,client再連接這個節點進行讀寫操作。

10、MOVED Redirection

hash slot map會發生變更,這些變更會複製到所有的節點,但是gossip保證的是最終複製到所有的節點,再加上client會緩存hash slot map,client可能會把某個key的請求發給錯誤的節點來處理。

錯誤的節點收到請求後,發現這個key不應該自己來處理,會給客戶端返回MOVED的錯誤,在錯誤消息中,會告訴客戶端,哪個節點應該負責這個slot。Client收到MOVED消息後,會向消息中指定的節點再次發送請求。

client可以將slot的節點信息更新到本地緩存的hash slot map中,但是更好的方法是,重新獲取完整的hash slot map,替換本地的緩存。因爲在大多數情況下,hash slot map中的變更不僅僅只修改一個slot。

雖然client按照MOVED消息中的節點信息重新發送請求,但是client仍然可能再次從新節點收到MOVED錯誤消息,因爲上一個節點的hash slot map可能也不是最新的。但是因爲hash slot map最終會在所有的節點上一致,所以client在幾次收到MOVED錯誤後,最終會獲取到最新的hash slot map。

11、Failover、currentEpoch、lastVoteEpoch

當master發生故障宕機後,Redis Cluster會選出一個slave來接替這個master。

如果有多個slave存在,那麼每個slave都可能都會發現master發生了宕機,並且試圖把自己變成爲master,如果有多個slave成爲master,那麼這些新master都會更新本地hash slot map,把舊master負責的slot更新成自己,並且把自己對hash slot map的更新傳播給其他的節點。這會導致hash slot map在節點間出現差異。

從而導致,因爲所連接的節點不同,client拿到不同的hash slot map,對於同一個slot,不同的client會連接不同的節點,最終導致節點上的數據出現差異。所以failover要保證,只有一個slave被選成新master。

Redis Cluster採用了類似Raft算法的技術來防止多個slave被選成master。每個節點都會有叫做currentEpoch、lastVoteEpoch的兩個值。在集羣剛創建時,每個節點的currentEpoch都是0。

當slave發現master宕機時,這個slave會增加currentEpoch(即currentEpoch++)。並且向所有的master發送FAILOVER_AUTH_REQUEST請求,請求中會攜帶自己currentEpoch,master收到FAILOVER_AUTH_REQUEST,如果請求中的currentEpoch比自己的currentEpoch和lastVoteEpoch都大,則記錄請求中的currentEpoch值到自己的currentEpoch、lastVoteEpoch中,並且回覆FAILOVER_AUTH_ACK給slave,回覆中攜帶master的currentEpoch。

所以可以看出,FAILOVER_AUTH_ACK中的Epoch一定與slave的currentEpoch相同。Slave從大多數的master收到FAILOVER_AUTH_ACK後,則成爲master。

上面的過程保證只有一個slave被選出,我們來舉例說明。五個master的集羣,master節點分別是A、B、C、D、E,A節點有兩個slave,分別是A1和A2。A節點發生宕機,A1增加自己的currentEpoch=5(4+1),A1給所有的master發送FAILOVER_AUTH_REQUEST,節點B、C、D收到FAILOVER_AUTH_REQUEST,把自己的currentEpoch和lastVoteEpoch更新成5,並且給A1回覆FAILOVER_AUTH_ACK,A1贏得選舉,成爲新的master。但是與此同時,A2也發現A宕機,也試圖選舉成master。A2增加自己的currentEpoch=5(4+1),A2給所有的master發送FAILOVER_AUTH_REQUEST,但這時的B、C、D的lastVoteEpoch已經是5,所以B、C、D不會給A2回覆,E還沒有收到A1的請求,所以只有E會給A2回覆,但是不能形成大多數,所以A2不能稱爲master。

上面講述的過程已經可以保證只有一個master被選出,但是除此之外,Redis Cluster還做了一個優化,那就是master回覆了一個請求後不會在給這個master的其他的slave發送回覆。

12、Configuration epoch

failover完成後,新master會修改hash slot map,把相應的slot記錄的節點改成自己,並且把這次對hash slot map的改動傳播給其他節點。

雖然currentEpoch和lastVoteEpoch能保證每次failover只能有一個節點被選成新的master,但是先後兩次failover,可能選出的兩個不同的master,但是他們對hash slot map的修改的傳播卻是異步,也就是後面一次failover的改動可能先於第一次failover的改動到達某個節點,從而導致節點間對hash slot map這個信息產生不一致。

Redis Cluster通過configEpoch來解決這個問題。每個節點會保存一個configEpoch的值。相當於在node table中還會有一列數據叫configEpoch,類似於下面的表:

id ip port
configEpoch id1 xxx.xxx.xxx.xxx
3001 1 id2
xxx.xxx.xxx.xxx 3002 2

每次failover完成後,新選出的master會用currentEpoch覆蓋configEpoch。Failover的機制保證兩次failover的新master一定是具有不同的currentEpoch,並且後一次的failover的currentEpoch一定比前一次大。這樣就可以保證,即便採用了gossip這樣傳播協議,仍然能夠保證最後一次failover的hash slot map的變更會生效,也就是configEpoch更大的變更會生效,並且最終所有的節點上的hash slot map是一致的。

Slave節點的configEpoch就是其master的configEpoch。

由於gossip保證的hash slot map最終保持一致的,所以可能存在slave的hash slot map舊於master,failover不能基於舊的hash slot map基礎上做變更,所以前面failover的過程中還需要補充一個規則要遵守:

  • 在FAILOVER_AUTH_REQUEST中會攜帶slave節點的configEpoch,如果這個slave的configEpoch比這個slave負責的所有slot的master的configEpoch中任意一個要小,則master不會給slave回覆FAILOVER_AUTH_ACK。

13、Resharding

在集羣創建之後,我們還會有對Redis cluster做擴容、縮容、balancing這樣的運維需求,這些需求本質上都可以用 Resharding 操作解決,resharding操作就是把slot在節點間重新的分佈,把slot從一個節點轉移到另外一個節點上。在Redis Cluster中,擴容需求實質上就是加入一個新的節點,再把一些slot分配到這個新節點上。

縮容需求實質上就是先把這個節點上的所有slot分配到其他節點上,再把這個節點從集羣中移出。當節點間的流量不均衡時,我們有balancing這樣的需求,balancing就是把流量比較大的節點上的一些slot分配都流量比較少的節點上。

Resharding操作可以是對整個hash slot map的調整,也就是可以包括對多個slot的 遷移(migration) ,遷移就是把一個slot從一個節點遷移到另外一個節點。一個slot migration操作包括前面講的hash slot map變更,另外還包括key的遷移操作。要把一個slot遷移到另外的節點上,首先把這個slot上的所有的key遷移到這個節點,當把所有key都遷移完後,再進行hash slot map變更,當hash slot map變更完成,這次slot migration結束。

Redis Cluster使用CLUSTER SETSLOT來設置遷移。舉例說明,將slot1從節點A遷移到節點B。分別對節點A和節點B執行下面的命令:

  • 節點A上:CLUSTER SETSLOT 1 MIGRATING NODEB
  • 節點B上:CLUSTER SETSLOT 1 IMPORTING NODEA

其中,MIGRATING表示數據要從這個節點遷出,而IMPORTING表示數據要往這個節點遷入。

執行完這兩個命令後,節點A中的slot1不在創建新的key。一個叫做redis-trib的特殊的程序負責把所有的key從節點A遷移到節點B。redis-trib會執行下面的命令:

CLUSTER GETKEYSINSLOT slot count

這個命令會返回count個key,對於每個返回的key,redis-trib執行下面的命令:

MIGRATE target_host target_port key target_database id timeout

這個命令會原子地把一個key從節點A遷移到節點B。具體來說,MIGRATE命令會連接目標節點,併發向目標節點發送這個key,一旦目標節點收到這個key,則從自己的數據庫中刪除這個key,在這個過程中,節點A和節點B都會加鎖。

在把所有的key遷移完後,再分別在兩個節點上執行下面的命令:

CLUSTER SETSLOT slot NODE nodeA

把所有的key遷移完一般需要一些時間,也就是說在開始遷移後和完成遷移前,在這個窗口期內,key的實際的分佈,與hash slot map裏記錄的是不一致的,client按照hash slot map訪問key,會出現錯誤。

Redis Cluster通過ASK redirection來解決這個問題。按照client端的hash slot map,slot1的key一定會發給節點A,節點A收到這個請求後,如果發現這個key已經遷移到節點B了,那麼就會給client回覆ASK redirection,client收到ASK redirection後,會向節點b先發送一個ASKING命令,之後在發送對這個key的請求。

14、Configuration的實際存儲

Hash slot map和node table都是邏輯上的結構,他們在Redis Cluster中的實際存儲結構稍有不同(詳情看結尾參考資料1、2、3、4)。

在節點的內存中,用兩個變量來存儲這兩個信息:

  • myself變量 :myself代表本節點,是一個ClusterNode類型的變量,這個變量中,包含本節點的configEpoch,還包括slaveof,如果是slave節點則在slaveof中記錄着它的master節點,還包括一個bitmap,代表這個節點負責的所有的slot的槽位值。這個bitmap有2048個byte組成,一總是16384(2048*8)個bit,每個bit代表一個slot,bit置1,代表這個節點負責這個slot;
  • cluster變量 :代表了所在集羣的狀態,它包含currentEpoch、lastVoteEpoch和slots數組,slots數組的index代表了slot,數組的每個成員都指向一個節點,是一個ClusterNode類型的變量,與myself變量的類型一樣。

所有Configuration的更改都會被保存到磁盤中,具體來講是保存到一個名字叫node.conf的文件中,這個文件是Redis Cluster負責寫入的,不需要人工配置。

node.conf按照節點維度進行保存。每一行對應一個節點,每行分別包含這些信息:id,ip:port,flag,slaveof,ping timestamp, pong timespamp,configEpoch,link status,slots。

所有的節點結束後,會在文件的最後保存curruntEpoch和lastVoteEpoch兩個變量。其中flag字段是枚舉類型,會指明這個節點是不是自己,節點類型是master還是slave。

如果是slave節點,則會在slaveof字段記錄其master節點的id。如果是master節點,則在最後多一個slots字段,記錄着這個節點負責着哪些slot。Flags字段還記錄着其他非常重

要的狀態,本文就不繼續展開了。

同樣,ping timestamp、pong timestmap、link staus三個字段本文也不繼續展開了。

具體的node.conf文件類似下面的例子:

[[email protected] data]# cat nodes-6384.conf
fb763117270d14205c41174605b15741co03a945 10.112.178.174:6383 slave 5e35bda1a44c8d781eb54e08be88a3bab42070f3 0 1596683852819 2 connected
3dc5890fb1591e3b20196f81eb5f2f99754253e8 10.112.178.141:6383 master - 0 1596683851915 1 connected 0-5461
f1967b687c9b2c27108cce08517e98e7a80d5e7e 10.112.178.171:6383 slave 3dc5890fb1591e3b20196f81eb5f2f99754253e8 0 1596683850813 1 connected
2bbab7353e973e991566df3bb52afb4857a7bf25 10.112.178.171:6384 slave 1f0a8cf1bfd0c915ef404482f3dc6bf5c7cf41f5 0 1596683848812 3 connected
5e35bda1a44c8d781eb54e08be88a3bab42070f3 10.112.178.142:6383 master - 0 1596683849813 2 connected 5462-10923
1f0a8cf1bfd0c915ef404482f3dc6bf5c7cf41f5 10.112.178.141:6384 myself,master - 0 0 3 connected 10924-16383

節點啓動時會讀取node.conf文件,把裏面的信息加載到myself和cluster兩個變量中。Slot信息會被轉換成bitmap保存在myself變量中。並且slot信息還會逆向的轉換成slot到節點的映射保存在cluster變量中。

hash slot map變更或者node table變更,就是修改內存中的myself變量和cluater變量,並且每次變更都會把這兩個變量序列化轉化後保存到node.conf中。

15、查看configuration

Redis Cluster提供了兩個命令來查看configuration:

第一個是CLUSTER SLOT命令,用來展示hash slot維度的信息,CLUSTER SLOT命令的展示如下:

127.0.0.1:7000> cluster slots
1)  1) (integer) 5461
2) (integer) 10922
3)  1) "127.0.0.1"
2) (integer) 7001
4)  1) "127.0.0.1"
2) (integer) 7004
2)  1) (integer) 0
2) (integer) 5460
3)  1) "127.0.0.1"
2) (integer) 7000
4)  1) "127.0.0.1"
2) (integer) 7003
3)  1) (integer) 10923
2) (integer) 16383
3)  1) "127.0.0.1"
2) (integer) 7002
4)  1) "127.0.0.1"
2) (integer) 7005

第二個是CLUSTER NODE命令,用來展示node table維度的信息,CLUSTER NODE命令的展示如下:

$ redis-cli cluster nodes
d1861060fe6a534d42d8a19aeb36600e18785e04 127.0.0.1:6379 myself - 0 1318428930 1 connected 0-1364
3886e65cc906bfd9b1f7e7bde468726a052d1dae 127.0.0.1:6380 master - 1318428930 1318428931 2 connected 1365-2729
d289c575dcbc4bdd2931585fd4339089e461a27d 127.0.0.1:6381 master - 1318428931 1318428931 3 connected 2730-4095

CLUSTER NODE命令展示的結果與node.conf文件中的內容非常類似。每一行都代表一個節點,每一行都包含node id, address:port, slaveof,flags, last ping sent, last pong received, configuration epoch, link state, slots這些字段。

CLUSTER NODE、CLUSTER SLOT兩個命令可以連接到任意節點上執行,這兩個命令都是讀取的這個節點的本地信息,根據gossip的特性,存在這兩個命令展示的不是最新的configuration的可能性。

16、Conflict

雖然前面講的failover過程通過大多數master投票的方式保證只有一個slave選中,並且產生唯一的configEpoch。但是Resharding的過程卻沒有經過大多數的master的投票。

執行slot遷移時,僅僅是在集羣中所有configEpoch中最大的那個configEpoch的基礎上,再加一而得到的。並且由於Resharding一般包括多個slot的遷移,Redis cluster目前的做法是,在一次resharding過程中,所有的slot遷移使用的configEpoch都是第一個slot遷移時產生的那個configEpoch。

而failover和resharding都會修改hash slot map,如果在resharding的過程中發生了failover,這就有可能導致對hash slot map的修改產生衝突。另外,手動failover也是不經過master投票的,也就是執行CLUSTER FAILOVER命令(帶TAKEOVER參數)。

產生衝突就是指針對同一個slot,slot被修改成映射到不同的節點上,並且這些修改具有相同的configEpoch。

爲了解決這個問題,Redis cluster需要存在一個衝突解決的機制。如果一個master發現相同的configEpoch,則比較一下兩個節點的id,id小的節點,把自己currentEpoch加一,作爲自己的configEpoch。

三、Write Safety

由於有衝突的存在,可能導致不同的節點上的hash slot map不一致,取決於連接的節點不同,一部分client可能會把某個slot的key寫入到一個節點中,而另外一部分client會把同樣slot的key寫入到另外一個節點中。當衝突被解決後,其中一個節點上接受的寫入會丟失。

另外,由於master和slave之間的數據複製是異步的,在failover時如果slave還沒有收到最新的數據,就發生了failover,那麼這部分寫入就會丟失。Redis cluster在這方面做了一個優化,當一個slave發現master發生了宕機,它不會立即開始選舉的過程,它會等待一個時間,這個時間計算公式如下:

DELAY = 500 milliseconds + random delay between 0 and 500 milliseconds + SLAVE_RANK * 1000 milliseconds

這個計算公式中,

  • 第一部分是一個固定500毫秒的時間,這是爲了給master充分的時間,也發現節點宕機這個事實;
  • 第二個是隨機等待一段時間,這是爲了儘量避免多個slave同時發現master宕機,然後同時開始選舉,導致master被瓜分,從而導致所有的選舉都不成功;
  • 第三部分是slave的rank,rank主要取決於slave的複製進度,複製的數據越多,則rank越小,也就是越短的等待時間,越先開始選舉,有更大的可能性被選成新的master。但這僅僅是個優化,不能完全防止丟數據的可能。

參考資料

[1]https://github.com/redis/redis/blob/unstable/src/cluster.c

[2]https://github.com/redis/redis/blob/unstable/src/cluster.h

[3]https://github.com/redis/redis/blob/unstable/src/server.c

[4]https://github.com/redis/redis/blob/unstable/src/server.h

作者介紹

陳東明,現任國美在線基礎架構總監。曾任餓了麼北京技術中心任架構組負責人,負責產品線架構設計及基礎架構研發工作;曾任百度架構師,負責即時通訊產品的架構設計。具有豐富的大規模系統構建和基礎架構研發經驗,善於複雜業務需求下的大併發、分佈式系統設計和持續優化。個人公衆號:dongming_cdm。

原文鏈接

拆解Redis Cluster,怎麼實現“寫安全”這個重要特性?

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