Redis架構及分片管理
Redis 叢集的 TCP 埠(Redis Cluster TCP ports)
每個 Redis 叢集節點需要兩個 TCP 連線開啟。正常的 TCP 埠用來服務客戶端,例如 6379,加 10000 的埠用作資料埠,在上面的例子中就是 16379。 第二個大一些的埠用於叢集匯流排(bus),也就是使用二進位制協議的點到點通訊通道。叢集匯流排被節點用 於錯誤檢測,配置更新,故障轉移授權等等。客戶端不應該嘗試連線叢集匯流排埠,而應一直與正常的 Redis 命令埠通訊,但是要確保在防火牆中打開了這兩個埠,否則 Redis 叢集的節點不能相互通訊。 命令埠和叢集匯流排埠的偏移量一直固定為 10000。 注意,為了讓 Redis 叢集工作正常,對每個節點: 1. 用於與客戶端通訊的正常的客戶端通訊埠(通常為 6379)需要開放給所有需要連線叢集的客戶端 以及其他叢集節點(使用客戶端埠來進行鍵遷移)。 2. 叢集匯流排埠(客戶端埠加 10000)必須從所有的其他叢集節點可達。 如果你不開啟這兩個 TCP 埠,叢集就無法正常工作。
Redis 叢集的資料分片(Redis Cluster data sharding)
Redis 叢集沒有使用一致性雜湊,而是另外一種不同的分片形式,每個鍵概念上是被我們稱為雜湊槽 (hash slot)的東西的一部分。 Redis 叢集有 16384 個雜湊槽,我們只是使用鍵的 CRC16 編碼對 16384 取模來計算一個指定鍵所屬的 雜湊槽。 每一個 Redis 叢集中的節點都承擔一個雜湊槽的子集,例如,你可能有一個 3 個節點的叢集,其中:
節點 A 包含從 0 到 5500 的雜湊槽。
節點 B 包含從 5501 到 11000 的雜湊槽。
節點 C 包含從 11001 到 16384 的雜湊槽。
這可以讓在叢集中新增和移除節點非常容易。例如,如果我想新增一個新節點 D,我需要從節點 A,B, C 移動一些雜湊槽到節點 D。同樣地,如果我想從叢集中移除節點 A,我只需要移動 A 的雜湊槽到 B 和 C。 當節點 A 變成空的以後,我就可以從叢集中徹底刪除它。 因為從一個節點向另一個節點移動雜湊槽並不需要停止操作,所以新增和移除節點,或者改變節點持有 的雜湊槽百分比,都不需要任何停機時間(downtime)。
Redis cluster 架構(Redis Cluster Architecture)
redis-cluster 架構圖
架構細節:
所有的 redis 節點彼此互聯(PING-PONG 機制),內部使用二進位制協議優化傳輸速度和頻寬.
節點的 fail 是通過叢集中超過半數的節點檢測失效時才生效.
客戶端與 redis 節點直連,不需要中間 proxy 層.客戶端不需要連線叢集所有節點,連線叢集中任何一個 可用節點即可
redis-cluster 把所有的物理節點對映到[0-16383]slot 上,cluster 負責維護 node<->slot<->value
redis-cluster 選舉:容錯
領袖選舉過程是叢集中所有 master 參與,如果半數以上 master 節點與 master 節點通訊超過 (cluster-node-timeout),認為當前 master 節點掛掉.
什麼時候整個叢集不可用(cluster_state:fail)
a:如果叢集任意 master 掛掉,且當前 master 沒有 slave.叢集進入 fail 狀態,也可以理解成叢集的 slot 映 射[0-16383]不完成時進入 fail 狀態. ps : redis-3.0.0.rc1 加入 cluster-require-full-coverage 引數,預設關閉, 開啟叢集相容部分失敗.
b:如果叢集超過半數以上 master 掛掉,無論是否有 slave 叢集進入 fail 狀態.
ps:當叢集不可用時,所有對叢集的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down) 錯誤
Redis 叢集的主從模型(Redis Cluster master-slave model)
為了當部分節點失效時,或者無法與大多數節點通訊時仍能保持可用,Redis 叢集採用每個節點擁有 1(主 服務自身)到 N 個副本(N-1 個附加的從伺服器)的主從模型。 在我們的例子中,叢集擁有 A,B,C 三個節點,如果節點 B 失效叢集將不能繼續服務,因為我們不再 有辦法來服務在 5501-11000 範圍內的雜湊槽。 但是,如果當我們建立集群后(或者稍後),我們為每一個主伺服器新增一個從伺服器,這樣最終的叢集 就由主伺服器 A,B,C 和從伺服器 A1,B1,C1 組成,如果 B 節點失效系統仍能繼續服務。 B1 節點複製 B 節點,於是叢集會選舉 B1 節點作為新的主伺服器,並繼續正確的運轉。
Redis 叢集的一致性保證(Redis Cluster consistency guarantees)
Redis 叢集不保證強一致性。實踐中,這意味著在特定的條件下,Redis 叢集可能會丟掉一些被系統收 到的寫入請求命令。
Redis 叢集為什麼會丟失寫請求的第一個原因,是因為採用了非同步複製。這意味著在寫期間下面的事情 發生了:
你的客戶端向主伺服器 B 寫入。
主伺服器 B 回覆 OK 給你的客戶端。
主伺服器 B 傳播寫入操作到其從伺服器 B1,B2 和 B3。
手動故障轉移(Manual failover)
有時候在主伺服器事實上沒有任何故障的情況下強制一次故障轉移是很有用的。例如,為了升級主服務 器節點中的一個程序,可以對其進行故障轉移使其變為一個從伺服器,這樣最小化了對可用性的影響。
Redis 叢集支援使用 CLUSTER FAILOVER 命令來手動故障轉移,必須在你想進行故障轉移的主服務的 其中一個從伺服器上執行。
手動故障轉移很特別,和真正因為主伺服器失效而產生的故障轉移要更安全,因為採取了避免過程中數 據丟失的方式,僅當系統確認新的主伺服器處理完了舊的主伺服器的複製流時,客戶端才從原主伺服器切 換到新主伺服器。
建立redis叢集(create a new cluser)
redis-trib create --replicas 1 127.0.0.1:6379 127.0.0.1:7379 127.0.0.2:6379 127.0.0.2:7379 127.0.0.3:6379 127.0.0.3:7379 127.0.0.4:6379 127.0.0.4:7379 127.0.0.5:6379 127.0.0.5:7379
檢視redis叢集狀態(check cluser status)
redis-trib check 127.0.0.1:7379
檢視node狀態(check node status)
# redis-cli -c -p 6379
# INFO
新增新節點(Adding a new node)
新增一個新節點的過程基本上就是,新增一個空節點,然後,如果是作為主節點則移動一些資料進去, 如果是從節點則其作為某個節點的副本。
兩種情況我們都會討論,先從新增一個新的主伺服器例項開始。
兩種情況下,第一步要完成的都是新增一個空節點。
我們使用與其他節點相同的配置(埠號除外)在 7006 埠(我們已存在的 6 個節點已經使用了從 7000 到 7005 的埠)上開啟一個新的節點,那麼為了與我們之前的節點佈局一致,你得這麼做:
在你的終端程式中開啟一個新的標籤視窗。
進入 cluster-test 目錄。
建立一個名為 7006 的目錄。
在裡面建立一個 redis.conf 的檔案,類似於其它節點使用的檔案,但是使用 7006 作為埠號。
最後使用../redis-server ./redis.conf 啟動伺服器。
Java程式碼- ./redis-trib.rb add-node 127.0.0.1:7006127.0.0.1:7000
新增副本節點(Adding a new node as a replica)
新增一個新副本可以有兩種方式。顯而易見的一種方式是再次使用 redis-trib,但是要使用—slave 選項, 像這樣:
Java程式碼- ./redis-trib.rb add-node --slave 127.0.0.1:7006127.0.0.1:7000
注意,這裡的命令列完全像我們在新增一個新主伺服器時使用的一樣,所以我們沒有指定要給哪個主服 務器新增副本。這種情況下,redis-trib 會新增一個新節點作為一個具有較少副本的隨機的主伺服器的副本。
但是,你可以使用下面的命令列精確地指定你想要的主伺服器作為副本的目標:
Java程式碼- ./redis-trib.rb add-node --slave --master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.
- 0.0.1:7006127.0.0.1:7000
移除節點(Removing a node)
要移除一個從伺服器節點,只要使用 redis-trib 的 del-node 命令就可以:
Java程式碼- ./redis-trib del-node 127.0.0.1:7000 <node-id>
升級節點(Upgrading nodes in a Redis Cluster)
升級從伺服器節點很簡單,因為你只需要停止節點然後用已更新的 Redis 版本重啟。如果有客戶端使用 從伺服器節點分離讀請求,它們應該能夠在某個節點不可用時重新連線另一個從伺服器。
升級主伺服器要稍微複雜一些,建議的步驟是:
1. 使用 CLUSTER FAILOVER 來觸發一次手工故障轉移主伺服器(請看本文件的手工故障轉移小 節)。
2. 等待主伺服器變為從伺服器。
3. 像升級從伺服器那樣升級這個節點。
4. 如果你想讓你剛剛升級的節點成為主伺服器,觸發一次新的手工故障轉移,讓升級的節點重新變 回主伺服器。
本文主要杜撰自 http://phipray.iteye.com/blog/2233135