Redis Cluster
Redis Cluster是redis的分布式解決方案,在redis 3.0版本推出后有效的解決了reids分布式方面的需求,Redis Cluster的主要特性有:
- 資料進行分片,在每個master上保存一部分資料
- 內置高可用支持,部分master不可用時,仍可提供服務
- 支持N個master節點,每個master node可以掛載多個slave node
- 支持自動選舉機制,在master node故障時,會從slave node中選舉出新的master,并進行切換
- 每個master節點都負責進行資料讀寫操作,每個節點之間會進行通信
Redis Cluster的虛擬槽磁區(hash slot)
虛擬槽磁區是Redis Cluster采用的磁區方式,
- Redis Cluster為我們預設了16384個hash slot(范圍0-16383),每一個hash slot映射一個資料子集,
- 資料子集中的key通過計算CRC16的值,然后對16384取模,來確認對應的hash slot,
- 每個master管理一部分slot,根據master節點的資料平均分配,
- 由于資料保存在slot中,當節點擴容或縮容時,對slot進行重新分配遷移即可,資料不會丟失,
- 分配遷移slot的成本是非常低的(slot的總數只有16384個)
- Redis Cluster的節點之間會共享訊息,每個節點都會知道是哪個節點負責哪個范圍內的slot
節點間的內部通信機制
基礎通信原理
- redis cluster節點間采取gossip協議進行通信
跟集中式不同,不是將集群元資料(節點資訊,故障,等等)集中存盤在某個節點上,
而是互相之間不斷通信,保持整個集群所有節點的資料是完整的
- 集中式:好處在于,元資料的更新和讀取,時效性非常好,一旦元資料出現了變更,
立即就更新到集中式的存盤中,其他節點讀取的時候立即就可以感知到;
不好在于,所有的元資料的更新壓力全部集中在一個地方,可能會導致元資料的存盤有壓力- gossip:好處在于,元資料的更新比較分散,不是集中在一個地方,更新請求會陸陸續續,
打到所有節點上去更新,有一定的延時,降低了壓力; 缺點,元資料更新有延時,可能導致集群的一些操作會有一些滯后
- 10000埠
- 每個節點都有一個專門用于節點間通信的埠,就是自己提供服務的埠號+10000,比如7001,那么用于節點間通信的就是17001埠
- 每個節點每隔一段時間都會往另外幾個節點發送ping訊息,同時其他幾點接收到ping之后回傳pong
- 交換的資訊
故障資訊,節點的增加和移除,hash slot資訊,等
gossip協議
gossip協議包含多種訊息,包括ping,pong,meet,fail
- meet: 某個節點發送meet給新加入的節點,讓新節點加入集群中,然后新節點就會開始與其他節點進行通信
redis-trib.rb add-node
其實內部就是發送了一個gossip meet訊息,給新加入的節點,通知那個節點去加入我們的集群 - ping: 每個節點都會頻繁給其他節點發送ping,其中包含自己的狀態還有自己維護的集群元資料,互相通過ping交換元資料
每個節點每秒都會頻繁發送ping給其他的集群,ping,頻繁的互相之間交換資料,互相進行元資料的更新 - pong: 回傳ping和meet,包含自己的狀態和其他資訊,也可以用于資訊廣播和更新
- fail: 某個節點判斷另一個節點fail之后,就發送fail給其他節點,通知其他節點,指定的節點宕機了
ping訊息
- ping很頻繁,而且要攜帶一些元資料,所以可能會加重網路負擔
每個節點每秒會執行10次ping,每次會選擇5個最久沒有通信的其他節點 - 當然如果發現某個節點通信延時達到了cluster_node_timeout / 2,那么立即發送ping,避免資料交換延時過長,落后的時間太長了
- 比如說,兩個節點之間都10分鐘沒有交換資料了,那么整個集群處于嚴重的元資料不一致的情況,就會有問題
所以cluster_node_timeout可以調節,如果調節比較大,那么會降低發送的頻率 - 每次ping,一個是帶上自己節點的資訊,還有就是帶上1/10其他節點的資訊,發送出去,進行資料交換
至少包含3個其他節點的資訊,最多包含總節點-2個其他節點的資訊
訊息頭
Ping和Pong資料包包含所有型別的資料包(例如,請求故障轉移投票的資料包)通用的訊息頭,
通用訊息頭具有以下資訊:
- 節點ID,在第一次創建節點時分配的160位偽隨機字串,在Redis Cluster節點的整個生命周期中都保持不變
- 節點標志,指示該節點是從節點,主節點還是其他節點資訊
- 發送節點的哈希槽的位圖
- 發送節點的TCP埠
- 發送節點的狀態
- 發送節點的主節點ID(如果它是從節點)
客戶端路由
moved重定向
- 每個節點通過通信都會共享Redis Cluster中槽和集群中對應節點的關系
- 客戶端向Redis Cluster的任意節點發送命令,接收命令的節點會根據CRC16規則進行hash運算與16384取模,計算自己的槽和對應節點
- 如果保存資料的槽被分配給當前節點,則去槽中執行命令,并把命令執行結果回傳給客戶端
- 如果保存資料的槽不在當前節點的管理范圍內,則向客戶端回傳moved重定向例外
- 客戶端接收到節點回傳的結果,如果是moved例外,則從moved例外中獲取目標節點的資訊
- 客戶端向目標節點發送命令,獲取命令執行結果
ask重定向
什么是ask重定向?
在對集群進行擴容和縮容時,需要對槽及槽中資料進行遷移
當客戶端向某個節點發送命令,節點向客戶端回傳moved例外,告訴客戶端資料對應的槽的節點資訊
如果此時正在進行集群擴展或者縮容操作,當客戶端向正在遷移的節點發送命令時,要操作的資料已經被遷移到別的節點了,就會回傳ask,這就是ask重定向機制
步驟:
- 客戶端向目標節點發送命令,目標節點中的槽正在遷移中,此時目標節點會回傳ask重定向給客戶端
- 客戶端接收到ask后,向新的節點發起重定向操作,通過發送Asking命令的方式來操作,
- 新節點執行命令,把命令執行結果回傳給客戶端
- 客戶端接收ask重向后,并不會更新本地映射表(槽和集群中節點的對應關系)
多Key操作(hash tags)
在Redis Cluster中,每個key對應的hash slot都各不相同,資料保存的節點也不盡相同,那么如何做到多個key的批量操作呢?
hash tags就是用來解決這個問題的,使用hash tags可以確保多個key映射到同一個hash slot中,
redis cluster中為了實作hash tags做了些特殊計算,
如果一個鍵包含一個 “{…}” 這樣的模式,只有 { 和 } 之間的字串會被用來做哈希以獲取哈希槽
但是由于可能出現多個 { 或 },算的演算法如下:
- 如果鍵包含一個 { 字符,
- 那么在 { 的右邊就會有一個 },
- 在 { 和 } 之間會有一個或多個字符,第一個 } 一定是出現在第一個 { 之后,
例如:
- abc{hello} yhn{hello}
- {abc}}hello {abc}}nihao
多key操作:
MSET {user:1000}.name Angela {user:1000}.surname White
參考資料:
https://redis.io/topics/cluster-spec
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/273567.html
標籤:NoSQL
