高可用redis簡單解析和Docker搭建

項目已經在github上傳,歡迎指教。redis-cluster-dockergit

首先先把基礎概念內容相對理一遍:github

哨兵

1.基本概念

在這邊先對幾個名詞進行說明:redis

名詞 邏輯結構 物理結構
主節點(master) Redis主服務/數據庫 一個獨立的redis進程
從節點(slave) Redis從服務/數據庫 一個獨立的redis進程
Redis數據節點 主節點和從節點 主節點和從節點的進程
Sentinel節點 監控Redis數據節點 一個獨立的Sentinel節點進程
Sentinel節點集合 若干Sentinel節點的抽象組合 若干Sentinel節點進程
Redis Sentinel Redis高可用實現方案 Sentinel節點集合和Redis數據節點進程
應用方 泛指一個或多個客戶端 一個或者多個客戶端進程或者線程

Red Sentinel是Redis的高可用實現方案。算法

1.1.主從複製的問題

Redis的主從複製模式能夠將主節點的數據改變同步給從節點,這樣從節點就能夠起到兩個做用:第一,做爲主節點的一個備份,一旦主節點出了故障不可達的狀況,從節點能夠做爲後備頂上來,而且保證數據儘可能不丟失(主從複製是最終一致性)。第二,從節點能夠擴展主節點的讀能力。docker

1.2.高可用

Redis主從複製模式下,一旦主節點出現了故障不可達,就須要Redis Sentinel自動完成發現和故障轉移,而且通知應用方,從而實現真正的高可用。shell

Redis Sentinel是一個分佈式架構,其中包括若干個Sentinel節點和Redis數據節點,每一個Sentinel節點會對數據節點和其他Sentinel節點進行監控,當他發現節點不可達時,會對節點作下線標識。若是被標誌的是主節點,它還會和其餘Sentinel節點進行「協商」,當大多數Sentinel節點都認爲主節點不可達時候,它們回選舉出一個Sentinel節點來完成自動故障轉移的工做,同時會將這個變化實時通知給Redis應用方。整個過程是徹底自動的,不須要人工來介入。數據庫

所以,能夠總結Redis Sentinel具備如下幾個功能:bash

  • 監控:Sentinel節點會按期檢測Redis數據節點,其他Sentinel節點是否可達。
  • 通知:Sentinel節點會將故障轉移的結果通知給應用方。
  • 主節點故障轉移:實現從節點晉升爲主節點並維護後續正確的主從關係。
  • 配置提供者:在Redis Sentinel結構中,客戶端在初始化的時候鏈接的是Sentinel節點集合,從中獲取主節點信息。

同時看到,Redis Sentinel包含若干個Sentinel節點,這樣作也帶來了兩個好處:服務器

  • 對於節點的故障判斷是由多個Sentinel節點共同完成的,這樣能夠有效地防止誤判。
  • Sentinel節點集合是由若干Sentinel節點組成的,這樣即便個別Sentinel節點不可用,整個Sentinel節點集合依然是健壯的。

注意,Sentinel節點自己就是獨立的Redis節點,只不過它們有一點特殊,它們不存儲任何數據,只支持部分命令。網絡

2.實現原理

Redis Sentinel的基本實現原理,具體包含如下幾個方面:

  1. Redis Sentinel的三個定時任務
  2. 主觀下線和客觀下線
  3. Sentinel領導選舉
  4. 故障轉移。

2.1.三個定時任務

1.每隔10s,每一個Sentinel節點會向主節點和從節點發送info命令獲取最新的拓撲結構。如:

# Replication
role:master
connected_salves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=4917,lag=1
slave1:ip=127.0.0.1,port=6380,state=online,offset=4917,lag=1
複製代碼

Sentinel節點經過對上述結果進行解析就能夠找到相應的從節點。具體表如今:

  • 經過向主節點執行info命令,獲取從節點的信息,這也是爲何Sentinel節點不須要顯示配置監控從節點。
  • 當有新的從節點加入時均可以馬上感知出來。
  • 節點不可達或者故障轉移後,能夠經過info命令實時更新節點拓撲信息。
  1. 每隔2秒,每一個Sentinel節點會向Redis數據節點的**__sentinel__:hello**頻道上發送該節點對於主節點的判斷以及當前Sentinel節點的信息,同時每隔Sentinel節點也會訂閱該頻道,來了解其餘Sentinel節點以及他們對主節點的判斷,因此這個定時任務能夠完成如下兩個工做:
    • 發現新的Sentinel節點
    • Sentinel節點以前交換主節點的狀態(做爲後面客觀下線以及領導者選舉的依據)
  2. 每隔1秒,每一個Sentinel節點會向主節點,從節點,其他Sentinel節點發送一條ping命令作心跳檢測,來確認當前節點是否可達。

簡單總結:

1)每隔10秒,會向主從節點發送info獲取拓撲信息。2)每隔2秒,向*__sentinel__:hello頻道發送對主節點判斷和當前Sentinel信息,也就是本身的彙報結果。3)每隔1秒,向其他全部**節點發送ping,保持聯繫。*

2.2.主觀下線和客觀下線

  1. 主觀下線:就像前面說的第三個定時任務,每一個Sentinel節點每隔1s對主、從節點、其餘Sentinel節點發送ping作心跳檢測。當這些節點超過配置的時長沒有收到有效的恢復,Sentinel節點就會對該節點作失敗斷定,這個行爲叫作主觀下線。

    能夠看出是一家之言,有誤判的可能。

  2. 客觀下線:當Sentinel主觀下線的節點是主節點時,該Sentinel節點會經過Sentinel is-master-down-by-addr命令向其餘Sentinel節點詢問對主節點的判斷,當超過個數,Sentinel節點認爲主節點確實有問題,這時候Sentinel會作出客觀下線的決定,這樣客觀下線的含義是比較明顯了。

上面指的是對主節點客觀下線的,注意,從節點、Sentinel節點在主觀下線後,沒有後續的故障轉移操做。

2.4.領導者Sentinel節點選舉

故障轉移的工做只須要一個Sentinel節點來完成便可,因此Sentinel節點之間會作一個領導者選舉的工做,選一個Sentinel節點做爲領導者進行故障轉移的工做。而採用的就是Raft算法。這邊講解一下Redis Sentinel進行領導者選舉的大體思路:

  1. 每一個Sentinel節點都有資格成爲領導者。按照前面所說的:當他確認主節點主觀下線時候,會向其餘Sentinel節點發送Sentinel is-master-down-by-addr命令,這條的做用,也有要求將本身設置爲領導者。
  2. 收到命令的Sentinel節點,若是沒有贊成過其餘Sentinel節點的Sentinel is-master-down-by-addr命令,將贊成該請求,不然拒絕。
  3. 若是該Sentinel節點發現本身的票數已經大於等於max(quorum,num(sentinels)/2+1)。那麼它將成爲領導。
  4. 若是此過程沒有選舉出領導者,將進行下一次選舉。

**簡單來講:**在客觀下線確認的同時,就會請求當領導者的贊成。

超過半數Sentinel節點贊成,或者配置時候的贊成下線人數贊成。

2.5.故障轉移

從剛剛選舉出的領導者Sentinel節點,他來進行故障轉移:

  1. 在從節點列表中選出一個節點做爲新的主節點,選擇方法以下:

    • 過濾不健康的(在心跳檢測等等鏈接中表現很差的)
    • 儘可能選擇(有的話)salve-priority(從節點優先級)最高的從節點列表。
  2. 對第一部選出來的從節點執行slaveof no one命令讓它成爲主節點。

  3. Sentinel領導者節點會向剩餘的從節點發送命令,讓它們成爲新主節點的從節點,複製規則和parallel-syncs參數有關。

    也就是用來限制在一次故障轉移以後,每次向新的主節點發起復制操做的從節點個數。(避免對主節點形成過分網絡和磁盤IO的開銷)

  4. Sentinel節點集合會將原理的主節點更新爲從節點,並保持着對其關注,當其恢復後命令它去複製新的主節點。

    原主節點在從新上線後會被要求去複製新的主節點。也就是說,Sentinel節點依然會對這些下線節點進行按期監控,這是Redis Sentinel設計思路決定的。

前提:本試驗環境已經提早安裝了docker和docker-compose

說明:本次部署是單機僞集羣,想要部署真正的集羣,修改ip地址拆分配置到各個主機上部署便可。

部署

這邊先說一些部署技巧:

部署至少3個且奇數個的Sentinel節點:

  1. 3個以上是經過Sentinel節點的個數提升對於故障判定的準確性,由於領導者選舉須要至少通常加1個的節點,奇數個節點能夠在知足該條件的基礎上節省一個節點。詳情見前面說起的概念內容。
  2. Sentinel節點集合能夠只監控一個主節點,也能夠監控多個主節點。

項目分紅兩個目錄,一個是redis目錄。主要存放redis主從節點的docke-compose文件。

  1. 在redis文件夾下建立redis目錄,主要是爲了持久化redis。(RDB和AOF路徑同樣)

  2. 在同文件夾下新建 docker-compose.yml文件。

    ├── data
    │   ├── master
    │   ├── slave1
    │   └── slave2
    └── docker-compose.yml
    複製代碼
  3. 這邊簡單說重要的配置項:

    ...
     container_name: redis-master
    ...
     volumes:
     - ./data/master:/data
     command: redis-server --port 6379 --requirepass 123
        
     ...
     container_name: redis-slave-1
    ...
     volumes:
     - ./data/slave1:/data
     command: redis-server --slaveof 192.168.0.107 6379 --port 6380 --requirepass 1234 --masterauth 123
        
    複製代碼

    須要配置好對應驗證密碼和容器命以便從節點鏈接主節點。注意從節點鏈接不能用127.0.0.1鏈接上主服務器。這個的緣由就是redis主服務器綁定了127.0.0.1,那麼跨服務器IP的訪問就會失敗,從服務器用IP和端口訪問主的時候,主服務器發現本機6379端口綁在了127.0.0.1上,也就是隻能本機才能訪問,外部請求會被過濾。這邊我修改成ifconfig獲取的網卡地址,若是是線上生產環境建議綁定IP地址。

接下來是在跟目錄下創建文件夾sentinel:

  1. 在文件夾下創建配置文件夾conf。對於3個配置文件:slave1.conf,slave2.conf,slave3.conf內容相同:
sentinel monitor mymaster 192.168.0.107 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster 1234
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
複製代碼
  1. 在文件夾下新建docker-compose.yml。如今sentinel文件夾結構以下:

    ├── conf
    │   ├── sentinel1.conf
    │   ├── sentinel2.conf
    │   └── sentinel3.conf
    └── docker-compose.yml
    複製代碼
  2. 配置項重點是如下2條(注意配置文件每次成功運行後會自動更新一些節點信息):

    #自定義集羣名,其中 192.168.8.188 爲 redis-master 的 ip,6379 爲 redis-master 的端口,2 爲最小投票數(由於有 3 臺 Sentinel 因此能夠設置成 2)
    sentinel monitor mymaster 192.168.8.188 6379 2
    # 每一個Sentinel節點都要經過按期發送ping命令來判斷redis數據節點和其他Sentinel節點是否可達,超過down-after-milliseconds即爲不可達。
    sentinel down-after-milliseconds mymaster 30000
    複製代碼
相關文章
相關標籤/搜索