什麼叫系統不可用:node
什麼是99.99高可用性:正則表達式
高可用計算規則,整年 系統可用的時間 / 整年redis
redis不可用是什麼?算法
redis主從基於哨兵模式的高可用:安全
哨兵的主要功能:服務器
(1)集羣監控,負責監控redis master和slave進程是否正常正常工做架構
(2)消息通知,若是某個redis實例有故障,那麼哨兵負責發送消息做爲報警通知給管理員異步
(3)故障遷移,若是master node掛掉了,會自動轉移到slave node 上ide
(4) 配置中心,若是故障發生了,通知client客戶端新的master地址測試
哨兵的核心知識:
(1) 哨兵至少須要 3 個實例,保證本身的健壯性
(2) 哨兵 + redis,是不會保證數據零丟失的,只能保證redis集羣的高可用
(3) 哨兵 + redis ,這種複製的架構,儘可能多作容災演練
爲何哨兵最少要三臺?:
2臺的 majority = 2, (reids 服務器發生問題以後,須要兩臺都贊成,才能執行遷移操做)
3 臺的 majority = 2, (兩臺哨兵贊成便可)
4 臺的 majority = 2, (兩臺哨兵贊成便可))
5 臺的 majority = 3 (三臺哨兵贊成便可))
若是哨兵只有兩天,呢麼其中一臺發生問題,即時檢查到了redis master發生問題,也不能執行redis遷移(必需要兩臺都贊成遷移,才能夠遷移)
redis哨兵主備切換的數據丟失問題:
1)異步複製:
2) 集羣腦裂
解決異步複製和腦裂致使的數據丟失(redis.conf文件中配置):
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有一個slave,複製和同步數據的延遲不能超過10秒
若是說一旦全部的slave,數據複製和同步延遲都超過了10秒,這時候master將不會接收任何寫請求
redis哨兵核心底層原理:
1.sdown 和 odown
sdown和odown兩種失敗狀態
sdown是主觀宕機,就一個哨兵若是本身以爲一個master宕機了,那麼就是主觀宕機
odown是客觀宕機,若是quorum數量的哨兵都以爲一個master宕機了,那麼就是客觀宕機
sdown達成的條件很簡單,若是一個哨兵ping一個master,超過了is-master-down-after-milliseconds指定的毫秒數以後,就主觀認爲master宕機
sdown到odown轉換的條件很簡單,若是一個哨兵在指定時間內,收到了quorum指定數量的其餘哨兵也認爲那個master是sdown了,那麼就認爲是odown了,客觀認爲master宕機
2.哨兵集羣的自動發現機制
哨兵互相之間的發現,是經過redis的pub/sub系統實現的,每一個哨兵都會往__sentinel__:hello這個channel裏發送一個消息,這時候全部其餘哨兵均可以消費到這個消息,並感知到其餘的哨兵的存在
每隔兩秒鐘,每一個哨兵都會往本身監控的某個master+slaves對應的__sentinel__:hello channel裏發送一個消息,內容是本身的host、ip和runid還有對這個master的監控配置
每一個哨兵也會去監聽本身監控的每一個master+slaves對應的__sentinel__:hello channel,而後去感知到一樣在監聽這個master+slaves的其餘哨兵的存在
每一個哨兵還會跟其餘哨兵交換對master的監控配置,互相進行監控配置的同步
3.slave配置的自動糾正
哨兵會負責自動糾正slave的一些配置,好比slave若是要成爲潛在的master候選人,哨兵會確保slave在複製現有master的數據; 若是slave鏈接到了一個錯誤的master上,好比故障轉移以後,那麼哨兵會確保它們鏈接到正確的master上
哨兵會自動更改redis的配置文件
4.slave->master選舉算法
若是一個master被認爲odown了,並且majority哨兵都容許了主備切換,那麼某個哨兵就會執行主備切換操做,此時首先要選舉一個slave來
會考慮slave的一些信息
(1)跟master斷開鏈接的時長
(2)slave優先級
(3)複製offset
(4)run id
若是一個slave跟master斷開鏈接已經超過了down-after-milliseconds的10倍,外加master宕機的時長,那麼slave就被認爲不適合選舉爲master
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下來會對slave進行排序:
(1)按照slave優先級進行排序,slave priority越低,優先級就越高
(2)若是slave priority相同,那麼看replica offset,哪一個slave複製了越多的數據,offset越靠後,優先級就越高
(3)若是上面兩個條件都相同,那麼選擇一個run id比較小的那個slave
5.quorum和majority
每次一個哨兵要作主備切換,首先須要quorum數量的哨兵認爲odown,而後選舉出一個哨兵來作切換,這個哨兵還得獲得majority哨兵的受權,才能正式執行切換
若是quorum < majority,好比5個哨兵,majority就是3,quorum設置爲2,那麼就3個哨兵受權就能夠執行切換
可是若是quorum >= majority,那麼必須quorum數量的哨兵都受權,好比5個哨兵,quorum是5,那麼必須5個哨兵都贊成受權,才能執行切換
6.configuration epoch
哨兵會對一套redis master+slave進行監控,有相應的監控的配置
執行切換的那個哨兵,會從要切換到的新master(salve->master)那裏獲得一個configuration epoch,這就是一個version號,每次切換的version號都必須是惟一的
若是第一個選舉出的哨兵切換失敗了,那麼其餘哨兵,會等待failover-timeout時間,而後接替繼續執行切換,此時會從新獲取一個新的configuration epoch,做爲新的version號
7.configuraiton傳播
哨兵完成切換以後,會在本身本地更新生成最新的master配置,而後同步給其餘的哨兵,就是經過以前說的pub/sub消息機制
這裏以前的version號就很重要了,由於各類消息都是經過一個channel去發佈和監聽的,因此一個哨兵完成一次新的切換以後,新的master配置是跟着新的version號的
其餘的哨兵都是根據版本號的大小來更新本身的master配置的
配置哨兵模式(主從狀態監控)
1. Redis Sentinel搭建
1.1. Redis Sentinel的部署須知
1. 一個穩健的 Redis Sentinel 集羣,應該使用至少 三個 Sentinel 實例,而且保證講這些實例放到 不一樣的機器 上,甚至不一樣的 物理區域。
2. Sentinel 沒法保證 強一致性。
3. 常見的 客戶端應用庫 都支持 Sentinel。
4. Sentinel 須要經過不斷的 測試 和 觀察,才能保證高可用。
1.2. Redis Sentinel的配置文件
# 哨兵sentinel實例運行的端口,默認26379 port 26379 # 哨兵sentinel的工做目錄 dir ./ # 哨兵sentinel監控的redis主節點的 ## ip:主機ip地址 ## port:哨兵端口號 ## master-name:能夠本身命名的主節點名字(只能由字母A-z、數字0-9 、這三個字符".-_"組成。) ## quorum:當這些quorum個數sentinel哨兵認爲master主節點失聯 那麼這時 客觀上認爲主節點失聯了 # sentinel monitor <master-name> <ip> <redis-port> <quorum> sentinel monitor mymaster 127.0.0.1 6379 2 # 當在Redis實例中開啓了requirepass <foobared>,全部鏈接Redis實例的客戶端都要提供密碼。 # sentinel auth-pass <master-name> <password> sentinel auth-pass mymaster 123456 # 指定主節點應答哨兵sentinel的最大時間間隔,超過這個時間,哨兵主觀上認爲主節點下線,默認30秒 # sentinel down-after-milliseconds <master-name> <milliseconds> sentinel down-after-milliseconds mymaster 30000 # 指定了在發生failover主備切換時,最多能夠有多少個slave同時對新的master進行同步。這個數字越小,完成failover所需的時間就越長;反之,可是若是這個數字越大,就意味着越多的slave由於replication而不可用。能夠經過將這個值設爲1,來保證每次只有一個slave,處於不能處理命令請求的狀態。 # sentinel parallel-syncs <master-name> <numslaves> sentinel parallel-syncs mymaster 1 # 故障轉移的超時時間failover-timeout,默認三分鐘,能夠用在如下這些方面: ## 1. 同一個sentinel對同一個master兩次failover之間的間隔時間。 ## 2. 當一個slave從一個錯誤的master那裏同步數據時開始,直到slave被糾正爲從正確的master那裏同步數據時結束。 ## 3. 當想要取消一個正在進行的failover時所須要的時間。 ## 4.當進行failover時,配置全部slaves指向新的master所需的最大時間。不過,即便過了這個超時,slaves依然會被正確配置爲指向master,可是就不按parallel-syncs所配置的規則來同步數據了 # sentinel failover-timeout <master-name> <milliseconds> sentinel failover-timeout mymaster 180000 # 當sentinel有任何警告級別的事件發生時(好比說redis實例的主觀失效和客觀失效等等),將會去調用這個腳本。一個腳本的最大執行時間爲60s,若是超過這個時間,腳本將會被一個SIGKILL信號終止,以後從新執行。 # 對於腳本的運行結果有如下規則: ## 1. 若腳本執行後返回1,那麼該腳本稍後將會被再次執行,重複次數目前默認爲10。 ## 2. 若腳本執行後返回2,或者比2更高的一個返回值,腳本將不會重複執行。 ## 3. 若是腳本在執行過程當中因爲收到系統中斷信號被終止了,則同返回值爲1時的行爲相同。 # sentinel notification-script <master-name> <script-path> sentinel notification-script mymaster /var/redis/notify.sh # 這個腳本應該是通用的,能被屢次調用,不是針對性的。 # sentinel client-reconfig-script <master-name> <script-path> sentinel client-reconfig-script mymaster /var/redis/reconfig.sh |
1.3. Redis Sentinel的節點規劃
角色 |
IP地址 |
端口號 |
Redis Master |
10.206.20.231 |
16379 |
Redis Slave1 |
10.206.20.231 |
26379 |
Redis Slave2 |
10.206.20.231 |
36379 |
Redis Sentinel1 |
10.206.20.231 |
16380 |
Redis Sentinel2 |
10.206.20.231 |
26380 |
Redis Sentinel3 |
10.206.20.231 |
36380 |
1.4. Redis Sentinel的配置搭建
搭建reids-server 集羣:
1.4.1. Redis-Server的配置管理
分別拷貝三份 redis.conf 文件到 /usr/local/redis-sentinel 目錄下面。三個配置文件分別對應 master、slave1 和 slave2 三個 Redis 節點的 啓動配置。
$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-16379.conf
$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-26379.conf
$ sudo cp /usr/local/redis-4.0.11/redis.conf /usr/local/redis-sentinel/redis-36379.conf
分別修改三份配置文件以下:
主節點:redis-16379.conf
daemonize yes pidfile /var/run/redis-16379.pid logfile /var/log/redis/redis-16379.log port 16379 bind 0.0.0.0 timeout 300 databases 16 dbfilename dump-16379.db dir ./redis-workdir masterauth 123456 requirepass 123456 |
從節點1:redis-26379.conf
daemonize yes pidfile /var/run/redis-26379.pid logfile /var/log/redis/redis-26379.log port 26379 bind 0.0.0.0 timeout 300 databases 16 dbfilename dump-26379.db dir ./redis-workdir masterauth 123456 requirepass 123456 slaveof 127.0.0.1 16379 |
從節點2:redis-36379.conf
daemonize yes pidfile /var/run/redis-36379.pid logfile /var/log/redis/redis-36379.log port 36379 bind 0.0.0.0 timeout 300 databases 16 dbfilename dump-36379.db dir ./redis-workdir masterauth 123456 requirepass 123456 slaveof 127.0.0.1 16379 |
若是要作 自動故障轉移,建議全部的 redis.conf 都設置 masterauth。由於 自動故障 只會重寫 主從關係,即 slaveof,不會自動寫入 masterauth。若是 Redis 本來沒有設置密碼,則能夠忽略。
1.4.2. Redis-Server啓動驗證
按順序分別啓動 16379,26379 和 36379 三個 Redis 節點,啓動命令和啓動日誌以下:
Redis 的啓動命令:
$ sudo redis-server /usr/local/redis-sentinel/redis-16379.conf
$ sudo redis-server /usr/local/redis-sentinel/redis-26379.conf
$ sudo redis-server /usr/local/redis-sentinel/redis-36379.conf
查看 Redis 的啓動進程:
$ ps -ef | grep redis-server
0 7127 1 0 2:16下午 ?? 0:01.84 redis-server 0.0.0.0:16379
0 7133 1 0 2:16下午 ?? 0:01.73 redis-server 0.0.0.0:26379
0 7137 1 0 2:16下午 ?? 0:01.70 redis-server 0.0.0.0:36379
查看 Redis 的啓動日誌:
節點 redis-16379
$ cat /var/log/redis/redis-16379.log 7126:C 22 Aug 14:16:38.907 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7126:C 22 Aug 14:16:38.908 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7126, just started 7126:C 22 Aug 14:16:38.908 # Configuration loaded 7127:M 22 Aug 14:16:38.910 * Increased maximum number of open files to 10032 (it was originally set to 256). 7127:M 22 Aug 14:16:38.912 * Running mode=standalone, port=16379. 7127:M 22 Aug 14:16:38.913 # Server initialized 7127:M 22 Aug 14:16:38.913 * Ready to accept connections 7127:M 22 Aug 14:16:48.416 * Slave 127.0.0.1:26379 asks for synchronization 7127:M 22 Aug 14:16:48.416 * Full resync requested by slave 127.0.0.1:26379 7127:M 22 Aug 14:16:48.416 * Starting BGSAVE for SYNC with target: disk 7127:M 22 Aug 14:16:48.416 * Background saving started by pid 7134 7134:C 22 Aug 14:16:48.433 * DB saved on disk 7127:M 22 Aug 14:16:48.487 * Background saving terminated with success 7127:M 22 Aug 14:16:48.494 * Synchronization with slave 127.0.0.1:26379 succeeded 7127:M 22 Aug 14:16:51.848 * Slave 127.0.0.1:36379 asks for synchronization 7127:M 22 Aug 14:16:51.849 * Full resync requested by slave 127.0.0.1:36379 7127:M 22 Aug 14:16:51.849 * Starting BGSAVE for SYNC with target: disk 7127:M 22 Aug 14:16:51.850 * Background saving started by pid 7138 7138:C 22 Aug 14:16:51.862 * DB saved on disk 7127:M 22 Aug 14:16:51.919 * Background saving terminated with success 7127:M 22 Aug 14:16:51.923 * Synchronization with slave 127.0.0.1:36379 succeeded |
如下兩行日誌日誌代表,redis-16379 做爲 Redis 的 主節點,redis-26379 和 redis-36379 做爲 從節點,從 主節點 同步數據。
7127:M 22 Aug 14:16:48.416 * Slave 127.0.0.1:26379 asks for synchronization
7127:M 22 Aug 14:16:51.848 * Slave 127.0.0.1:36379 asks for synchronization
節點 redis-26379
$ cat /var/log/redis/redis-26379.log 7132:C 22 Aug 14:16:48.407 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7132:C 22 Aug 14:16:48.408 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7132, just started 7132:C 22 Aug 14:16:48.408 # Configuration loaded 7133:S 22 Aug 14:16:48.410 * Increased maximum number of open files to 10032 (it was originally set to 256). 7133:S 22 Aug 14:16:48.412 * Running mode=standalone, port=26379. 7133:S 22 Aug 14:16:48.413 # Server initialized 7133:S 22 Aug 14:16:48.413 * Ready to accept connections 7133:S 22 Aug 14:16:48.413 * Connecting to MASTER 127.0.0.1:16379 7133:S 22 Aug 14:16:48.413 * MASTER <-> SLAVE sync started 7133:S 22 Aug 14:16:48.414 * Non blocking connect for SYNC fired the event. 7133:S 22 Aug 14:16:48.414 * Master replied to PING, replication can continue... 7133:S 22 Aug 14:16:48.415 * Partial resynchronization not possible (no cached master) 7133:S 22 Aug 14:16:48.417 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:0 7133:S 22 Aug 14:16:48.494 * MASTER <-> SLAVE sync: receiving 176 bytes from master 7133:S 22 Aug 14:16:48.495 * MASTER <-> SLAVE sync: Flushing old data 7133:S 22 Aug 14:16:48.496 * MASTER <-> SLAVE sync: Loading DB in memory 7133:S 22 Aug 14:16:48.498 * MASTER <-> SLAVE sync: Finished with success |
節點 redis-36379
$ cat /var/log/redis/redis-36379.log 7136:C 22 Aug 14:16:51.839 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7136:C 22 Aug 14:16:51.840 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7136, just started 7136:C 22 Aug 14:16:51.841 # Configuration loaded 7137:S 22 Aug 14:16:51.843 * Increased maximum number of open files to 10032 (it was originally set to 256). 7137:S 22 Aug 14:16:51.845 * Running mode=standalone, port=36379. 7137:S 22 Aug 14:16:51.845 # Server initialized 7137:S 22 Aug 14:16:51.846 * Ready to accept connections 7137:S 22 Aug 14:16:51.846 * Connecting to MASTER 127.0.0.1:16379 7137:S 22 Aug 14:16:51.847 * MASTER <-> SLAVE sync started 7137:S 22 Aug 14:16:51.847 * Non blocking connect for SYNC fired the event. 7137:S 22 Aug 14:16:51.847 * Master replied to PING, replication can continue... 7137:S 22 Aug 14:16:51.848 * Partial resynchronization not possible (no cached master) 7137:S 22 Aug 14:16:51.850 * Full resync from master: 211d3b4eceaa3af4fe5c77d22adf06e1218e0e7b:14 7137:S 22 Aug 14:16:51.923 * MASTER <-> SLAVE sync: receiving 176 bytes from master 7137:S 22 Aug 14:16:51.923 * MASTER <-> SLAVE sync: Flushing old data 7137:S 22 Aug 14:16:51.924 * MASTER <-> SLAVE sync: Loading DB in memory 7137:S 22 Aug 14:16:51.927 * MASTER <-> SLAVE sync: Finished with success |
配置Sentinel:
1.4.3. Sentinel的配置管理
分別拷貝三份 redis-sentinel.conf 文件到 /usr/local/redis-sentinel 目錄下面。三個配置文件分別對應 master、slave1 和 slave2 三個 Redis 節點的 哨兵配置。
$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-16380.conf
$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-26380.conf
$ sudo cp /usr/local/redis-4.0.11/sentinel.conf /usr/local/redis-sentinel/sentinel-36380.conf
節點1:sentinel-16380.conf
protected-mode no bind 0.0.0.0 port 16380 daemonize yes sentinel monitor master 127.0.0.1 16379 2 sentinel down-after-milliseconds master 5000 sentinel failover-timeout master 180000 sentinel parallel-syncs master 1 sentinel auth-pass master 123456 logfile /var/log/redis/sentinel-16380.log |
節點2:sentinel-26380.conf
protected-mode no bind 0.0.0.0 port 26380 daemonize yes sentinel monitor master 127.0.0.1 16379 2 sentinel down-after-milliseconds master 5000 sentinel failover-timeout master 180000 sentinel parallel-syncs master 1 sentinel auth-pass master 123456 logfile /var/log/redis/sentinel-26380.log |
節點3:sentinel-36380.conf
protected-mode no bind 0.0.0.0 port 36380 daemonize yes sentinel monitor master 127.0.0.1 16379 2 sentinel down-after-milliseconds master 5000 sentinel failover-timeout master 180000 sentinel parallel-syncs master 1 sentinel auth-pass master 123456 logfile /var/log/redis/sentinel-36380.log |
1.4.4. Sentinel啓動驗證
按順序分別啓動 16380,26380 和 36380 三個 Sentinel 節點,啓動命令和啓動日誌以下:
$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-16380.conf
$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-26380.conf
$ sudo redis-sentinel /usr/local/redis-sentinel/sentinel-36380.conf
查看 Sentinel 的啓動進程:
$ ps -ef | grep redis-sentinel
0 7954 1 0 3:30下午 ?? 0:00.05 redis-sentinel 0.0.0.0:16380 [sentinel]
0 7957 1 0 3:30下午 ?? 0:00.05 redis-sentinel 0.0.0.0:26380 [sentinel]
0 7960 1 0 3:30下午 ?? 0:00.04 redis-sentinel 0.0.0.0:36380 [sentinel]
查看 Sentinel 的啓動日誌:
節點 sentinel-16380
$ cat /var/log/redis/sentinel-16380.log 7953:X 22 Aug 15:30:27.245 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7953:X 22 Aug 15:30:27.245 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7953, just started 7953:X 22 Aug 15:30:27.245 # Configuration loaded 7954:X 22 Aug 15:30:27.247 * Increased maximum number of open files to 10032 (it was originally set to 256). 7954:X 22 Aug 15:30:27.249 * Running mode=sentinel, port=16380. 7954:X 22 Aug 15:30:27.250 # Sentinel ID is 69d05b86a82102a8919231fd3c2d1f21ce86e000 7954:X 22 Aug 15:30:27.250 # +monitor master master 127.0.0.1 16379 quorum 2 7954:X 22 Aug 15:30:32.286 # +sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379 7954:X 22 Aug 15:30:34.588 # -sdown sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379 |
sentinel-16380 節點的 Sentinel ID 爲 69d05b86a82102a8919231fd3c2d1f21ce86e000,並經過 Sentinel ID 把自身加入 sentinel 集羣中。
節點 sentinel-26380
$ cat /var/log/redis/sentinel-26380.log 7956:X 22 Aug 15:30:30.900 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7956:X 22 Aug 15:30:30.901 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7956, just started 7956:X 22 Aug 15:30:30.901 # Configuration loaded 7957:X 22 Aug 15:30:30.904 * Increased maximum number of open files to 10032 (it was originally set to 256). 7957:X 22 Aug 15:30:30.905 * Running mode=sentinel, port=26380. 7957:X 22 Aug 15:30:30.906 # Sentinel ID is 21e30244cda6a3d3f55200bcd904d0877574e506 7957:X 22 Aug 15:30:30.906 # +monitor master master 127.0.0.1 16379 quorum 2 7957:X 22 Aug 15:30:30.907 * +slave slave 127.0.0.1:26379 127.0.0.1 26379 @ master 127.0.0.1 16379 7957:X 22 Aug 15:30:30.911 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 16379 7957:X 22 Aug 15:30:36.311 * +sentinel sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379 |
sentinel-26380 節點的 Sentinel ID 爲 21e30244cda6a3d3f55200bcd904d0877574e506,並經過 Sentinel ID 把自身加入 sentinel 集羣中。此時 sentinel 集羣中已有 sentinel-16380 和 sentinel-26380 兩個節點。
節點 sentinel-36380
$ cat /var/log/redis/sentinel-36380.log 7959:X 22 Aug 15:30:34.273 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7959:X 22 Aug 15:30:34.274 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=7959, just started 7959:X 22 Aug 15:30:34.274 # Configuration loaded 7960:X 22 Aug 15:30:34.276 * Increased maximum number of open files to 10032 (it was originally set to 256). 7960:X 22 Aug 15:30:34.277 * Running mode=sentinel, port=36380. 7960:X 22 Aug 15:30:34.278 # Sentinel ID is fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 7960:X 22 Aug 15:30:34.278 # +monitor master master 127.0.0.1 16379 quorum 2 7960:X 22 Aug 15:30:34.279 * +slave slave 127.0.0.1:26379 127.0.0.1 26379 @ master 127.0.0.1 16379 7960:X 22 Aug 15:30:34.283 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 16379 7960:X 22 Aug 15:30:34.993 * +sentinel sentinel 21e30244cda6a3d3f55200bcd904d0877574e506 127.0.0.1 26380 @ master 127.0.0.1 16379 |
sentinel-36380 節點的 Sentinel ID 爲 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7,並經過 Sentinel ID 把自身加入 sentinel 集羣中。此時 sentinel 集羣中已有 sentinel-16380,sentinel-26380 和 sentinel-36380 三個節點。
1.4.5. Sentinel配置刷新(這裏注意一下,sentinel的配置文件是自動刷新的)
sentinel-16380.conf 文件新生成以下的配置項:
# Generated by CONFIG REWRITE dir "/usr/local/redis-sentinel" sentinel config-epoch master 0 sentinel leader-epoch master 0 sentinel known-slave master 127.0.0.1 36379 sentinel known-slave master 127.0.0.1 26379 sentinel known-sentinel master 127.0.0.1 26380 21e30244cda6a3d3f55200bcd904d0877574e506 sentinel known-sentinel master 127.0.0.1 36380 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 sentinel current-epoch 0 |
能夠注意到,sentinel-16380.conf 刷新寫入了 Redis 主節點關聯的全部 從節點 redis-26379 和 redis-36379,同時寫入了其他兩個 Sentinel 節點 sentinel-26380 和 sentinel-36380 的 IP 地址,端口號 和 Sentinel ID。
# Generated by CONFIG REWRITE dir "/usr/local/redis-sentinel" sentinel config-epoch master 0 sentinel leader-epoch master 0 sentinel known-slave master 127.0.0.1 26379 sentinel known-slave master 127.0.0.1 36379 sentinel known-sentinel master 127.0.0.1 36380 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 sentinel known-sentinel master 127.0.0.1 16380 69d05b86a82102a8919231fd3c2d1f21ce86e000 sentinel current-epoch 0 |
能夠注意到,sentinel-26380.conf 刷新寫入了 Redis 主節點關聯的全部 從節點 redis-26379 和 redis-36379,同時寫入了其他兩個 Sentinel 節點 sentinel-36380 和 sentinel-16380 的 IP 地址,端口號 和 Sentinel ID。
# Generated by CONFIG REWRITE dir "/usr/local/redis-sentinel" sentinel config-epoch master 0 sentinel leader-epoch master 0 sentinel known-slave master 127.0.0.1 36379 sentinel known-slave master 127.0.0.1 26379 sentinel known-sentinel master 127.0.0.1 16380 69d05b86a82102a8919231fd3c2d1f21ce86e000 sentinel known-sentinel master 127.0.0.1 26380 21e30244cda6a3d3f55200bcd904d0877574e506 sentinel current-epoch 0 |
能夠注意到,sentinel-36380.conf 刷新寫入了 Redis 主節點關聯的全部 從節點 redis-26379 和 redis-36379,同時寫入了其他兩個 Sentinel 節點 sentinel-16380 和 sentinel-26380 的 IP 地址,端口號 和 Sentinel ID。
1.5. Sentinel時客戶端命令
檢查其餘 Sentinel 節點的狀態,返回 PONG 爲正常。
> PING sentinel
顯示被監控的全部 主節點 以及它們的狀態。
> SENTINEL masters
顯示指定 主節點 的信息和狀態。
> SENTINEL master <master_name>
顯示指定 主節點 的全部 從節點 以及它們的狀態。
> SENTINEL slaves <master_name>
返回指定 主節點 的 IP 地址和 端口。若是正在進行 failover 或者 failover 已經完成,將會顯示被提高爲 主節點 的 從節點 的 IP 地址和 端口。
> SENTINEL get-master-addr-by-name <master_name>
重置名字匹配該 正則表達式 的全部的 主節點 的狀態信息,清除它以前的 狀態信息,以及 從節點 的信息。
> SENTINEL reset <pattern>
強制當前 Sentinel 節點執行 failover,而且不須要獲得其餘 Sentinel 節點的贊成。可是 failover 後會將 最新的配置 發送給其餘 Sentinel 節點。
>SENTINEL failover <master_name>
2. Redis Sentinel故障切換與恢復
2.1. Redis CLI客戶端跟蹤
上面的日誌顯示,redis-16379 節點爲 主節點,它的進程 ID 爲 7127。爲了模擬 Redis 主節點故障,強制殺掉這個進程。
$ kill -9 7127
使用 redis-cli 客戶端命令進入 sentinel-16380 節點,查看 Redis 節點 的狀態信息。
$ redis-cli -p 16380
查看 Redis 主從集羣的 主節點 信息。能夠發現 redis-26379 晉升爲 新的主節點。
127.0.0.1:16380> SENTINEL master master 1) "name" 2) "master" 3) "ip" 4) "127.0.0.1" 5) "port" 6) "26379" 7) "runid" 8) "b8ca3b468a95d1be5efe1f50c50636cafe48c59f" 9) "flags" 10) "master" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "588" 19) "last-ping-reply" 20) "588" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "9913" 25) "role-reported" 26) "master" 27) "role-reported-time" 28) "663171" 29) "config-epoch" 30) "1" 31) "num-slaves" 32) "2" 33) "num-other-sentinels" 34) "2" 35) "quorum" 36) "2" 37) "failover-timeout" 38) "180000" 39) "parallel-syncs" 40) "1" |
2.2. Redis Sentinel日誌跟蹤
查看任意 Sentinel 節點的日誌以下:
7954:X 22 Aug 18:40:22.504 # +tilt #tilt mode entered 7954:X 22 Aug 18:40:32.197 # +tilt #tilt mode entered 7954:X 22 Aug 18:41:02.241 # -tilt #tilt mode exited 7954:X 22 Aug 18:48:24.550 # +sdown master master 127.0.0.1 16379 7954:X 22 Aug 18:48:24.647 # +new-epoch 1 7954:X 22 Aug 18:48:24.651 # +vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 1 7954:X 22 Aug 18:48:25.678 # +odown master master 127.0.0.1 16379 #quorum 3/2 7954:X 22 Aug 18:48:25.678 # Next failover delay: I will not start a failover before Wed Aug 22 18:54:24 2018 7954:X 22 Aug 18:48:25.709 # +config-update-from sentinel fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 127.0.0.1 36380 @ master 127.0.0.1 16379 7954:X 22 Aug 18:48:25.710 # +switch-master master 127.0.0.1 16379 127.0.0.1 26379 7954:X 22 Aug 18:48:25.710 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 26379 7954:X 22 Aug 18:48:25.711 * +slave slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379 7954:X 22 Aug 18:48:30.738 # +sdown slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379 7954:X 22 Aug 19:38:23.479 # -sdown slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379 |
分析日誌,能夠發現 redis-16329 節點先進入 sdown 主觀下線 狀態。
+sdown master master 127.0.0.1 16379
哨兵檢測到 redis-16329 出現故障,Sentinel 進入一個 新紀元,從 0 變爲 1。
+new-epoch 1
三個 Sentinel 節點開始協商 主節點 的狀態,判斷其是否須要 客觀下線。
+vote-for-leader fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7 1
超過 quorum 個數的 Sentinel 節點認爲 主節點 出現故障,redis-16329 節點進入 客觀下線狀態。
+odown master master 127.0.0.1 16379 #quorum 3/2
Sentinal 進行 自動故障切換,協商選定 redis-26329 節點做爲新的 主節點。
+switch-master master 127.0.0.1 16379 127.0.0.1 26379
redis-36329 節點和已經 客觀下線 的 redis-16329 節點成爲 redis-26479 的 從節點。
7954:X 22 Aug 18:48:25.710 * +slave slave 127.0.0.1:36379 127.0.0.1 36379 @ master 127.0.0.1 26379
7954:X 22 Aug 18:48:25.711 * +slave slave 127.0.0.1:16379 127.0.0.1 16379 @ master 127.0.0.1 26379
2.3. Redis的配置文件(自動刷新的)
分別查看三個 redis 節點的配置文件,發生 主從切換 時 redis.conf 的配置會自動發生刷新。
節點 redis-16379
daemonize yes pidfile "/var/run/redis-16379.pid" logfile "/var/log/redis/redis-16379.log" port 16379 bind 0.0.0.0 timeout 300 databases 16 dbfilename "dump-16379.db" dir "/usr/local/redis-sentinel/redis-workdir" masterauth "123456" requirepass "123456" |
節點 redis-26379
daemonize yes pidfile "/var/run/redis-26379.pid" logfile "/var/log/redis/redis-26379.log" port 26379 bind 0.0.0.0 timeout 300 databases 16 dbfilename "dump-26379.db" dir "/usr/local/redis-sentinel/redis-workdir" masterauth "123456" requirepass "123456" |
節點 redis-36379
daemonize yes pidfile "/var/run/redis-36379.pid" logfile "/var/log/redis/redis-36379.log" port 36379 bind 0.0.0.0 timeout 300 databases 16 dbfilename "dump-36379.db" dir "/usr/local/redis-sentinel/redis-workdir" masterauth "123456" requirepass "123456" slaveof 127.0.0.1 26379 |
分析:redis-26379 節點 slaveof 配置被移除,晉升爲 主節點。redis-16379 節點處於 宕機狀態。redis-36379 的 slaveof 配置更新爲 127.0.0.1 redis-26379,成爲 redis-26379 的 從節點。
重啓節點 redis-16379。待正常啓動後,再次查看它的 redis.conf 文件,配置以下:
daemonize yes pidfile "/var/run/redis-16379.pid" logfile "/var/log/redis/redis-16379.log" port 16379 bind 0.0.0.0 timeout 300 databases 16 dbfilename "dump-16379.db" dir "/usr/local/redis-sentinel/redis-workdir" masterauth "123456" requirepass "123456" # Generated by CONFIG REWRITE slaveof 127.0.0.1 26379 |
節點 redis-16379 的配置文件新增一行 slaveof 配置屬性,指向 redis-26379,即成爲 新的主節點 的 從節點。
小結
本文首先對 Redis 實現高可用的幾種模式作出了闡述,指出了 Redis 主從複製 的不足之處,進一步引入了 Redis Sentinel 哨兵模式 的相關概念,深刻說明了 Redis Sentinel 的 具體功能,基本原理,高可用搭建 和 自動故障切換 驗證等。
固然,Redis Sentinel 僅僅解決了 高可用 的問題,對於 主節點 單點寫入和單節點沒法擴容等問題,還須要引入 Redis Cluster 集羣模式 予以解決。
3.哨兵節點管理
3.1 哨兵節點的增長和刪除
增長sentinal,會自動發現
刪除sentinal的步驟
(1)中止sentinal進程
(2)SENTINEL RESET *,在全部sentinal上執行,清理全部的master狀態
(3)SENTINEL MASTER mastername,在全部sentinal上執行,查看全部sentinal對數量是否達成了一致
3.2 slave的永久下線
讓master摘除某個已經下線的slave:SENTINEL RESET mastername,在全部的哨兵上面執行
3.3 slave切換爲Master的優先級
slave->master選舉優先級:slave-priority,值越小優先級越高
3.4 基於哨兵集羣架構下的安全認證
每一個slave都有可能切換成master,因此每一個實例都要配置兩個指令
master上啓用安全認證,requirepass
master鏈接口令,masterauth
sentinal,sentinel auth-pass <master-group-name> <pass>
3.5 容災演練
經過哨兵看一下當前的master:SENTINEL get-master-addr-by-name mymaster
把master節點kill -9掉,pid文件也刪除掉
查看sentinal的日誌,是否出現+sdown字樣,識別出了master的宕機問題; 而後出現+odown字樣,就是指定的quorum哨兵數量,都認爲master宕機了
(1)三個哨兵進程都認爲master是sdown了
(2)超過quorum指定的哨兵進程都認爲sdown以後,就變爲odown
(3)哨兵1是被選舉爲要執行後續的主備切換的那個哨兵
(4)哨兵1去新的master(slave)獲取了一個新的config version
(5)嘗試執行failover
(6)投票選舉出一個slave區切換成master,每一個哨兵都會執行一次投票
(7)讓salve,slaveof noone,不讓它去作任何節點的slave了; 把slave提拔成master; 舊的master認爲再也不是master了
(8)哨兵就自動認爲以前的187:6379變成了slave了,19:6379變成了master了
(9)哨兵去探查了一下187:6379這個salve的狀態,認爲它sdown了
全部哨兵選舉出了一個,來執行主備切換操做
若是哨兵的majority都存活着,那麼就會執行主備切換操做
再經過哨兵看一下master:SENTINEL get-master-addr-by-name mymaster
嘗試鏈接一下新的master
故障恢復,再將舊的master從新啓動,查看是否被哨兵自動切換成slave節點
(1)手動殺掉master
(2)哨兵可否執行主備切換,將slave切換爲master
(3)哨兵完成主備切換後,新的master可否使用
(4)故障恢復,將舊的master從新啓動
(5)哨兵可否自動將舊的master變爲slave,掛接到新的master上面去,並且也是可使用的
主從架構,單master的瓶頸:
可以存儲多少數據量,受限於master
怎麼橫向擴展,master:
咱們能夠作多個redis 主從集羣,作業務的分流,不一樣的請求,訪問到不一樣的master
redis cluster幫咱們作好了這樣的功能:
能夠支撐N個redis master node,每一個master node均可以掛載多個slave node
redis cluster (多master + 讀寫分離 + 高可用)
redis cluster 是用來支撐海量數據的