哨兵模式
哨兵模式是redis高可用
的實現(xiàn)方式之一
使用一個或者多個哨兵(Sentinel)實例組成的系統(tǒng)软族,對redis節(jié)點進行監(jiān)控,在主節(jié)點出現(xiàn)故障的情況下立砸,能將從節(jié)點中的一個升級為主節(jié)點,進行故障轉(zhuǎn)義颗祝,保證系統(tǒng)的可用性。
哨兵們是怎么感知整個系統(tǒng)中的所有節(jié)點(主節(jié)點/從節(jié)點/哨兵節(jié)點)的
- 首先主節(jié)點的信息是配置在哨兵(Sentinel)的配置文件中
- 哨兵節(jié)點會和配置的主節(jié)點建立起兩條連接
命令連接
和訂閱連接
- 哨兵會通過
命令連接
每10s發(fā)送一次INFO
命令搁宾,通過INFO命令
盖腿,主節(jié)點會返回自己的run_id和自己的從節(jié)點信息
- 哨兵會對這些從節(jié)點也建立兩條連接
命令連接
和訂閱連接
- 哨兵通過
命令連接
向從節(jié)點發(fā)送INFO
命令,獲取到他的一些信息
a. run_id
b. role
c. 從服務(wù)器的復制偏移量 offset
d. 等 - 因為哨兵對與集群中的其他節(jié)點(主從節(jié)點)當前都有兩條連接鸟款,
命令連接
和訂閱連接
a. 通過命令連接
向服務(wù)器的_sentinel:hello
頻道發(fā)送一條消息茂卦,內(nèi)容包括自己的ip端口、run_id疙筹、配置紀元(后續(xù)投票的時候會用到)等
b. 通過訂閱連接
對服務(wù)器的_sentinel:hello
頻道做了監(jiān)聽而咆,所以所有的向該頻道發(fā)送的哨兵的消息都能被接受到
c. 解析監(jiān)聽到的消息幕袱,進行分析提取,就可以知道還有那些別的哨兵服務(wù)節(jié)點也在監(jiān)聽這些主從節(jié)點了涯捻,更新結(jié)構(gòu)體將這些哨兵節(jié)點記錄下來
d. 向觀察到的其他的哨兵節(jié)點建立命令連接
----沒有訂閱連接
哨兵模式下的故障遷移
主觀下線
哨兵(Sentinel)節(jié)點會每秒一次的頻率向建立了命令連接的實例發(fā)送PING命令障癌,如果在down-after-milliseconds
毫秒內(nèi)沒有做出有效響應(yīng)包括(PONG/LOADING/MASTERDOWN)以外的響應(yīng)辩尊,哨兵就會將該實例在本結(jié)構(gòu)體中的狀態(tài)標記為SRI_S_DOWN
主觀下線
客觀下線
當一個哨兵節(jié)點發(fā)現(xiàn)主節(jié)點處于主觀下線狀態(tài)是摄欲,會向其他的哨兵節(jié)點發(fā)出詢問,該節(jié)點是不是已經(jīng)主觀下線了我注。如果超過配置參數(shù)quorum
個節(jié)點認為是主觀下線時但骨,該哨兵節(jié)點就會將自己維護的結(jié)構(gòu)體中該主節(jié)點標記為SRI_O_DOWN
客觀下線
詢問命令SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <run_id>
參數(shù) | 意義 |
---|---|
ip/port | 當前認為下線的主節(jié)點的ip和端口 |
current_epoch | 配置紀元 |
run_id | *標識僅用于詢問是否下線 有值標識該哨兵節(jié)點希望對方將自己設(shè)置為leader 詢問時用*玻淑,選舉時用run_id
|
leader選舉
在認為主節(jié)點客觀下線
的情況下,哨兵節(jié)點節(jié)點間會發(fā)起一次選舉补履,命令還是上面的命令SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <run_id>
,只是run_id
這次會將自己的run_id
帶進去,希望接受者將自己設(shè)置為主節(jié)點贬蛙。如果超過半數(shù)以上的節(jié)點返回將該節(jié)點標記為leader的情況下,會有該leader對故障進行遷移
故障遷移
- 在從節(jié)點中挑選出新的主節(jié)點
a. 通訊正常
b. 優(yōu)先級排序
c. 優(yōu)先級相同是選擇offset最大的 - 將該節(jié)點設(shè)置成新的主節(jié)點
SLAVEOF no one
,并確保在后續(xù)的INGO命令時氛堕,該節(jié)點返回狀態(tài)為master - 將其他的從節(jié)點設(shè)置成從新的主節(jié)點復制,
SLAVEOF命令
- 將舊的主節(jié)點變成新的主節(jié)點的從節(jié)點
優(yōu)缺點
- 優(yōu)點
高可用野蝇,在主節(jié)點故障時能實現(xiàn)故障的轉(zhuǎn)移 - 缺點:好像沒辦法做到水平拓展绕沈,如果內(nèi)容很大的情況下
集群模式
官方提供的分布式方案(槽指派/重新分片/故障轉(zhuǎn)移)
集群內(nèi)的節(jié)點,都會有個數(shù)據(jù)結(jié)構(gòu)存儲整個集群內(nèi)的節(jié)點信息
//整體
struct clusterState{
clusterNode *mySelf;
....
dict *nodes; //集群內(nèi)的所有節(jié)點
}
// 單個節(jié)點
struct clusterNode {
char name[];
char ip[];
int port;
clusterLink *link; //保存節(jié)點間赠摇,連接的信息
int flags; //狀態(tài)標記
}
//節(jié)點間連接的信息
struct clusterLink{
mstime_t ctime; //創(chuàng)建時間
int fd; //tcp套接字描述符
sds sndbuf; // 輸出緩存區(qū)
sds rcvbuf; //輸入緩存區(qū)
struct clusterNode *node;
}
槽指派
redis集群可以被分為16384個槽藕帜,只有這些槽全被指派了處理的節(jié)點的情況下惜傲,集群的狀態(tài)才能是上線狀態(tài)(ok)
操作redis集群的時候,將key作為參數(shù)收津,就可以計算出對應(yīng)的處理槽上浊伙,所以存儲等操作都應(yīng)該在該槽對應(yīng)的節(jié)點上嚣鄙。通過這種方式,可以完美的實現(xiàn)集群存儲的水平拓展哑子。
def slot_number(key):
return CRC16(key) & 16383
//得到的結(jié)果就是槽的序號
槽指派的信息是怎么存儲的
struct clusterState{
clusterNode *slots[16384]
}
struct clusterNode{
unsigned char slots[16384/8]
}
通過上面兩個結(jié)構(gòu)體中的定義可以看出卧蜓,槽指派的信息是分了兩種方式,保存在結(jié)構(gòu)體里面榨惠。
分兩種存儲的好處
1. 如果需要判斷某一個節(jié)點負責的槽赠橙,只需要獲取方式二中的數(shù)組做判斷就可以
2.如果找某個槽是哪個節(jié)點負責期揪,只需要獲取方式一的列表,一查就知道
重新分片
將已經(jīng)指派給節(jié)點的槽姓建,重新執(zhí)行新的節(jié)點缤苫。
故障轉(zhuǎn)移
發(fā)現(xiàn)故障節(jié)點
- 集群內(nèi)的節(jié)點會向其他節(jié)點發(fā)送PING命令榨馁,檢查是否在線
- 如果未能在規(guī)定時間內(nèi)做出PONG響應(yīng)翼虫,則會把對應(yīng)的節(jié)點標記為疑似下線
- 集群中一半以上
負責處理槽的主節(jié)點
都將主節(jié)點X標記為疑似下線的話屡萤,那么這個主節(jié)點X就會被認為是已下線
- 向集群廣播主節(jié)點X
已下線
,大家收到消息后都會把自己維護的結(jié)構(gòu)體里的主節(jié)點X標記為已下線
從節(jié)點選舉
- 當從節(jié)點發(fā)現(xiàn)自己復制的主節(jié)點已下線了,會向集群里面廣播一條消息招拙,要求所有有投票權(quán)的節(jié)點給自己投票(
所有負責處理槽的主節(jié)點都有投票權(quán)
) - 主節(jié)點會向第一個給他發(fā)選舉消息的從節(jié)點回復支持
- 當支持數(shù)量超過N/2+1的情況下别凤,該從節(jié)點當選新的主節(jié)點
故障的遷移
- 新當選的從節(jié)點執(zhí)行
SLAVEOF no one
,修改成主節(jié)點 - 新的主節(jié)點會撤銷所有已下線的老的主節(jié)點的槽指派领虹,指派給自己
- 新的主節(jié)點向集群發(fā)送命令塌衰,通知其他節(jié)點自己已經(jīng)變成主節(jié)點了,負責哪些槽指派
- 新的主節(jié)點開始處理自己負責的槽的命令
集群模式和哨兵模式的區(qū)別
- 哨兵模式監(jiān)控權(quán)交給了哨兵系統(tǒng)最疆,集群模式中是工作節(jié)點自己做監(jiān)控
- 哨兵模式發(fā)起選舉是選舉一個leader哨兵節(jié)點來處理故障轉(zhuǎn)移努酸,集群模式是在從節(jié)點中選舉一個新的主節(jié)點,來處理故障的轉(zhuǎn)移