redis集群扩容和缩容_Full-Stack-Notes
Redis Cluster
一、集群模式介紹
1.1 數據分區
1.2 節點通訊
1.3 請求路由
1.4 故障發現
1.5 故障恢復
二、集群模式搭建
2.1 節點配置
2.2 啟動集群
2.3 集群完整性校驗
2.4 關于版本差異的說明
三、集群伸縮
3.1 集群擴容
3.2 集群縮容
一、集群模式介紹
Redis Cluster 是 Redis 官方提供的分布式實現,在 Redis 3.0 版本正式推出,通過集群模式可以擴展單機的性能瓶頸,同時也可以通過橫向擴展來實現擴容。此外,Redis 集群模式還提供了副本遷移機制,用于保證數據的安全和提高集群的容錯能力,從而實現高可用。
1.1 數據分區
Redis Cluster 采用虛擬槽進行分區,槽是集群內數據管理和遷移的基本單位。所有的鍵根據哈希函數映射到 16384 個整數槽內,每個節點負責維護一部分槽及槽上的數據,計算公式如下:
HASH_SLOT = CRC16(key) mod 16384
假設現在有一個 6 個節點的集群,分別有 3 個 Master 點和 3 個 Slave 節點,槽會盡量均勻的分布在所有 Master 節點上。數據經過散列后存儲在指定的 Master 節點上,之后 Slave 節點會進行對應的復制操作。這里再次說明一下槽只是一個虛擬的概念,并不是數據存放的實際載體。
1.2 節點通訊
在 Redis 分布式架構中,每個節點都存儲有整個集群所有節點的元數據信息,這是通過 P2P 的 Gossip 協議來實現的。集群中的每個節點都會單獨開辟一個 TCP 通道,用于節點之間彼此通信,通信端口號在基礎端口上加 10000;每個節點定期通過特定的規則選擇部分節點發送 ping 消息,接收到 ping 信息的節點用 pong 消息作為響應,通過一段時間的彼此通信,最終所有節點都會達到一致的狀態,每個節點都會知道整個集群全部節點的狀態信息,從而到達集群狀態同步的目的。
1.3 請求路由
1. 請求重定向
在集群模式下,Redis 接收到命令時會先計算鍵對應的槽,然后根據槽找出對應的目標節點,如果目標節點就是此時所在的節點,則直接進行處理,否則返回 MOVED 重定向消息給客戶端,通知客戶端去正確的節點上執行操作。
2. Smart 客戶端
Redis 的大多數客戶端都是 Smart 客戶端, Smart 客戶端會在內部緩存槽與節點之間的映射關系,從而在本機就可以查找到正確的節點,這樣可以保證 IO 效率的最大化。如果客戶端還接收到 MOVED 重定向的消息,則代表客戶端內部的緩存已經失效,此時客戶端會去重新獲取映射關系然后刷新本地緩存。
3. ASK 重定向
當集群處于擴容階段時,此時槽上的數據可能正在從源節點遷移到目標節點,在這個期間可能出現一部分數據在源節點, 而另一部分在目標節點情況。此時如果源節點接收到命令并判斷出鍵對象不存在, 說明其可能存在于目標節點上, 這時會返回給客戶端 ASK 重定向異常。
ASK 重定向與 MOVED 重定向的區別在于:收到 ASK 重定向時說明集群正在進行數據遷移, 客戶端無法知道什么時候遷移完成,因此只是臨時性的重定向, 客戶端不會更新映射緩存。 但是 MOVED 重定向說明鍵對應的槽已經明確遷移到新的節點, 因此需要更新映射緩存。
1.4 故障發現
由于 Redis 集群的節點間都保持著定時通訊,某個節點向另外一個節點發送 ping 消息,如果正常接受到 pong 消息,此時會更新與該節點最后一次的通訊時間記錄,如果之后無法正常接受到 pong 消息,并且判斷當前時間與最后一次通訊的時間超過 cluster-node-timeout ,此時會對該節點做出主觀下線的判斷。
當做出主觀下線判斷后,節點會把這個判斷在集群內傳播,通過 Gossip 消息傳播, 集群內節點不斷收集到故障節點的下線報告。 當半數以上持有槽的主節點都標記某個節點是主觀下線時, 觸發客觀下線流程。 這里需要注意的是只有持有槽主節點才有權利做出主觀下線的判斷,因為集群模式下只有處理槽的主節點才負責讀寫請求和維護槽等關鍵信息, 而從節點只進行主節點數據和狀態信息的復制。
1.5 故障恢復
1. 資格檢查
每個從節點都要檢查最后與主節點斷線時間, 判斷是否有資格替換故障的主節點。 如果從節點與主節點斷線時間超過 cluster-node-time*cluster-slave-validity-factor,則當前從節點不具備故障轉移資格。 這兩個參數可以在 redis.conf 中進行修改,默認值分別為 15000 和 10。
2. 準備選舉
當從節點符合故障轉移資格后, 更新觸發故障選舉的時間, 只有到達該時間后才能執行后續流程。在這一過程中,Redis 會比較每個符合資格的從節點的復制偏移量,然后讓復制偏移量大(即數據更加完整)的節點優先發起選舉。
3. 選舉投票
從節點每次發起投票時都會自增集群的全局配置紀元,全局配置紀元是一個只增不減的整數。之后會在集群內廣播選舉消息,只有持有槽的主節點才會處理故障選舉消息,并且每個持有槽的主節點在一個配置紀元內只有唯一的一張選票。假設集群內有 N 個持有槽的主節點,當某個從節點獲得 N/2+1 張選票則代表選舉成功。如果在開始投票之后的 cluster-node-timeout*2 時間內沒有從節點獲取足夠數量的投票, 則本次選舉作廢,從節點會對配置紀元自增并發起下一輪投票, 直到選舉成功為止。
4. 替換主節點
當從節點收集到足夠的選票之后,就會觸發替換主節點操作:
當前從節點取消復制變為主節點。
執行 clusterDelSlot 操作撤銷原主節點負責的槽, 并執行 clusterAddSlot 把這些槽委派給自己。
向集群廣播自己的 pong 消息,通知集群內的其他節點自己已經成為新的主節點。
二、集群模式搭建
2.1 節點配置
拷貝6份 redis.conf,分別命名為 redis-6479.conf ~ redis-6484.conf,需要修改的配置項如下:
# redis-6479.conf
port 6479
# 以守護進程的方式啟動
daemonize yes
# 當Redis以守護進程方式運行時,Redis會把pid寫入該文件
pidfile /var/run/redis_6479.pid
logfile 6479.log
dbfilename dump-6479.rdb
dir /home/redis/data/
# 開啟集群模式
cluster-enabled yes
# 節點超時時間,單位毫秒
cluster-node-timeout 15000
# 集群內部配置文件
cluster-config-file nodes-6479.conf
# redis-6480.conf
port 6480
daemonize yes
pidfile /var/run/redis_6480.pid
logfile 6480.log
dbfilename dump-6480.rdb
dir /home/redis/data/
cluster-enabled yes
cluster-node-timeout 15000
cluster-config-file nodes-6480.conf
..... 其他配置類似,修改所有用到端口號的地方
2.2 啟動集群
啟動所有 Redis 節點,啟動后使用 ps -ef | grep redis 查看進程,輸出應如下:
接著需要使用以下命令創建集群,集群節點之間會開始進行通訊,并完成槽的分配:
redis-cli --cluster create 127.0.0.1:6479 127.0.0.1:6480 127.0.0.1:6481 \
127.0.0.1:6482 127.0.0.1:6483 127.0.0.1:6484 --cluster-replicas 1
執行后輸出如下:M 開頭的表示持有槽的主節點,S 開頭的表示從節點,每個節點都有一個唯一的 ID。最后一句輸出表示所有的槽都已經分配到主節點上,此時代表集群搭建成功。
2.3 集群完整性校驗
集群完整性指所有的槽都分配到存活的主節點上, 只要16384個槽中有一個沒有分配給節點則表示集群不完整。 可以使用以下命令進行檢測, check 命令只需要給出集群中任意一個節點的地址就可以完成整個集群的檢查工作:
redis-cli --cluster check 127.0.0.1:6479
2.4 關于版本差異的說明
如果你使用的是 Redis 5,可以和上面的示例一樣,直接使用嵌入到 redis-cli 中的 Redis Cluster 命令來創建和管理集群。
如果你使用的是 Redis 3 或 4,則需要使用 redis-trib.rb 工具,此時需要預先準備 Ruby 環境和安裝 redis gem。
三、集群伸縮
Redis 集群提供了靈活的節點擴容和縮容方案,可以在不影響集群對外服務的情況下,進行動態伸縮。
3.1 集群擴容
這里準備兩個新的節點 6485 和 6486,配置和其他節點一致,配置完成后進行啟動。集群擴容的命令為 add-node,第一個參數為需要加入的新節點,第二個參數為集群中任意節點,用于發現集群:
redis-cli --cluster add-node 127.0.0.1:6485 127.0.0.1:6479
成功加入集群后,可以使用 cluster nodes 命令查看集群情況。不做任何特殊指定,默認加入集群的節點都是主節點,但是集群并不會為分配任何槽。如下圖所示,其他 master 節點后面都有對應的槽的位置信息,但新加入的 6485 節點則沒有,由于沒有負責的槽,所以該節點此時不能進行任何讀寫操作:
redis-cli -h 127.0.0.1 -p 6479 cluster nodes
想要讓新加入的節點能夠進行讀寫操作,可以使用 reshard 命令為其分配槽,這里我們將其他三個主節點上的槽遷移一部分到 6485 節點上,這里一共遷移 4096 個槽,即 16384 除以 4 。 cluster-from 用于指明槽的源節點,可以為多個,cluster-to 為槽的目標節點,cluster-slots 為需要遷移的槽的總數:
redis-cli --cluster reshard 127.0.0.1:6479 \
--cluster-from fd35b17ace0f15314ed3b3d4f8ff4da08e11b89d,ebd0425db25b8bcf843fee9826755848e23a895a,98a175734db4a106ae676dc403f39b2783640789 \
--cluster-to 819f867afd1da1acfb1a528d3efa91cffb02ba97 \
--cluster-slots 4096 --cluster-yes
遷移后,再次使用 cluster nodes 命令可以查看到此時 6485 上已經有其他三個主節點上遷移過來的槽:
為保證高可用,可以為新加入的主節點添加從節點,命令如下。add-node 接收兩個參數,第一個為需要添加的從節點,第二個參數為集群內任意節點,用于發現集群。cluster-master-id 參數用于指明作為哪個主節點的從節點,如果不加這個參數,則自動分配給從節點較少的主節點:
redis-cli --cluster add-node 127.0.0.1:6486 127.0.0.1:6479 --cluster-slave \
--cluster-master-id 819f867afd1da1acfb1a528d3efa91cffb02ba97
3.2 集群縮容
集群縮容的命令如下:第一個參數為集群內任意節點,用于發現集群;第二個參數為需要刪除的節點:
redis-cli --cluster del-node 127.0.0.1:6479 ``
需要注意的是待刪除的主節點上必須為空,如果不為空則需要將它上面的槽和數據遷移到其他節點上,和擴容時一樣,可以使用 reshard 命令來完成數據遷移。
參考資料
付磊,張益軍 . 《Redis 開發與運維》. 機械工業出版社 . 2017-3-1
總結
以上是生活随笔為你收集整理的redis集群扩容和缩容_Full-Stack-Notes的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语音 udp最大长度_c语言udp自定
- 下一篇: java 接口 返回值_java api