您好,登錄后才能下訂單哦!
一個系統(tǒng)建立集群主要需要解決兩個問題:數(shù)據(jù)同步問題和集群容錯問題。
一個簡單粗暴的方案是部署多臺一模一樣的Redis服務(wù),再用負載均衡來分?jǐn)倝毫σ约氨O(jiān)控服務(wù)狀態(tài)。這種方案的優(yōu)勢在于容錯簡單,只要有一臺存活,整個集群就仍然可用。但是它的問題在于保證這些Redis服務(wù)的數(shù)據(jù)一致時,會導(dǎo)致大量數(shù)據(jù)同步操作,反而影響性能和穩(wěn)定性。
Redis集群方案基于分而治之的思想。Redis中數(shù)據(jù)都是以Key-Value形式存儲的,而不同Key的數(shù)據(jù)之間是相互獨立的。因此可以將Key按照某種規(guī)則劃分成多個分區(qū),將不同分區(qū)的數(shù)據(jù)存放在不同的節(jié)點上。這個方案類似數(shù)據(jù)結(jié)構(gòu)中哈希表的結(jié)構(gòu)。在Redis集群的實現(xiàn)中,使用哈希算法(公式是CRC16(Key) mod 16383
)將Key映射到0~16383范圍的整數(shù)。這樣每個整數(shù)對應(yīng)存儲了若干個Key-Value數(shù)據(jù),這樣一個整數(shù)對應(yīng)的抽象存儲稱為一個槽(slot)。每個Redis Cluster的節(jié)點——準(zhǔn)確講是master節(jié)點——負責(zé)一定范圍的槽,所有節(jié)點組成的集群覆蓋了0~16383整個范圍的槽。
據(jù)說任何計算機問題都可以通過增加一個中間層來解決。槽的概念也是這么一層。它介于數(shù)據(jù)和節(jié)點之間,簡化了擴容和收縮操作的難度。數(shù)據(jù)和槽的映射關(guān)系由固定算法完成,不需要維護,節(jié)點只需維護自身和槽的映射關(guān)系。
上面的方案只是解決了性能擴展的問題,集群的故障容錯能力并沒有提升。提高容錯能力的方法一般為使用某種備份/冗余手段。負責(zé)一定數(shù)量的槽的節(jié)點被稱為master節(jié)點。為了增加集群穩(wěn)定性,每個master節(jié)點可以配置若干個備份節(jié)點——稱為slave節(jié)點。Slave節(jié)點一般作為冷備份保存master節(jié)點的數(shù)據(jù),在master節(jié)點宕機時替換master節(jié)點。在一些數(shù)據(jù)訪問壓力比較大的情況下,slave節(jié)點也可以提供讀取數(shù)據(jù)的功能,不過slave節(jié)點的數(shù)據(jù)實時性會略差一下。而寫數(shù)據(jù)的操作則只能通過master節(jié)點進行。
當(dāng)Redis節(jié)點接收到對某個key的命令時,如果這個key對應(yīng)的槽不在自己的負責(zé)范圍內(nèi),則返回MOVED重定向錯誤,通知客戶端到正確的節(jié)點去訪問數(shù)據(jù)。
如果頻繁出現(xiàn)重定向錯誤,勢必會影響訪問的性能。由于從key映射到槽的算法是固定公開的,客戶端可以在內(nèi)部維護槽到節(jié)點的映射關(guān)系,訪問數(shù)據(jù)時可以自己通過key計算出槽,然后找到正確的節(jié)點,減少重定向錯誤。目前大部分開發(fā)語言的Redis客戶端都會實現(xiàn)這個策略。這個地址https://redis.io/clients可以查看主流語言的Redis客戶端。
盡管不同節(jié)點存儲的數(shù)據(jù)相互獨立,這些節(jié)點仍然需要相互通信以同步節(jié)點狀態(tài)信息。Redis集群采用P2P的Gossip協(xié)議,節(jié)點之間不斷地通信交換信息,最終所有節(jié)點的狀態(tài)都會達成一致。常用的Gossip消息有下面幾種:
當(dāng)某個節(jié)點出現(xiàn)問題時,需要一定的傳播時間讓多數(shù)master節(jié)點認(rèn)為該節(jié)點確實不可用,才能標(biāo)記標(biāo)記該節(jié)點真正下線。Redis集群的節(jié)點下線包括兩個環(huán)節(jié):主觀下線(pfail)和客觀下線(fail)。
一個持有槽的master節(jié)點客觀下線后,集群會從slave節(jié)點中選出一個提升為master節(jié)點來替換它。Redis集群使用選舉-投票的算法來挑選slave節(jié)點。一個slave節(jié)點必須獲得包括故障的master節(jié)點在內(nèi)的多數(shù)master節(jié)點的投票后才能被提升為master節(jié)點。假設(shè)集群規(guī)模為3主3從,則必須至少有2個主節(jié)點存活才能執(zhí)行故障恢復(fù)。如果部署時將2個主節(jié)點部署到同一臺服務(wù)器上,則該服務(wù)器不幸宕機后集群無法執(zhí)行故障恢復(fù)。
默認(rèn)情況下,Redis集群如果有master節(jié)點不可用,即有一些槽沒有負責(zé)的節(jié)點,則整個集群不可用。也就是說當(dāng)一個master節(jié)點故障,到故障恢復(fù)的這段時間,整個集群都處于不可用的狀態(tài)。這對于一些業(yè)務(wù)來說是不可忍受的??梢?strong>在配置中將cluster-require-full-coverage配置為no,那么master節(jié)點故障時只會影響訪問它負責(zé)的相關(guān)槽的數(shù)據(jù),不影響對其他節(jié)點的訪問。
修改Redis配置文件以啟動集群模式:
# 開啟集群模式
cluster-enabled yes
# 節(jié)點超時時間,單位毫秒
cluster-node-timeout 15000
# 集群節(jié)點信息文件
cluster-config-file "nodes-6379.conf"
然后啟動新節(jié)點。
使用客戶端發(fā)起命令cluster <ip> <port>
,節(jié)點會發(fā)送meet消息將指定IP和端口的新節(jié)點加入集群。
上一步執(zhí)行完后我們得到的是一個還沒有負責(zé)任何槽的“空”集群。為了使集群可用,我們需要將16384個槽都分配到master節(jié)點數(shù)。
在客戶端執(zhí)行cluster add addslots {<a>...<b>}
命令,將<a>
~<b>
范圍的槽都分配給當(dāng)前客戶端所連接的節(jié)點。將所有的槽都分配給master節(jié)點后,執(zhí)行cluster nodes
命令,查看各個節(jié)點負責(zé)的槽,以及節(jié)點的ID。
接下來還需要分配slave節(jié)點。使用客戶端連接待分配的slave節(jié)點,執(zhí)行cluster replicate <nodeId>
命令,將該節(jié)點分配為<nodeId>
指定的master節(jié)點的備份。
在Redis 5版本中redis-cli
客戶端新增了集群操作命令。
如下所示,直接使用命令創(chuàng)建一個3主3從的集群:
redis-cli --cluster create 127.0.0.1:7000 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 \
--cluster-replicas 1
如果你用的是舊版本的Redis,可以使用官方提供的redis-trib.rb
腳本來創(chuàng)建集群:
./redis-trib.rb create --replicas 1 127.0.0.1:7000 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
擴容操作與創(chuàng)建集群操作類似,不同的在于最后一步是將槽從已有的節(jié)點遷移到新節(jié)點。
redis-cli --cluster add-node
命令將新節(jié)點加入集群(內(nèi)部使用meet消息實現(xiàn))。redis-cli --cluster reshard
進行槽遷移操作。為了安全刪除節(jié)點,Redis集群只能下線沒有負責(zé)槽的節(jié)點。因此如果要下線有負責(zé)槽的master節(jié)點,則需要先將它負責(zé)的槽遷移到其他節(jié)點。
redis-cli --cluster reshard
將待刪除節(jié)點的槽都遷移到其他節(jié)點。redis-cli --cluster del-node
刪除節(jié)點(內(nèi)部使用forget消息實現(xiàn))。如果你的redis-cli版本低于5,那么可以使用redis-trib.rb腳本來完成上面的命令。點擊這里查看redis-cli
和redis-trib.rb
操作集群的命令。
Redis有RDB和AOF兩種持久化策略。
RDB持久化神坑:
save ""
試圖關(guān)閉RDB,然而RDB持久化仍然有可能會觸發(fā)。后果:
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。