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