Redis 集羣實現

Nosql,做爲程序員在當下不瞭解點兒,還真不行,出去聊起來別人就會說你土。那麼就聊聊其中一個比較火的redis。redis單機版沒得說,可是一直沒有集羣版,有也是山寨的。前段時間對redis的實現進行了一些學習,明天就要發佈redis集羣的穩定版,做爲記念以及學習,發一下redis集羣實現的細節,英文好的就看原文吧。node

redis集羣實現一個高性能、線性可擴展的1000節點的集羣。程序員

Redis集羣沒有最重要或者說中心節點,這個版本最主要的一個目標是設計一個線性可伸縮(可隨意增刪節點?)的功能。redis

Redis集羣沒有任何的數據合併動做。寫,直接是與主節點通訊,但同步到slave也有一個時間窗口。在可用性方面,除了master以及全部slave失效,否則一直可用。算法

Redis集羣爲了數據的一致性可能犧牲部分容許單點故障的功能,因此當網絡故障和節點發生故障時這個系統會盡力去保證數據的一致性和有效性。(這裏咱們認爲節點故障是網絡故障的一種特殊狀況)sql

爲了解決單點故障的問題,咱們同時須要masters 和 slaves。 即便主節點(master)和從節點(slave)在功能上是一致的,甚至說他們部署在同一臺服務器上,從節點也僅用以替代故障的主節點。 實際上應該說 若是對從節點沒有read-after-write(寫並當即讀取數據 以避免在數據同步過程當中沒法獲取數據)的需求,那麼從節點僅接受只讀操做。數據庫

wps_clip_image-14343

已實現的子集

Redis集羣實現單一key在非分佈式版本的Redis中的全部功能。對於複合操做好比求並集求交集之類則只實如今單個節點的操做。緩存

增長了hash tags的概念,主要用來強制把某些multi-key分配在一個節點。可是在resharding中,這些multi-key可能找不到。安全

Redis集羣版本將再也不像獨立版本同樣支持多數據庫,在集羣版本中只有database 0,而且SELECT命令是不可用的。服務器

客戶端與服務端在Redis集羣版中的約定

在Redis集羣版本中,節點有責任/義務保存數據和自身狀態,這其中包括把數據(key)映射到正確的節點。全部節點都應該自動探測集羣中的其餘節點,而且在發現故障節點以後把故障節點的從節點更改成主節點(原文這裏有「若是有須要」 多是指須要設置或者說存在從節點)。網絡

集羣節點使用TCP bus和二進制協議進行互聯並對任務進行分派。各節點使用gossip 協議發送ping packets給集羣其餘節點以肯定其餘節點是否正常工做。Cluster bus也能夠用來在節點間執行PUB/SUB命令。

當發現集羣節點無應答的時候則會使用redirections errors -MOVED and -ASK命令而且會重定向至可用節點。理論上客戶端可隨意向集羣中任意節點發送請求並得到重定向,也就是說客戶端實際上並不用關心集羣的狀態。然而,客戶端也能夠緩存數據對應的節點這樣能夠免去服務端進行重定向的工做,這在必定程度上能夠提升效率。

安全寫

Redis cluster節點之間經過異步複製,這樣總會存在丟數據的窗口。可是client在鏈接master多的分區和少的分區的窗口是不同的。

Redis cluster在鏈接master多的分區的時候,儘可能保證不丟寫操做。除了下面兩種狀況:

1)當一個寫到達master,master已經回覆client,可是master還沒來的及複製到slave就宕機了,那麼這個寫操做就會丟失。直到其中一個slave被提拔爲master。

2)另一種理論上可能丟失寫操做的狀況以下,

一個master由於partition不可到達

其中一個slave獲取master失敗

一下子後master能夠從新到達

一個client沒用更新路由表,還在向舊的master寫

實際上,這是不太可能發生,由於節點沒法到達其餘大多數master故障切換,再也不接收寫操做須要足夠的時間,並當分區固定後,一段時間內寫操做仍然是拒絕的,讓其餘節點通知有關配置更改。

Redis cluster會丟失不少寫操做,當一個或多個客戶端鏈接到一個少master分區時。由於若是這些master不能夠到達多master的分區,這些寫操做就會丟失。

若是在NODE_TIMEOUT前不可到達,不會丟消息,若是在NODE_TIMEOUT後,會有消息丟失。(暫時不理解爲啥不丟消息)。

可用性

少master分區是不開用的,假設多master分區至少有一個不開到達master的slave,那麼在NODE_TIMEOUT後,slave就會被選舉爲相應的master。假設一個master有一個slave,那麼可用性爲1-(1/(2*n-1))。

性能

在Redis中不在經過代理命令來肯定給定鍵的節點,而是它們將客戶端重定向到服務密鑰空間的給定部分的節點。

最終客戶保存着集羣和那個節點提供密鑰的時間標識符,因此在正常操做期間,client直接聯繫合適的節點,以便發送給定的命令。

由於使用異步複製的,節點不等待寫入的其餘節點的確認。

此外,因爲限制多個鍵執行操做命令的子集,若是不rsharding,數據歷來不在節點之間移動。

因此在單個Redis的實例下,正常操做處理能夠完成的,在N個主節點Redis的集羣,能夠指望以單一的Redis實例相同的性能乘以N做爲設計的線性擴展。在同一時間,一般在單次往返執行查詢,由於客戶一般保持與節點持久鏈接,以便和單個獨立的Redis節點延遲性也是同樣的。

很是高的性能和弱(非CAP)的可擴展性,但合理的形式一致性和可用性是主要目標。

爲何避免合併操做

Redis集羣設計避免了版本衝突的相同鍵值在多個節點,由於在Redis的數據模型下,這並不老是可取的:在Redis的值一般都很是大,這是常常能夠看到的,列表或數百萬元素的sorted set。另外,數據類型在語義上是複雜的。轉移和合並這些類型的值,可能須要的應用程序端邏輯實現。

Keys分配模式

Key分爲16384,這樣最多能夠有16384個節點,可是建議最多有1000個節點。

全部的主節點會控制16384個key空間的百分比。當集羣穩定以後,也就是說不會再更改集羣配置(hash slot不在節點之間移動),那麼一個節點將只爲一個hash slot服務。(可是服務節點(主節點)能夠擁有多個從節點用來防止單點故障)

用來計算key屬於哪一個hash slot的算法以下:

HASH_SLOT = CRC16(key) mod 16384

Name: XMODEM (also known as ZMODEM or CRC-16/ACORN)

Width: 16 bit

Poly: 1021 (That is actually x^16 + x^12 + x^5 + 1)

Initialization: 0000

Reflect Input byte: False

Reflect Output CRC: False

Xor constant to output CRC: 0000

Output for "123456789": 31C3

這裏咱們會取CRC16後的14個字節。在咱們的測試中,對於16384個slots, CRC16算法最合適。

Keys散列tags

有一個計算hash slots的例外是使用hash tags。Hash tags以確保兩個鍵被分配在相同的hash slot。這是用在爲了實現多鍵在Redis集羣中操做。

爲了實現hash tags,hash時使用了不一樣的算法。基本上若是關鍵字包含「{...}」,那麼在{和}之間的字符串被hash,然而可能有多個匹配的{或}該算法由如下規則規定:

若是key包含{,在{的右邊有一個},並在第一次出現{與第一次出現}之間有一個或者多個字符串,那麼就做爲key進行hash。例如,{user1000}.following和{user1000}.followed就在同一個hash slot;foo{}{bar}整個字符被hash,foo{{bar}},{bar被hash;foo{bar}{zap},bar被hash。

集羣節點特性

在集羣中每一個節點都擁有惟一的名字。節點名爲16進制的160 bit隨機數,當節點獲取到名字後將被當即啓用。節點名將被永久保存到節點配置文件中,除非系統管理員手動刪除節點配置文件。

節點名是集羣中每一個節點的身份證實。在不更改節點ID的狀況下是容許修改節點IP和地址的。cluster bus會自動經過gossip協議獲取更改後的節點設置。

每一個節點可獲知其餘節點的信息包括:

IP 端口

狀態

管理的hash slots

cluster bus最後發送PING的時間

最後接收到PONG的時間

標記節點失敗的時間

從節點數量

若是是slave,那麼還包含master節點ID

不管是主節點仍是從節點均可以經過CLUSTER NODES命令來獲取以上信息
示例以下:

$ redis-cli cluster nodes

d1861060fe6a534d42d8a19aeb36600e18785e04 :0 myself - 0 1318428930 connected 0-1364

3886e65cc906bfd9b1f7e7bde468726a052d1dae 127.0.0.1:6380 master - 1318428930 1318428931 connected 1365-2729

d289c575dcbc4bdd2931585fd4339089e461a27d 127.0.0.1:6381 master - 1318428931 1318428931

集羣拓撲結構

Redis的集羣是一個全網狀的,經過TCP,每個節點都與其餘每一個節點鏈接。在N個節點的集羣中,每一個節點有N-1個對外TCP鏈接,和N-1的傳入鏈接。這些TCP鏈接一直保持着,不須要的時候才建立。

節點握手

節點永遠接受集羣總線端口的鏈接,即便ping命令的節點不被信任,當收到ping時也回覆。可是,若是該節點不是集羣中的,全部的其餘數據包將被丟棄。

一個節點被另外一個視爲集羣的一部分,只能經過下面兩種方式:

1)若是一個節點的MEET消息。和ping消息類似,但強制把該節點作爲集羣的一部分。只有系統管理員經過如下的命令,節點才發送MEET消息給其餘節點。

CLUSTER MEET ip port

2)節點也將註冊另外一個信任的節點做爲集羣的一部分。若是A知道B和B知道C,最終B就發送C相關的gossip消息到A。當發生這種狀況,A將C做爲網絡的一部分,並會嘗試鏈接C。

這意味着,只要咱們加入的節點在連通圖中,他們最終會自動造成一個徹底連通圖。基本上集羣可以自動發現其餘節點,但僅當由系統管理員肯定。這種機制使得集羣更加健壯,但可防止意外地混合不一樣的Redis集羣將IP地址或其它變化後的網絡相關事件。若是連接斷開,全部節點積極嘗試鏈接到全部其餘已知的節點。

MOVED重定向

客戶端發送查詢到集羣中的隨便一個節點,甚至是slave,該節點分析查詢,看key在那個節點hash slot中,若是hash slot在本節點,處理很是簡單,不然檢查hash slot和節點ID對應關係,方式MOVED error。

一個MOVED error以下:

GET x

-MOVED 3999 127.0.0.1:6381

錯誤包含key的hash slot和IP:port,客戶端須要從新發出查詢到指定的ip和port,在從新發送前,須要很長一段時間,那麼在這期間,配置文件可能發生了變化,可是目的節點仍然回覆MOVED error。

儘管集羣節點由id來肯定,可是咱們只給客戶端暴漏hash slot和IP:port的對應關係。客戶端儘可能記住,hash slot(3999)和27.0.0.1:6381對應。這樣計算出目標key的hash slot,很是有機會直接找到相應的node。

當集羣穩定,那麼全部客戶端有hash slot和node的對應關係,這樣集羣效率很是高,就不存在重定向代理和單節點故障。

集羣實時從新配置

Redis的集羣支持在羣集運行時添加和刪除節點。實際上添加或刪除一個節點被抽象成相同的操做,即移動hash slot從一個節點到另外一個節點。

若要將新節點添加到集羣中的空節點,即hash slot從現有節點移動到新的節點。

從羣集中刪除一個節點,即分配給該節點的hash slot移動到其餘現有節點。

所以,實施的核心是圍繞移動hash slot。其實從實用的角度出發hash slot僅僅是一組key。所以Redis集羣resharding是keys從一個實例鍵移動到另外一個實例。

要理解這是如何工做,那麼必須知道集羣的slots轉化的子命令。以下:

CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]

CLUSTER DELSLOTS slot1 [slot2] ... [slotN]

CLUSTER SETSLOT slot NODE node

CLUSTER SETSLOT slot MIGRATING node

CLUSTER SETSLOT slot IMPORTING node

前兩個命令ADDSLOTS和DELSLOTS,只是用來分配(或刪除)一個Redis的節點slots。分配後,將使用gossip協議在集羣傳播。該ADDSLOTS命令一般用於一個新的集羣爲全部節點從頭配置slots的一個快速的方式。

SETSLOT子命令用於將slots指定給特定節點的ID,除了該節點的形式被使用。不然,該slot可指定兩個特殊的狀態MIGRATING和IMPORTING:

1)當一個slot被設置爲MIGRATING時,該節點將接受的是關於這個哈希位置查詢的全部請求,但前提是鍵存在。不然查詢使用-ASK重定向目標節點。

2)當一個slot被設置爲IMPORTING,該節點將接受的是關於這個哈希位置查詢的全部請求,但只有請求被前面ASKING。不然,查詢MOVED到真正的hash slot全部者。

起初這看起來很奇怪,但如今咱們會更清楚。假設咱們有兩個Redis的節點,稱爲A和B。咱們想要移動的hash slot8從A到B,因此咱們發出的命令是這樣的:

We send B: CLUSTER SETSLOT 8 IMPORTING A

We send A: CLUSTER SETSLOT 8 MIGRATING B

全部節點都指向A,每次都查詢屬於8的key,會發生:

All the queries about already existing keys are processed by "A".

All the queries about non existing keys in A are processed by "B".

在A就再也不創建新的keys,集羣配置管理工具redis-trib能夠查看:

CLUSTER GETKEYSINSLOT slot count

上述命令將返回該slot中key的個數,從A遷移到B的每個key(是原子的)都會顯示,如:

MIGRATE target_host target_port key target_database id timeout

MIGRATE將鏈接到目標實例,發送鍵的序列化版本,一旦接收到ok,會刪除key的舊數據集。所以在必定時間段,從外部客戶端看來key存在於A或B。

在Redis的集羣沒有必要指定除0之外的數據庫,但MIGRATE可用於不涉及Redis集羣的其餘任務。即便是複雜的key如lists,MIGRATE優化的也很是快。但若是有等待時間約束的應用,在從新配置redis集羣,使用big keys是不明智的。

ASK重定向

在上一節中,咱們簡要地談到了ASK重定向,爲何咱們不能簡單地用MOVED重定向?MOVED重定向意味着hash slot永久在那個節點,下一個查詢應該嘗試對指定的節點,ASK只代表到指定節點查詢。

ASK代表hash slot8下的key仍然在A中,因此咱們老是但願client將嘗試A,若是須要而後B。因爲這種狀況只有hash slot超出16384時發生,性能損失是能夠接受的。

然而,咱們須要強制該客戶端的行爲,因此爲了確保客戶端將只嘗試hash slotB,A嘗試後,節點B就只能接受客戶端發送ASK並被設置爲IMPORTING hash slot的查詢。

對於client,ASK語義以下:

1)若是收到ASK重定向,只把此次查詢發向指定的節點

2)伴隨ASK,開始查詢

3)不更新hash slot 8 到B的映射

若是hash slot 8遷移完成,那麼就會發送MOVED消息,client會永久保存hash slot 8到新IP:port的映射。若是有客戶端提早映射,也是沒有問題的,那麼查詢的時候沒有ASK消息,那麼會發送MOVED消息,重定向到A。

多key操做

使用hash tags操做多key,下面的操做是有有效的:

MSET {user:1000}.name Angela {user:1000}.surname White

當hash slot正在從一個節點移動到另外一個節點,因爲人工resharding,多健操做不可用。

更具體地講,即便在resharding,多鍵操做key全部位於同一節點(源或目的節點),key仍然可用。

在resharding,源和目的分開,多健操做將產生TRYAGAIN error,client在稍後嘗試操做,或彙報錯誤。

容錯

節點心跳和gossip消息

每一秒,一般一個節點將ping幾個隨機節點,這樣ping的數據包的總數量(和接收的pong包     )是一個恆定的量,不管集羣中節點的數量。

可是每一個節點可確保ping通,ping或pong不超過一半NODE_TIMEOUT。前NODE_TIMEOUT已過,節點也嘗試從新與另外一個節點的TCP連接,節點不相信由於當前TCP連接,是不可達的。

信息的交換量大於O(N) ,NODE_TIMEOUT設置爲一個小的數字,但節點的數量(N)是很是大的,由於每一個節點將嘗試ping ,若是配置信息在NODE_TIMEOUT一半的時間沒有更新。

例如,NODE_TIMEOUT設置爲60秒的100個節點集羣,每一個節點會嘗試發送99 ping每30秒,那麼每秒3.3個ping,即乘以100個節點是每秒330個ping。

有一些方法可使用已經經過交換的Redis集羣的gossip信息,以減小交換的消息的數量。例如,咱們能夠ping那些一半NODE_TIMEOUT內「可能的失敗」狀態的節點,而後每秒ping幾個包到那些工做的節點。然而,在現實世界中,設置很是小的NODE_TIMEOUT的大型集羣可靠地工做,將在將來做爲大型集羣實際部署測試。

ping和pong消息內容

ping和pong都包含一個通用的header和一個gossip消息節。

通用的header內容以下:

1)節點ID,在建立節點的時候分配的一個160位的僞隨機數,並在集羣中保持不變。

2)currentEpoch和configEpoch字段,這是爲了安裝Redis集羣的分佈式算法使用。若是節點是一個slave,那麼configEpoch是master最後版本的configEpoch。

3)節點的標誌,代表該節點是slave、master和其餘單位節點的信息。

4)給定節點的hash slot位圖,若是該節點是slave,那麼是master hash slot的位圖。

5)端口:發送方的TCP基本端口(也就是,使用Redis的接受客戶端的命令,加10000,獲得集羣的端口)。

6)狀態:發送者的狀態(down或OK)。

7)主節點的ID,若是是slave。

ping和pong都包含一個gossip節,給接受者提供集羣中其餘節點的信息,只是sender知道的隨機幾個節點的信息。

gossip節中,每一個節點的信息以下:

ID

ip和port

節點狀態

receiver從sender得到其餘節點信息,這在故障檢測和節點發現是很是有用的。

故障檢測

故障檢測用於失敗master或slave不可達,提一個slave爲master,若是失敗,那麼集羣阻止clients的查詢。

每一個節點保存已知節點的狀態列表,包括兩種狀態PFAIL和FAIL,PFAIL意思是可能失敗,不確信。FAIL的意思是,大部分master在固定的時間,肯定是失敗的。

PFAIL flag

若是一個節點在超過NODE_TIMEOUT時間不可到達一個節點,那麼master和slave標誌這個節點爲PFAIL。

不可到達的意思是,ping在通過NODE_TIMEOUT尚未回覆,所以NODE_TIMEOUT必須大於網絡往返的時間。爲了可用性,節點在超過一半NODE_TIMEOUT後,進行重連,這樣一直保持着鏈接,不至於誤報故障。

FAIL flag

PFAIL只是一個節點本地的信息,不足把slave提爲master。認爲一個節點down,那麼必須是FAIL。

每一個節點發送的gossip消息都包含一些隨機節點的狀態,這樣每一個節點都會收到其餘節點的狀態,能夠標誌其餘節點已經檢測到的故障。

遇到如下狀況,就會由PFAIL過分到FAIL:

一些節點標識B爲PFAIL,而且調用A,那麼A收集其餘master對B標識的狀態,在NODE_TIMEOUT * FAIL_REPORT_VALIDITY_MULT時間範圍內,標識爲PFAIL。A將會標識B爲FAIL,發送B的標識FAIL到其餘節點。強制其餘節點標識B爲FAIL。

若是要清除FAIL flag,有如下兩種狀況:

1)一個節點爲slave並能夠到達,那麼FAIL flag被清除。

2)一個節點爲master並能夠到達,沒有hash slot,能夠清除FAIL flag,等待加入集羣。

3)一個節點爲master能夠到達,但很長一段時間(NODE_TIMEOUT* N),沒有檢測到slave能夠提爲master。

但從PFAIL轉化爲FAIL過程當中,使用的協議很是弱:

1)收集其餘節點的意見,由於這一段時間,不能夠肯定狀態是穩定的。

2)當一個節點檢測到FAIL條件,強制其餘節點使用FAIL消息,可是不能夠肯定是否能夠到達全部節點。

然而,Redis的集羣故障檢測具備活躍性要求:最終全部節點即便在分區都應該贊成有關給定節點的狀態。一旦分區癒合,一些少數節點認爲節點是在故障狀態,或相信該節點是不在故障狀態。在這兩種狀況下,最終給定節點的狀態只有一個。

案例1:若是多數masters標記一個節點失敗,那麼其餘節點最終也標誌爲失敗。

案例2:只有少數masters標記一個節點發生故障,slave提爲master失敗,那麼就會清除FAIL flag。

基本上FAIL flag只是爲了提slave爲master算法的安全執行。在理論上slave是獨立運行的,當一個master不可到達時,開始提slave,但實際上,大多master是能夠訪問該master的,這樣PFAIL轉化爲FAIL就太複雜,這樣FAIL消息就能夠強制執行,阻止寫操做,實際上是因爲slave到達不了master引發,不須要slave提爲msater。

Cluster epoch

currentEpoch是一個64位無符號整數,節點新創建時,設置currentEpoch爲0。一個節點收到一個消息,currentEpoch比本地的大,那麼更新本地的currentEpoch。經過這種策略,集羣中節點接受比較大的currentEpoch。在slave升級爲master中起重要做用。

config epoch

每個master,在ping或pong消息中都包含他的configEpoch。當一個新的節點創建時,master的configEpoch設置爲0。

slave選舉時,創建一個新的configEpoch,slave增長Epoch取代失敗的master,獲得大部分masters的認證。若slave認證了,創建一個新的configEpoch,slave就變爲master了。configEpoch有助於解決不一樣節點分散的配置衝突。

slave在ping或pong消息中都包含他的master的configEpoch,這使得其餘實例來檢測一個slave有一箇舊的配置須要被更新。每次configEpoch改變都存儲在nodes conf文件。

目前,當一個節點被從新啓動其currentEpoch被設定爲已知的節點的最大configEpoch 。這是不安全的崩潰恢復系統模型,爲了持久保存currentEpoch,系統將會被修改。

slave選舉和推廣

一個slave在知足如下條件會進行選舉:

1)master處在FAIL狀態

2)master有服務的hash slot

3)slave和master斷開鏈接沒有超過給定的時間,爲了保證slave上的數據有意義

開始選舉前,增長currentEpoch,發送FAILOVER_AUTH_REQUEST消息,等待回包的最大時間爲2倍的NODE_TIMEOUT,一個master回覆了FAILOVER_AUTH_ACK,在2倍的NODE_TIMEOUT時間內,再也不回覆相同master的slave選舉。不能保證安全,可是在同一時間可避免多個slave選舉。

slave忽略currentEpoch小於發送的AUTH_ACK。

若是slave在2倍的NODE_TIMEOUT沒有收到master的回覆,那麼另外一個slave在通過4陪的NODE_TIMEOUT後,從新選舉。

選舉不是在master一處於FAIL狀態就開始的,須要通過DELAY,

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

DELAY爲了使masters知道該master的FAIL狀態。隨機時間,爲了避免同的選舉在不一樣的時間。SLAVE_RANK,最新更新的slave爲0,一次上漲。

若是一個slave成爲master,那麼在ping和pong包中包括服務的hash slot、爲currentEpoch的configEpoch。爲了快速傳播新的配置,能夠廣播pong包。

若是其餘節點檢測到新的master在服務原來的hash slot,那麼更新配置,若是舊的master或slave加入,須要重新master複製配置。

master回覆slave選舉請求

回覆必須知足如下條件:

1)一個給定的epoch只回復一次,不回覆低於lastVoteEpoch的currentEpoch。

2)master處在FAIL狀態

3)小於master currentEpoch的請求被忽略。例如master currentEpoch爲5,lastVoteEpoch爲1,slave currentEpoch爲3,那麼elect currentEpoch爲4,不回覆。slave重試,currentEpoch爲5,那麼認爲是有效的。

4)在兩倍的NODE_TIMEOUT時間內,不回覆相同master的slave選舉。

5)master不嘗試選擇最好的slave。

6)master拒絕支持給定的slave,這個請求被簡單忽略。

7)還不太理解

slave選舉中的競態條件

一個master有A、B、C三個slave,master處在FAIL狀態,A選舉爲master,可是產生了partition,選舉B爲master,隨後B處在FAIL狀態,A也可達了,那麼A和C爭當master,可是C的currentEpoch大,那麼C就做爲master。

服務器slots信息傳播規則

規則一:若是一個節點聲明,沒有hash slots,那麼修改hash slots,關聯到這個節點。

規則二:若是一個節點有hash slots,那麼他廣播的configEpoch大於slot擁有者的configEpoch,那麼新節點重構hash slot。

UPDATE消息

例如特定的hash slot在master A和slave B,一段時間A被partition,B做爲master,隨後A又能夠鏈接,可是他的配置是舊的,沒有節點可複製,這樣UPDATE消息就可起做用。當一個節點檢測到一個廣播的是舊的config,那麼他給這個節點發送一個UPDATE消息,包含這個hash slot的節點ID和這個節點服務的hash slots。

副本遷移算法

觸發的條件是,一個master沒有slave,選擇好的slave,而且ID最小。

configEpoch衝突解決算法

最小ID節點的configEpoch加1.

廣播和訂閱

如今這是節點廣播全部訂閱的消息到其餘全部的節點,後面實現bloomfilter。

http://redis.io/topics/cluster-spec

相關文章
相關標籤/搜索