【集群】Redis的哨兵模式和集群模式


哨兵模式

哨兵模式是redis高可用的實現方式之一
使用一個或者多個哨兵(Sentinel)實例組成的系統,對redis節點進行監控,在主節點出現故障的情況下,能將從節點中的一個升級為主節點,進行故障轉義,保證系統的可用性。

 

 

哨兵們是怎么感知整個系統中的所有節點(主節點/從節點/哨兵節點)的

  1. 首先主節點的信息是配置在哨兵(Sentinel)的配置文件中
  2. 哨兵節點會和配置的主節點建立起兩條連接命令連接訂閱連接
  3. 哨兵會通過命令連接每10s發送一次INFO命令,通過INFO命令,主節點會返回自己的run_id和自己的從節點信息
  4. 哨兵會對這些從節點也建立兩條連接命令連接訂閱連接
  5. 哨兵通過命令連接向從節點發送INFO命令,獲取到他的一些信息
    a. run_id
    b. role
    c. 從服務器的復制偏移量 offset
    d. 等
  6. 因為哨兵對與集群中的其他節點(主從節點)當前都有兩條連接,命令連接訂閱連接
    a. 通過命令連接向服務器的_sentinel:hello頻道發送一條消息,內容包括自己的ip端口、run_id、配置紀元(后續投票的時候會用到)等
    b. 通過訂閱連接對服務器的_sentinel:hello頻道做了監聽,所以所有的向該頻道發送的哨兵的消息都能被接受到
    c. 解析監聽到的消息,進行分析提取,就可以知道還有那些別的哨兵服務節點也在監聽這些主從節點了,更新結構體將這些哨兵節點記錄下來
    d. 向觀察到的其他的哨兵節點建立命令連接----沒有訂閱連接

哨兵模式下的故障遷移

主觀下線

哨兵(Sentinel)節點會每秒一次的頻率向建立了命令連接的實例發送PING命令,如果在down-after-milliseconds毫秒內沒有做出有效響應包括(PONG/LOADING/MASTERDOWN)以外的響應,哨兵就會將該實例在本結構體中的狀態標記為SRI_S_DOWN主觀下線

客觀下線

當一個哨兵節點發現主節點處於主觀下線狀態是,會向其他的哨兵節點發出詢問,該節點是不是已經主觀下線了。如果超過配置參數quorum個節點認為是主觀下線時,該哨兵節點就會將自己維護的結構體中該主節點標記為SRI_O_DOWN客觀下線
詢問命令SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <run_id>

參數 意義
ip/port 當前認為下線的主節點的ip和端口
current_epoch 配置紀元
run_id *標識僅用於詢問是否下線
有值標識該哨兵節點希望對方將自己設置為leader
詢問時用*,選舉時用run_id
leader選舉

在認為主節點客觀下線的情況下,哨兵節點節點間會發起一次選舉,命令還是上面的命令SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <run_id>,只是run_id這次會將自己的run_id帶進去,希望接受者將自己設置為主節點。如果超過半數以上的節點返回將該節點標記為leader的情況下,會有該leader對故障進行遷移

故障遷移
  1. 在從節點中挑選出新的主節點
    a. 通訊正常
    b. 優先級排序
    c. 優先級相同是選擇offset最大的
  2. 將該節點設置成新的主節點 SLAVEOF no one,並確保在后續的INGO命令時,該節點返回狀態為master
  3. 將其他的從節點設置成從新的主節點復制, SLAVEOF命令
  4. 將舊的主節點變成新的主節點的從節點

優缺點

  • 優點
    高可用,在主節點故障時能實現故障的轉移
  • 缺點:好像沒辦法做到水平拓展,如果內容很大的情況下

集群模式

官方提供的分布式方案(槽指派/重新分片/故障轉移)
集群內的節點,都會有個數據結構存儲整個集群內的節點信息

//整體 struct clusterState{ clusterNode *mySelf; .... dict *nodes; //集群內的所有節點 } // 單個節點 struct clusterNode { char name[]; char ip[]; int port; clusterLink *link; //保存節點間,連接的信息 int flags; //狀態標記 } //節點間連接的信息 struct clusterLink{ mstime_t ctime; //創建時間 int fd; //tcp套接字描述符 sds sndbuf; // 輸出緩存區 sds rcvbuf; //輸入緩存區 struct clusterNode *node; } 

 

槽指派

redis集群可以被分為16384個槽,只有這些槽全被指派了處理的節點的情況下,集群的狀態才能是上線狀態(ok)
操作redis集群的時候,將key作為參數,就可以計算出對應的處理槽上,所以存儲等操作都應該在該槽對應的節點上。通過這種方式,可以完美的實現集群存儲的水平拓展。

def slot_number(key): return CRC16(key) & 16383 //得到的結果就是槽的序號 

槽指派的信息是怎么存儲的

struct clusterState{ clusterNode *slots[16384] } struct clusterNode{ unsigned char slots[16384/8] } 

通過上面兩個結構體中的定義可以看出,槽指派的信息是分了兩種方式,保存在結構體里面。

 



 

 

分兩種存儲的好處
1. 如果需要判斷某一個節點負責的槽,只需要獲取方式二中的數組做判斷就可以
2.如果找某個槽是哪個節點負責,只需要獲取方式一的列表,一查就知道

重新分片

將已經指派給節點的槽,重新執行新的節點。

 


 
 

故障轉移

發現故障節點
  1. 集群內的節點會向其他節點發送PING命令,檢查是否在線
  2. 如果未能在規定時間內做出PONG響應,則會把對應的節點標記為疑似下線
  3. 集群中一半以上負責處理槽的主節點都將主節點X標記為疑似下線的話,那么這個主節點X就會被認為是已下線
  4. 向集群廣播主節點X已下線,大家收到消息后都會把自己維護的結構體里的主節點X標記為已下線
從節點選舉
  1. 當從節點發現自己復制的主節點已下線了,會向集群里面廣播一條消息,要求所有有投票權的節點給自己投票(所有負責處理槽的主節點都有投票權)
  2. 主節點會向第一個給他發選舉消息的從節點回復支持
  3. 當支持數量超過N/2+1的情況下,該從節點當選新的主節點
故障的遷移
  1. 新當選的從節點執行 SLAVEOF no one,修改成主節點
  2. 新的主節點會撤銷所有已下線的老的主節點的槽指派,指派給自己
  3. 新的主節點向集群發送命令,通知其他節點自己已經變成主節點了,負責哪些槽指派
  4. 新的主節點開始處理自己負責的槽的命令

集群模式和哨兵模式的區別

  1. 哨兵模式監控權交給了哨兵系統,集群模式中是工作節點自己做監控
  2. 哨兵模式發起選舉是選舉一個leader哨兵節點來處理故障轉移,集群模式是在從節點中選舉一個新的主節點,來處理故障的轉移



轉自:https://www.jianshu.com/p/d6d2325a5ec7


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM