Memcached 與Redis (3): Redis 的集群與復制

1. Redis 集群

1.1 集群節點

  • 加入集群:
    • 節點使用cluster meet <ip> <port>命令來嘗試握手, 若成功, 則加入到相應的集群中.
  • ClusterNode
    • 節點使用ClusterNode 來記錄自己的狀態, 并為集群中所有其它節點創建相應的clusterNode.
ClusterNode{ ctime, name, flags, configEpoch, ip, port, clusterLink};
ClusterLink{ ctime, fd, sndbuf, rcvbuf, ClusterNode*};
ClusterState{ mySelf, currentEpoch; state, size, dict* nodes}. 
  • flags 記錄著Node 的角色加狀態信息.
  • fd 代表tcp 描述符.
  • sndbuf 和rcvbuf 作為緩沖區 ,保存著從其它Node 發送和接收到的消息.
  • ClusterState 是以該Node 的視角來看, 集群目前所處的狀態.

1.2 slot

  • 以分片的方式來保存DB中的鍵值對, 分為16384個slot.
  • 當所有16384個槽都有節點處理時,集群處理OK上線狀態.否則為fail.
  • 記錄當前Node 被指派的槽信息: clusterNode{ char slots; int numslots};
    • 其中, slots 二進制位為1時代表處理相應數值的槽.
  • 節點會在集群內相互傳播槽指派信息.
    • 記錄著集群中所有槽的指派信息: clusterState{ clusterNode * slots[16384]};.
    • 通過查看state.slots[i] 的值, 即可得到負責處理槽i 的Node.
  • 可以在online 狀態下進行重新分片動作.

1.3 在集群中執行命令

  • 接收命令的Node 會計算出key 屬于那個槽,
    • 當該槽并未被指派給自己時, 會向客戶端返回MOVED 錯誤, 指引客戶端redirect 至正確的Node.
  • 計算key 所屬槽的: slot_number(key) = CRC16(key) & 16383;
  • 集群的客戶端會與多個Node創建?TCP 鏈接, redirect 命令通過轉換TCP 來完成命令的發送.
    • 如果與想要redirect 的節點還未建立TCP 鏈接, 會先建立后再進行轉向.
    • 集群模式下的redis-cli 客戶端會隱藏MOVED 錯誤而自動完成redirect.
    • 而單機模式下的客戶端因為無法進行redirect, 會打印出MOVED錯誤.
  • Node 只能使用0號數據庫, 而單機服務器并無該限制.
    • 記錄槽和鍵的對應關系: clusterState{ zskiplist *slot_to_keys}.

1.4 ASK 錯誤

  • 在重新分片期間, 可能會出現槽的鍵值同時分布在源和目的節點中的情況.
  • 若源節點發現鍵已不在自身上, 則向客戶端返回ASK錯誤, 來指引客戶端轉向正在導入槽的目標節點.

1.5 復制與故障轉移.

  • master 和slave
    • master負責處理槽;
    • slave ?會復制master 的數據, 并在master 下線后, 代替它繼續進行處理.
  • 設置slave節點: cluster replicate <node_id>.
    • 接收者設置自己的clusterNode *slaveof屬性為node_id, 同時修改flags.
    • 此時會開始從master 進行數據復制的動作: slaveof <master_ip> <master_port>.
  • clusterNode{ clusterNode *slaves, numslaves}.
    • 記錄著正在復制該master的slave信息
  • 故障檢測
    • 定期發送PING 消息, 若規定時間內沒有返回, 則將節點標記為probable fail(PFAIL).
    • 若集群中, 若半數以上處理槽的master 都將某節點設置為PFAIL, 則該節點將被標記為FAIL, 同時進行廣播.
  • 故障轉移
    • 如果slave 發現master 已下線, 則開始進行故障轉移.
  • 選舉新的master
    • 集群的配置紀元為自增計數器, 每一次故障轉移會進行自增.
    • 每個處理槽的master 都有一票, 第一個向master 要求投票的slave 將獲得master 的投票.
    • 收集到大于N/2個投票的slave 會成為新的 master.

1.6 消息

  • PING消息.
    • 默認每秒發送一次.
    • 過程: 從已知節點列表中隨機選出五個節點, 對其中的最長時間沒有發送過PING 的節點發送該消息, 來檢測其是否在線.
  • PONG消息.
    • 對MEET 和PING 的響應.
    • 或者用于讓其它節點刷新對自己狀態的認識
      • 如: 故障轉移后新的master.
  • PUBLISH消息.
    • 節點收到后, 會執行該命令, 然后向集群廣播PUBLISH 消息.

2. 復制

復制分為: 初次復制和斷線后復制.

2.1 舊版的實現

  • 同步的實現.
    • master 在收到SYNC 命令后, 從后臺生成RDB 文件, 并使用緩存記錄從現在開始的所有寫操作.
    • slave 接收并載入RDB 文件, 并接收執行緩存中記錄的寫操作.
  • 命令傳播.
    • 在同步過后, master 會將其執行的更新命令發送給master, 說明其已達到一致狀態.
    • 由于執行SYNC 命令非常耗費資源, 所以在斷線后復制時效率不佳.

2.2 新版的實現

  • 完整重同步.
    • 用于初次復制, 步驟等于SYNC.
  • 部分重同步.
    • 處理斷線后重復制.
    • master 只用將斷線期間的更新命令發送給slave, 并讓其執行.
      • master 和slave 各自維護各自的replication offset, 并分別在傳播和接收傳播時加上N.
        • 通過對比offset 的值來得知主從是否處于一致狀態.
    • 復制積壓緩存區.
      • 由master 負責維護的fixed-size 的FIFO 隊列, 默認大小為1MB.
      • 進行命令傳播時, 將命令寫入緩存區.
      • 緩存區同時會為隊列中每個字節記錄相應的offset.
      • 對于斷線重連的slave, 若其offset 之后的數據仍然存在于緩存區, 則使用部分重同步, 否則就需要使用完全重同步.
      • 根據slave 斷線后重連的時長和master 的寫命令頻率來調整緩存區大小.
    • 服務器運行ID.
      • 對于斷線重連的slave, 會將保存的master 的ID發送給重新連接到的master, 若相同,則可以嘗試進行部分重同步.

2.3 心跳檢測

  • replconf ACK <offset>.
  • 用于檢測主從服務器的網絡連接狀態.
  • 輔助實現min-slaves 配置選項, 以防止master 在不安全狀態下執行寫命令.
  • 檢測命令丟失.
    • 當master 發現slave 的offset 小于自己的offset, 會從復制積壓緩存區中找出slave 缺失的數據并進行重發.

3. Sentinel

  • 本質上是運行在特殊模式下的Redis 服務器.
  • sentinel 成為master 的客戶端, 并創建兩個指向master 的異步網絡連接.
    1. 命令連接. 用于向master 發送命令, 并接收命令回復.
    • 訂閱連接. 訂閱master 的sentinel:hello channel.
  • 獲取master 信息.
    • 每隔10秒通過命令連接向master 發送INFO 命令, 然后通過分析返回?獲取master 的狀態.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容