發(fā)送命令
在上一篇文章中,已經(jīng)將16384個(gè)槽都進(jìn)行了指派之后,集群已經(jīng)進(jìn)入上線狀態(tài)
127.0.0.1:7000> cluster info
// 集群狀態(tài):OK表示上線
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3
cluster_size:3
cluster_current_epoch:3
cluster_my_epoch:1
···
現(xiàn)在客戶端就可以向集群中的節(jié)點(diǎn)發(fā)送命令了。
當(dāng)客戶端向節(jié)點(diǎn)發(fā)送與數(shù)據(jù)庫(kù)鍵有關(guān)的命令時(shí)回铛,接收命令的節(jié)點(diǎn)會(huì)計(jì)算出命令要處理的數(shù)據(jù)庫(kù)鍵屬于哪個(gè)槽,并檢查這個(gè)槽是否指派給了自己:
- 如果鍵所在的槽剛好指派給當(dāng)前節(jié)點(diǎn)克锣,那么節(jié)點(diǎn)就回直接執(zhí)行這個(gè)命令茵肃。
- 如果不在當(dāng)前節(jié)點(diǎn),那么節(jié)點(diǎn)會(huì)向客戶端返回一個(gè)MOVED錯(cuò)誤袭祟,指引客戶端轉(zhuǎn)向(redirect)至正確的節(jié)點(diǎn)验残,并再次發(fā)送之前想要執(zhí)行的命令。
計(jì)算鍵屬于哪個(gè)槽
CLUSTER KEYSLOT <key>
127.0.0.1:7000> cluster keyslot "date"
(integer) 2022
說明"date"鍵會(huì)分配在2022這個(gè)槽巾乳。
當(dāng)節(jié)點(diǎn)計(jì)算出鍵所屬的槽i后您没,節(jié)點(diǎn)就回檢查自己在clusterState.slots數(shù)組中的項(xiàng)i,判斷鍵是否由自己負(fù)責(zé)胆绊。
MOVED錯(cuò)誤
當(dāng)節(jié)點(diǎn)發(fā)現(xiàn)鍵所在的槽并非自己負(fù)責(zé)處理的時(shí)候氨鹏,節(jié)點(diǎn)就會(huì)向客戶端返回一個(gè)MOVED錯(cuò)誤,指引客戶端轉(zhuǎn)向至正在負(fù)責(zé)槽的節(jié)點(diǎn)压状。
節(jié)點(diǎn)數(shù)據(jù)庫(kù)的實(shí)現(xiàn)
集群節(jié)點(diǎn)保存鍵值對(duì)以及鍵值對(duì)過期時(shí)間的方式與單機(jī)Redis服務(wù)器一樣仆抵,它們兩者只有一個(gè)區(qū)別,節(jié)點(diǎn)只能使用0號(hào)數(shù)據(jù)庫(kù),而單機(jī)Redis服務(wù)器沒有這一限制镣丑。
重新分片
Redis集群的重新分片操作可以將任意數(shù)量已經(jīng)指派給某個(gè)節(jié)點(diǎn)(源節(jié)點(diǎn))的槽改為指派給另一個(gè)節(jié)點(diǎn)(目標(biāo)節(jié)點(diǎn))舔糖,并且相關(guān)槽所屬的鍵值對(duì)也會(huì)從源節(jié)點(diǎn)被移動(dòng)到目標(biāo)節(jié)點(diǎn)。
在重新分片過程莺匠,集群不需要下線金吗,并且源節(jié)點(diǎn)和目標(biāo)節(jié)點(diǎn)都可以繼續(xù)進(jìn)行命令請(qǐng)求。
這時(shí)需要Redis的集群管理軟件redis-trib負(fù)責(zé)執(zhí)行慨蛙,Redis提供了進(jìn)行重新分片所需的所有命令,而redis-trib則通過向源節(jié)點(diǎn)和目標(biāo)節(jié)點(diǎn)發(fā)送命令來(lái)進(jìn)行重新分片操作纪挎。
[圖片上傳失敗...(image-e2a2ef-1534470023589)]
ASK錯(cuò)誤
在進(jìn)行重新分片過程中期贫,源節(jié)點(diǎn)向目標(biāo)節(jié)點(diǎn)遷移一個(gè)槽的過程中,可能會(huì)出現(xiàn)這種情況:屬于被遷移槽的一部分鍵值對(duì)保存在源節(jié)點(diǎn)里面异袄,而另一部分鍵值對(duì)則保存在目標(biāo)節(jié)點(diǎn)里面通砍。
當(dāng)客戶端向源節(jié)點(diǎn)發(fā)送一個(gè)與數(shù)據(jù)庫(kù)鍵有關(guān)的命令,并且命令要處理的數(shù)據(jù)庫(kù)鍵就在正在被遷移的槽時(shí):
- 源節(jié)點(diǎn)會(huì)先在自己的數(shù)據(jù)庫(kù)里面查找指定的鍵烤蜕,如果找到就回執(zhí)行命令
- 相反地封孙,沒有找到,這個(gè)鍵可能被遷移到目標(biāo)節(jié)點(diǎn)讽营,源節(jié)點(diǎn)將想客戶端返回一個(gè)ASK錯(cuò)誤虎忌,指引客戶端轉(zhuǎn)向正在導(dǎo)入槽的目標(biāo)節(jié)點(diǎn),并再次發(fā)送之前想要執(zhí)行的命令橱鹏。
ASK錯(cuò)誤和MOVED錯(cuò)誤的區(qū)別:
MOVED錯(cuò)誤代表槽的負(fù)責(zé)權(quán)已經(jīng)從一個(gè)節(jié)點(diǎn)轉(zhuǎn)移到了另一個(gè)節(jié)點(diǎn):在客戶端收到關(guān)于槽i的MOVED錯(cuò)誤之后膜蠢,客戶端每次遇到關(guān)于槽i的命令請(qǐng)求時(shí),都可以直接將命令請(qǐng)求發(fā)送至MOVED錯(cuò)誤所指向的節(jié)點(diǎn)莉兰,因?yàn)樵摴?jié)點(diǎn)就是目前負(fù)責(zé)槽i的節(jié)點(diǎn)挑围。
ASK錯(cuò)誤只是兩個(gè)節(jié)點(diǎn)在遷移槽的過程中使用的一種臨時(shí)措施:在客戶端收到槽i的ASK錯(cuò)誤之后,客戶端只會(huì)在接下來(lái)的一次命令請(qǐng)求中將關(guān)于槽i的命令請(qǐng)求發(fā)送至ASK錯(cuò)誤所指示的節(jié)點(diǎn)糖荒,但這種轉(zhuǎn)向不會(huì)對(duì)客戶端今后發(fā)送關(guān)于槽i的命令請(qǐng)求產(chǎn)生任何影響杉辙,客戶端仍然會(huì)將關(guān)于槽i的命令請(qǐng)求發(fā)送至目前負(fù)責(zé)處理槽i的節(jié)點(diǎn),除非ASK錯(cuò)誤再次出現(xiàn)
復(fù)制與故障轉(zhuǎn)移
Redis集群中的節(jié)點(diǎn)分為主節(jié)點(diǎn)(Master)和從節(jié)點(diǎn)(slave)捶朵,其中主節(jié)點(diǎn)負(fù)責(zé)處理槽蜘矢,而從節(jié)點(diǎn)則用于負(fù)責(zé)某個(gè)主節(jié)點(diǎn),并在被復(fù)制的主節(jié)點(diǎn)下線時(shí)综看,代替下線主節(jié)點(diǎn)繼續(xù)處理命令請(qǐng)求硼端。
個(gè)人感覺與單機(jī)版時(shí)的主從配置很相似,多了一步寓搬,就是主節(jié)點(diǎn)掛了之后珍昨,從節(jié)點(diǎn)繼承負(fù)責(zé)處理槽的職責(zé)。
集群中設(shè)置從節(jié)點(diǎn)
CLUSTER REPLICATE <node_id>
可以讓接收命令的節(jié)點(diǎn)成為node_id所指定節(jié)點(diǎn)的從節(jié)點(diǎn),并開始對(duì)主機(jī)進(jìn)行復(fù)制镣典。
故障檢測(cè)
集群中每個(gè)節(jié)點(diǎn)都會(huì)定期地想幾區(qū)中的其他節(jié)點(diǎn)發(fā)送PING消息兔毙,以此來(lái)檢測(cè)對(duì)方是否在線,如果接收PING消息的節(jié)點(diǎn)沒有在規(guī)定時(shí)間內(nèi)回復(fù)PONG消息兄春,那么發(fā)送PING消息的節(jié)點(diǎn)就會(huì)將接收PING消息的節(jié)點(diǎn)標(biāo)記為疑似下線(probable fail, PFAIL)澎剥。
在一個(gè)集群中,超過半數(shù)以上負(fù)責(zé)處理槽的主節(jié)點(diǎn)都將這個(gè)主節(jié)點(diǎn)x報(bào)告為疑似下線赶舆,那么這個(gè)主節(jié)點(diǎn)x將被標(biāo)記為以下線(FAIL)哑姚,并向集群廣播一條關(guān)于主節(jié)點(diǎn)x的FAIL消息。
故障轉(zhuǎn)移
主節(jié)點(diǎn)下線后芜茵,從節(jié)點(diǎn)將開始對(duì)下線主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移叙量,有以下幾個(gè)步驟:
- 從從節(jié)點(diǎn)中選出新的主節(jié)點(diǎn)
- 被選中的從節(jié)點(diǎn)會(huì)執(zhí)行SLAVEOF no one命令,成為新的主節(jié)點(diǎn)
- 新的主節(jié)點(diǎn)會(huì)撤銷所有對(duì)已下線主節(jié)點(diǎn)的槽指派九串,并將這些槽全部指派給自己
- 新的主節(jié)點(diǎn)像集群廣播PONG消息绞佩,讓其它節(jié)點(diǎn)了解這個(gè)節(jié)點(diǎn)已經(jīng)成為新的主節(jié)點(diǎn),接管原本已下線節(jié)點(diǎn)負(fù)責(zé)處理的槽
- 新的主節(jié)點(diǎn)開始接受和自己負(fù)責(zé)處理的槽有關(guān)的命令請(qǐng)求猪钮,故障轉(zhuǎn)移完成品山。
小結(jié):Redis集群的坑只填了一點(diǎn),還有關(guān)于Redis消息的沒填烤低,這個(gè)先留著吧肘交,先去寫論文。之后開始擼NIO還是SPRING呢扑馁,日常糾結(jié)??