redis cluster集群模式总结
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
Redis集群介紹
Redis 集群是一個提供在多個Redis間節(jié)點間共享數(shù)據(jù)的程序集。
Redis集群并不支持處理多個keys的命令,因為這需要在不同的節(jié)點間移動數(shù)據(jù),從而達不到像Redis那樣的性能,在高負載的情況下可能會導致不可預料的錯誤.
Redis 集群通過分區(qū)來提供一定程度的可用性,在實際環(huán)境中當某個節(jié)點宕機或者不可達的情況下繼續(xù)處理命令. Redis 集群的優(yōu)勢:
- 自動分割數(shù)據(jù)到不同的節(jié)點上。
- 整個集群的部分節(jié)點失敗或者不可達的情況下能夠繼續(xù)處理命令。
Redis 集群的數(shù)據(jù)分片
Redis 集群沒有使用一致性hash, 而是引入了?哈希槽的概念.
Redis 集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽.集群的每個節(jié)點負責一部分hash槽,舉個例子,比如當前集群有3個節(jié)點,那么:
- 節(jié)點 A 包含 0 到 5500號哈希槽.
- 節(jié)點 B 包含5501 到 11000 號哈希槽.
- 節(jié)點 C 包含11001 到 16384號哈希槽.
這種結(jié)構(gòu)很容易添加或者刪除節(jié)點. 比如如果我想新添加個節(jié)點D, 我需要從節(jié)點 A, B, C中得部分槽到D上. 如果我想移除節(jié)點A,需要將A中的槽移到B和C節(jié)點上,然后將沒有任何槽的A節(jié)點從集群中移除即可. 由于從一個節(jié)點將哈希槽移動到另一個節(jié)點并不會停止服務,所以無論添加刪除或者改變某個節(jié)點的哈希槽的數(shù)量都不會造成集群不可用的狀態(tài).
Redis 集群的主從復制模型
為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節(jié)點都會有N-1個復制品.
在我們例子中具有A,B,C三個節(jié)點的集群,在沒有復制模型的情況下,如果節(jié)點B失敗了,那么整個集群就會以為缺少5501-11000這個范圍的槽而不可用.
然而如果在集群創(chuàng)建的時候(或者過一段時間)我們?yōu)槊總€節(jié)點添加一個從節(jié)點A1,B1,C1,那么整個集群便有三個master節(jié)點和三個slave節(jié)點組成,這樣在節(jié)點B失敗后,集群便會選舉B1為新的主節(jié)點繼續(xù)服務,整個集群便不會因為槽找不到而不可用了
不過當B和B1 都失敗后,集群是不可用的.
Redis 一致性保證
Redis 并不能保證數(shù)據(jù)的強一致性. 這意味這在實際中集群在特定的條件下可能會丟失寫操作.
第一個原因是因為集群是用了異步復制. 寫操作過程:
- 客戶端向主節(jié)點B寫入一條命令.
- 主節(jié)點B向客戶端回復命令狀態(tài).
- 主節(jié)點將寫操作復制給他得從節(jié)點 B1, B2 和 B3.
主節(jié)點對命令的復制工作發(fā)生在返回命令回復之后, 因為如果每次處理命令請求都需要等待復制操作完成的話, 那么主節(jié)點處理命令請求的速度將極大地降低 —— 我們必須在性能和一致性之間做出權(quán)衡。 注意:Redis 集群可能會在將來提供同步寫的方法。 Redis 集群另外一種可能會丟失命令的情況是集群出現(xiàn)了網(wǎng)絡分區(qū), 并且一個客戶端與至少包括一個主節(jié)點在內(nèi)的少數(shù)實例被孤立。
舉個例子 假設集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六個節(jié)點, 其中 A 、B 、C 為主節(jié)點, A1 、B1 、C1 為A,B,C的從節(jié)點, 還有一個客戶端 Z1 假設集群中發(fā)生網(wǎng)絡分區(qū),那么集群可能會分為兩方,大部分的一方包含節(jié)點 A 、C 、A1 、B1 和 C1 ,小部分的一方則包含節(jié)點 B 和客戶端 Z1 .
Z1仍然能夠向主節(jié)點B中寫入, 如果網(wǎng)絡分區(qū)發(fā)生時間較短,那么集群將會繼續(xù)正常運作,如果分區(qū)的時間足夠讓大部分的一方將B1選舉為新的master,那么Z1寫入B中得數(shù)據(jù)便丟失了.
注意, 在網(wǎng)絡分裂出現(xiàn)期間, 客戶端 Z1 可以向主節(jié)點 B 發(fā)送寫命令的最大時間是有限制的, 這一時間限制稱為節(jié)點超時時間(node timeout), 是 Redis 集群的一個重要的配置選項:
?
集群在線重配置(live reconfiguration)-動態(tài)新增、刪除節(jié)點數(shù)據(jù)一致性保障
Redis 集群支持在集群運行過程中添加或移除節(jié)點。實際上,添加或移除節(jié)點都被抽象為同一個操作,那就是把哈希槽從一個節(jié)點移到另一個節(jié)點。
- 向集群添加一個新節(jié)點,就是把一個空節(jié)點加入到集群中并把某些哈希槽從已存在的節(jié)點移到新節(jié)點上。
- 從集群中移除一個節(jié)點,就是把該節(jié)點上的哈希槽移到其他已存在的節(jié)點上。
- 所以實現(xiàn)這個的核心是能把哈希槽移來移去。從實際角度看,哈希槽就只是一堆鍵,所以 Redis 集群在重組碎片(reshard)時做的就是把鍵從一個節(jié)點移到另一個節(jié)點。
為了理解這是怎么工作的,我們需要介紹 CLUSTER 的子命令,這些命令是用來操作 Redis 集群節(jié)點上的哈希槽轉(zhuǎn)換表(slots translation table)。
以下是可用的子命令:
- CLUSTER ADDSLOTS?slot1 [slot2] … [slotN]
- CLUSTER DELSLOTS?slot1 [slot2] … [slotN]
- CLUSTER SETSLOT?slot NODE node
- CLUSTER SETSLOT?slot MIGRATING node
- CLUSTER SETSLOT?slot IMPORTING node
- 頭兩個命令,ADDSLOTS 和 DELSLOTS,就是簡單地用來給一個 Redis 節(jié)點指派(assign)或移除哈希槽。 在哈希槽被指派后,節(jié)點會將這個消息通過 gossip 協(xié)議向整個集群傳播。ADDSLOTS 命令通常是用于在一個集群剛建立的時候快速給所有節(jié)點指派哈希槽。
當 SETSLOT 子命令使用 NODE 形式的時候,用來給指定 ID 的節(jié)點指派哈希槽。 除此之外哈希槽能通過兩個特殊的狀態(tài)來設定,MIGRATING 和 IMPORTING:
- 當一個槽被設置為 MIGRATING,原來持有該哈希槽的節(jié)點仍會接受所有跟這個哈希槽有關的請求,但只有當查詢的鍵還存在原節(jié)點時,原節(jié)點會處理該請求,否則這個查詢會通過一個 -ASK 重定向(-ASK redirection)轉(zhuǎn)發(fā)到遷移的目標節(jié)點。
- 當一個槽被設置為 IMPORTING,只有在接受到 ASKING 命令之后節(jié)點才會接受所有查詢這個哈希槽的請求。如果客戶端一直沒有發(fā)送 ASKING 命令,那么查詢都會通過 -MOVED 重定向錯誤轉(zhuǎn)發(fā)到真正處理這個哈希槽的節(jié)點那里。
這么講可能顯得有點奇怪,現(xiàn)在我們用實例讓它更清晰些。假設我們有兩個 Redis 節(jié)點,稱為 A 和 B。我們想要把哈希槽 8 從 節(jié)點A 移到 節(jié)點B,所以我們發(fā)送了這樣的命令:
- 我們向 節(jié)點B 發(fā)送:CLUSTER SETSLOT 8 IMPORTING A
- 我們向 節(jié)點A 發(fā)送:CLUSTER SETSLOT 8 MIGRATING B
其他所有節(jié)點在每次被詢問到的一個鍵是屬于哈希槽 8 的時候,都會把客戶端引向節(jié)點”A”。具體如下:
- 所有關于已存在的鍵的查詢都由節(jié)點”A”處理。
- 所有關于不存在于節(jié)點 A 的鍵都由節(jié)點”B”處理。
這種方式讓我們可以不用在節(jié)點 A 中創(chuàng)建新的鍵。同時,一個叫做 redis-trib 的特殊客戶端,它也是 Redis 集群的配置程序(configuration utility),會確保把已存在的鍵從節(jié)點 A 移到節(jié)點 B。這通過以下命令實現(xiàn):
CLUSTER GETKEYSINSLOT slot count上面這個命令會返回指定的哈希槽中 count 個鍵。對于每個返回的鍵,redis-trib 向節(jié)點 A 發(fā)送一個?MIGRATE?命令,這樣會以原子性的方式(在移動鍵的過程中兩個節(jié)點都被鎖住,以免出現(xiàn)競爭狀況)把指定的鍵從節(jié)點 A 移到節(jié)點 B。以下是?MIGRATE?的工作原理:
MIGRATE target_host target_port key target_database id timeout執(zhí)行 MIGRATE 命令的節(jié)點會連接到目標節(jié)點,把序列化后的 key 發(fā)送過去,一旦收到 OK 回復就會從它自己的數(shù)據(jù)集中刪除老的 key。所以從一個外部客戶端看來,在某個時間點,一個 key 要不就存在于節(jié)點 A 中要不就存在于節(jié)點 B 中。
在 Redis 集群中,不需要指定一個除了 0 號之外的數(shù)據(jù)庫,但?MIGRATE?命令能用于其他跟 Redis 集群無關的的任務,所以它是一個足夠通用的命令。MIGRATE?命令被優(yōu)化了,使得即使在移動像長列表這樣的復雜鍵仍然能做到快速。 不過當在重配置一個擁有很多鍵且鍵的數(shù)據(jù)量都很大的集群的時候,這個過程就并不那么好了,對于使用數(shù)據(jù)庫的應用程序來說就會有延時這個限制。
參數(shù)文檔:http://www.redis.cn/topics/cluster-spec.html、http://www.redis.cn/topics/cluster-tutorial.html
轉(zhuǎn)載于:https://my.oschina.net/u/3070368/blog/3056537
總結(jié)
以上是生活随笔為你收集整理的redis cluster集群模式总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL 8.0 技术详解
- 下一篇: 5分钟学会如何创建spring boot