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代碼??
?
添加副本節點(Adding a new node as a replica)
?
添加一個新副本可以有兩種方式。顯而易見的一種方式是再次使用 redis-trib,但是要使用—slave 選項, 像這樣:
Java代碼??
?注意,這里的命令行完全像我們在添加一個新主服務器時使用的一樣,所以我們沒有指定要給哪個主服 務器添加副本。這種情況下,redis-trib 會添加一個新節點作為一個具有較少副本的隨機的主服務器的副本。
但是,你可以使用下面的命令行精確地指定你想要的主服務器作為副本的目標:
?
Java代碼??
?
移除節點(Removing a node)
?
要移除一個從服務器節點,只要使用 redis-trib 的 del-node 命令就可以:
Java代碼??
??
升級節點(Upgrading nodes in a Redis Cluster)?
?
升級從服務器節點很簡單,因為你只需要停止節點然后用已更新的 Redis 版本重啟。如果有客戶端使用 從服務器節點分離讀請求,它們應該能夠在某個節點不可用時重新連接另一個從服務器。
升級主服務器要稍微復雜一些,建議的步驟是:?
?
1. 使用 CLUSTER FAILOVER 來觸發一次手工故障轉移主服務器(請看本文檔的手工故障轉移小 節)。
2. 等待主服務器變為從服務器。
3. 像升級從服務器那樣升級這個節點。
4. 如果你想讓你剛剛升級的節點成為主服務器,觸發一次新的手工故障轉移,讓升級的節點重新變 回主服務器。
總結
以上是生活随笔為你收集整理的Redis架构及分片管理的全部內容,希望文章能夠幫你解決所遇到的問題。