前面我們介紹了主從復(fù)制的方式和sentinel方式,這里我們看第三種模式-Cluster方式。
目錄
1.前兩種集群模式的特征與不足
2.Cluster模式
2.1 Cluster模式原理
?2.2 數(shù)據(jù)分片與槽位
2.3 Cluster模式配置和實現(xiàn)
3.一致性Hash
3.1 哈希后取模
3.2 一致性Hash算法
4 Redis Cluster集群
1.前兩種集群模式的特征與不足
主從復(fù)制是Redis的一種基本集群模式,它通過將一個Redis節(jié)點(主節(jié)點)的數(shù)據(jù)復(fù)制到一個或多個其他Redis節(jié)點(從節(jié)點)來實現(xiàn)數(shù)據(jù)的冗余和備份。主節(jié)點負責(zé)處理客戶端的寫操作,同時從節(jié)點會實時同步主節(jié)點的數(shù)據(jù)??蛻舳丝梢詮膹墓?jié)點讀取數(shù)據(jù),實現(xiàn)讀寫分離,提高系統(tǒng)性能。
主從復(fù)制模式適用于以下場景:
- 數(shù)據(jù)備份和容災(zāi)恢復(fù):通過從節(jié)點備份主節(jié)點的數(shù)據(jù),實現(xiàn)數(shù)據(jù)冗余。
- 讀寫分離:將讀操作分發(fā)到從節(jié)點,減輕主節(jié)點壓力,提高系統(tǒng)性能。
- 在線升級和擴展:在不影響主節(jié)點的情況下,通過增加從節(jié)點來擴展系統(tǒng)的讀取能力。
由此可見,主從復(fù)制模式適合數(shù)據(jù)備份、讀寫分離和在線升級等場景,但在主節(jié)點故障時需要手動切換,不能自動實現(xiàn)故障轉(zhuǎn)移。如果對高可用性要求較高,可以考慮使用哨兵模式或Cluster模式。
哨兵模式是在主從復(fù)制基礎(chǔ)上加入了哨兵節(jié)點,實現(xiàn)了自動故障轉(zhuǎn)移。哨兵節(jié)點是一種特殊的Redis節(jié)點,它會監(jiān)控主節(jié)點和從節(jié)點的運行狀態(tài)。當(dāng)主節(jié)點發(fā)生故障時,哨兵節(jié)點會自動從從節(jié)點中選舉出一個新的主節(jié)點,并通知其他從節(jié)點和客戶端,實現(xiàn)故障轉(zhuǎn)移。
此時的系統(tǒng)結(jié)構(gòu)如下所示,也就說哨兵模式可以增強主備模式的功能,:
哨兵模式適用于以下場景:
- 高可用性要求較高的場景:通過自動故障轉(zhuǎn)移,確保服務(wù)的持續(xù)可用。
- 數(shù)據(jù)備份和容災(zāi)恢復(fù):在主從復(fù)制的基礎(chǔ)上,提供自動故障轉(zhuǎn)移功能。
由此可見,哨兵模式在主從復(fù)制模式的基礎(chǔ)上實現(xiàn)了自動故障轉(zhuǎn)移,提高了系統(tǒng)的高可用性。然而,它仍然無法實現(xiàn)數(shù)據(jù)分片。如果需要實現(xiàn)數(shù)據(jù)分片和負載均衡,可以考慮使用Cluster模式。
2.Cluster模式
2.1 Cluster模式原理
Cluster模式是Redis的一種高級集群模式,它通過數(shù)據(jù)分片和分布式存儲實現(xiàn)了負載均衡和高可用性。在Cluster模式下,Redis將所有的鍵值對數(shù)據(jù)分散在多個節(jié)點上。每個節(jié)點負責(zé)一部分?jǐn)?shù)據(jù),稱為槽位。通過對數(shù)據(jù)的分片,Cluster模式可以突破單節(jié)點的內(nèi)存限制,實現(xiàn)更大規(guī)模的數(shù)據(jù)存儲。
這里,有個問題,如果我們來了多個請求怎么判斷該發(fā)送到哪個機器呢?這就是數(shù)據(jù)分片與槽位的問題。
?2.2 數(shù)據(jù)分片與槽位
這里我們先說結(jié)論,后面再解釋。
Redis Cluster將數(shù)據(jù)分為16384個槽位,每個節(jié)點負責(zé)管理一部分槽位。當(dāng)客戶端向Redis Cluster發(fā)送請求時,Cluster會根據(jù)鍵的哈希值將請求路由到相應(yīng)的節(jié)點。具體來說,Redis Cluster使用CRC16算法計算鍵的哈希值,然后對16384取模,得到槽位編號。
2.3 Cluster模式配置和實現(xiàn)
配置Redis節(jié)點:為每個節(jié)點創(chuàng)建一個redis.conf配置文件,并添加如下配置:
# cluster節(jié)點端口號
port 7001
# 開啟集群模式
cluster-enabled yes
# 節(jié)點超時時間
cluster-node-timeout 15000
像這樣的配置,一共需要創(chuàng)建6個,我們做一個三主三從的集群。
啟動Redis節(jié)點:使用如下命令啟動6個節(jié)點:
redis-server redis_7001.conf
創(chuàng)建Redis Cluster:使用Redis命令行工具執(zhí)行如下命令創(chuàng)建Cluster:
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
cluster-replicas?表示從節(jié)點的數(shù)量,1代表每個主節(jié)點都有一個從節(jié)點。
驗證Cluster模式:向Cluster發(fā)送請求,觀察請求是否正確路由到相應(yīng)的節(jié)點。
這樣我們就搭建了一個基本的Cluster集群了。
通過上面的方式,可以看到,這種方式需要客戶端自己來配置所有的機器,有些復(fù)雜,一些復(fù)雜的操作可能也會受到限制,但是這種方式配置明確,在中等類型的互聯(lián)網(wǎng)公司這么做都是可以的。
以下內(nèi)容摘自咕泡青山老師的課堂講義。
3.一致性Hash
如果客戶端去連接redis服務(wù)器的時候會有個問題,此時客戶端該如何選擇呢?也就是該如何進行分庫分表的分片策略呢?另外就是這段邏輯該由誰來做呢?
如下圖所示:
關(guān)于分片,我們可以有三種方案:
- 第一種,是在客戶端實現(xiàn)相關(guān)的邏輯,如用取?;蛘咭恢滦怨ey進行分片,查詢和修改都先判斷key的路由。
- 第二章,是把做分片處理的邏輯抽取出來,運行在一個獨立的代理服務(wù)器上,客戶端連接到這個dialing服務(wù),然后再轉(zhuǎn)發(fā)。
- 第三種就是服務(wù)端只有一個統(tǒng)一的對外接口,服務(wù)器之間自己實現(xiàn)分片策略。
第二種就是花錢消災(zāi)的方式,我們重點討論另外兩種。
以下內(nèi)容摘自青山老師的講義,內(nèi)容挺好,懷念一下青山老師。
我們前面介紹的客戶端Jedis客戶端中,支持分片功能,它是SpringBoot2版本之前默認(rèn)的Redis客戶端,RedisTempate就是對Jedis的封裝。
Jedis有多種連接池,其中一種是支持分片的。代碼示例如下:
public static void main(String[] args) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
JedisShardInfo shardInfo1 = new JedisShardInfo("127.0.0.1", 6379);
JedisShardInfo shardInfo2 = new JedisShardInfo("127.0.0.1", 6389);
List<JedisShardInfo> infoList = Arrays.asList(shardInfo1, shardInfo2);
ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, infoList);
ShardedJedis jedis = null;
try {
jedis = shardedJedisPool.getResource();
for (int i = 0; i < 100; i++) {
jedis.set("shard" + i, i + "");
}
for (int i = 0; i < 100; i++) {
System.out.println(jedis.get("shard" + i));
}
} catch (Exception exception) {
System.out.println(exception);
if (jedis != null) {
jedis.close();
}
}
}
通過dbsize命令發(fā)自按,一個機器有44個key,一臺機器有56個,大致是一半一半。
3.1 哈希后取模
ShardJedis是怎么做到的呢?如果是希望數(shù)據(jù)分布相對均勻的話,我們首先可以考慮哈希后取模。之所以先Hash,是因為key不一定是整數(shù),可能是字符串或者其他信息,同時為了使數(shù)據(jù)分布更均勻,所以先計算哈希比較好。
例如,hash(key)%N,根據(jù)余數(shù),決定映射到哪個結(jié)點。這種方式比較簡單,屬于靜態(tài)分片的方式,缺點也很明顯,一旦節(jié)點發(fā)生數(shù)量變化,或者某個hash被換了,此時取模N就會發(fā)生變化,數(shù)據(jù)就要重新分布。為了解決這個問題,我們又有了一致性Hash算法。ShardedJedis實際上使用的就是一致性哈希算法。
3.2 一致性Hash算法
一致性哈希的基本原理是:把所有的哈希值空間組織成一個虛擬的圓環(huán)(哈希環(huán)),整個空間按照順時針方向組織,其中0和最高位2^32-1是重疊的。
假設(shè)我們有四臺機器要哈希環(huán)來實現(xiàn)映射(分布數(shù)據(jù)),我們先根據(jù)機器的名稱或者ip計算哈希值,然后分布到環(huán)中,也就是圖中紅色標(biāo)記。
現(xiàn)在有4條數(shù)據(jù)或者4個訪問請求,對key計算后,得到哈希環(huán)中的位置(綠色位置)。沿哈希環(huán)順時針找到的一個Node,就是數(shù)據(jù)存儲的結(jié)點。
在這種情況下,新增一個Node5結(jié)點 ,只影響一部分?jǐn)?shù)據(jù)的分布,如下:
如果我們刪除一個結(jié)點Node4,只影響相鄰的一個結(jié)點。
一致性哈希解決了動態(tài)增減結(jié)點時,所有數(shù)據(jù)都需要重新分布的問題,它只會影響到下一個相鄰的結(jié)點,對其他結(jié)點沒有影響。
但是這樣的一致性哈希有一個缺點,因為結(jié)點不一定是均勻分布的,特別是在節(jié)點數(shù)比較少的情況下,所以數(shù)據(jù)不能得到均勻分布。解決這個問題的辦法是引入虛擬結(jié)點
比如,2個節(jié)點,5條數(shù)據(jù) ,只有1條分布到Node2,4條分布到Node1,不均勻。
Node1設(shè)置了兩個虛擬結(jié)點,Node2也設(shè)置了兩個兩個虛擬結(jié)點(虛線圓圈),這時候有3條數(shù)據(jù)分不到Node1,1條分布到Node2.
一致性Hash在分布式系統(tǒng)中很多場景都有應(yīng)用,例如負載均衡、分庫分表等等,是一個非常重要的基礎(chǔ)算法。
4 Redis Cluster集群
Redis Cluster也是用來解決分布式的需求,同時也可以實現(xiàn)高可用。在CLuster中,各個結(jié)點是去中心化的,客戶端可以連接到任一個節(jié)點上。
對于這種方式 ,我們有幾個問題需要思考,例如:
- 數(shù)據(jù)怎么相對均勻的分布地分片
- 客戶端怎么訪問到相應(yīng)的結(jié)點和數(shù)據(jù)
- 重新分片的過程,怎么保證正常服務(wù)。
我們來討論一下。對于一個Redis Cluster 集群,例如一個三主三從的結(jié)構(gòu),節(jié)點之間兩兩交互,共享數(shù)據(jù)分片、節(jié)點狀態(tài)等信息。此時的結(jié)構(gòu)是這樣的:
Redis沒有使用哈希取模,也沒有用一致性哈希,而是用虛擬槽來實現(xiàn)的。Redis創(chuàng)建了16384個槽,每個節(jié)點負責(zé)一定區(qū)間的slot,比如Node1負責(zé)0~5460,Node1負責(zé)5461~10922,Node3負責(zé)10923~~16383。
對象分不到Redis節(jié)點上時,對key采用crc16算法計算再與16384取模,得到一個slot的值,數(shù)據(jù)落到負責(zé)這個slot的redis節(jié)點上。
Redis的每個master節(jié)點都會維護自己負責(zé)的slot。用一個bit序列實現(xiàn),例如,序列的第0位是1,就代表第一個slot是它負責(zé),序列的第1位是0,代表第二個slot不歸它負責(zé)。
在這里key與slot的關(guān)系是永遠不會變的,變的只有slot和redis節(jié)點的關(guān)系。
問題:客戶端該連接到某一臺服務(wù)器,但是訪問的數(shù)據(jù)不在該節(jié)點上怎么辦?
這時候redis采取了一個非常簡單,但是比較笨的方式:根據(jù)新的規(guī)則算出數(shù)據(jù)遷移到里了,然后將地址返回給客戶端,讓客戶端重新去對應(yīng)的機器上連。
也就是這種情況下,客戶端需要連接兩次。不過Jedis等客戶端一般會在本地維護一份slot-node的關(guān)系,一般是不需要重定向的。文章來源:http://www.zghlxwxcb.cn/news/detail-815398.html
以上內(nèi)容大部分參考自青山老師的講義,在此表示感謝。文章來源地址http://www.zghlxwxcb.cn/news/detail-815398.html
到了這里,關(guān)于【征服redis14】認(rèn)真理解一致性Hash與Redis的三種集群的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!