跟我一起學Redis之加個哨兵讓主從複製更加高可用
阿新 • • 發佈:2021-01-18
### 前言
主從複製的實現在[上一篇](https://mp.weixin.qq.com/s?__biz=MzU1MzYwMjQ5MQ==&mid=2247484394&idx=1&sn=12eec9feea7ecd4e21c474fa1b146366&chksm=fbf11f3ecc869628bf494ccd896237f8649698cce8a952c2ed98b7f73afd1307129f6a5d6c22&token=1364939791&lang=zh_CN#rd)已經分享過,雖然主從複製本身的確讓讀寫分離更加高效,但是對於整體高可用存在很大的劣勢:當主節點宕機了之後還需要人為重新進行主從關係配置;這不是開玩笑嘛,這樣人為干預,故障恢復不及時,損失就難免啦。誰維護誰不爽,睡個覺都提心吊膽。
找個哨兵站崗,專門用來監控主伺服器,一旦有變故,哨兵自動處理,這樣故障恢復及時且更加智慧;接下來就來玩玩。
### 正文
**Redis哨兵(Sentinel)**其實本質就是一個RedisServer節點,通過設定**執行模式**來開啟哨兵的功能;主要功能如下:
- **監控(Monitoring**):哨兵節點會不斷的檢查的主服務和從服務的執行狀態;
- **自動故障遷移(Automatic failover)**:當Redis主從模式中的主伺服器發生故障時,哨兵節點會根據一定的策略自動進行故障遷移,即在原有主伺服器下的從伺服器中,自動選出一個從伺服器作為新的主伺服器,及時處理故障;
- **通知(Notification)**:當被監控的Redis伺服器故障時,哨兵節點可以向相關人員或客戶端傳送通知提醒;
- **配置提供者(Configuration provider)**:可以通過哨兵節點為客戶端提供主從模式中的主節點地址,這裡的客戶端指平時寫的程式;
老規矩,還是先不說那麼多理論,先來實操一把,然後再來總結:
#### 哨兵模式搭建
先來個最基礎的:一個哨兵監控一主二從的環境;後面小夥伴就知道如何擴充套件啦,如下圖所示(這裡通過一臺機器演示,所以通過埠進行區分各個redis節點):
![image-20210114141345708](https://i.loli.net/2021/01/14/S46Fj3t8EzD9KoY.png)
Redis哨兵模式是基於Redis主從複製的,所以先來搭建主從複製環境,這個過程在[上一篇](https://mp.weixin.qq.com/s?__biz=MzU1MzYwMjQ5MQ==&mid=2247484394&idx=1&sn=12eec9feea7ecd4e21c474fa1b146366&chksm=fbf11f3ecc869628bf494ccd896237f8649698cce8a952c2ed98b7f73afd1307129f6a5d6c22&token=1364939791&lang=zh_CN#rd)中已經詳細分享,這裡就不細說,直接動手啦;
1. 搭建主從複製環境,如上圖所示,6377作為主伺服器,6388和6399作為從伺服器,這裡是通過配置檔案的形式修改,最終效果如下:
![image-20210114142426244](https://i.loli.net/2021/01/14/a7FCS1iceUVMBrE.png)
2. 主從複製環境搭建完畢之後,接下來需要有一個哨兵對其進行監控;之前有說過,Redis的功能通過配置檔案就能快速實現,針對哨兵有一個單獨的配置檔案,這裡就起名為:**sentinel.conf**,內容如下:
```sentinel monitor mymaster 127.0.0.1 6377 1```
大概意思就是哨兵要監控對應的主伺服器,其他啥都不用配置;
這裡對於配置檔案內容先不解釋這麼多,接下來會專門進行介紹,先把環境搭建起來,玩一把再說;
3. 啟動哨兵,兩種方式:
**redis-sentinel啟動**,redis-sentinel其實是用redis的一個程式碼分支分離出來的,安裝完redis就有,命令如下:
```./redis-sentinel ZoeConfig/sentinel.conf```
**redis-server啟動**,指定為哨兵模式即可,命令如下:
```./redis-server ZoeConfig/sentinel.conf --sentinel```
啟動效果如下:
![image-20210114164300813](https://i.loli.net/2021/01/14/loWgyVp4JhHPxcT.png)
如上圖所示,Redis哨兵其實本質還是一個Redis節點,只是執行模式不一樣而已;
4. 哨兵模式執行起來,模擬主伺服器宕機,這裡直接將6377伺服器shutdown, 注意看哨兵列印的日誌:
先將主伺服器6377關掉,如下:
![image-20210114165824631](https://i.loli.net/2021/01/14/RKWqekpyfUNPlbD.png)
由於哨兵定時對主伺服器進行監控,如果在30秒內(預設30秒)發現主伺服器無法正常通訊時,就開始進行投票選舉原主伺服器下的從伺服器作為新主伺服器,哨兵列印日誌如下:
![image-20210114170909938](https://i.loli.net/2021/01/14/BOxZ5lSrmjgKTY6.png)
大概流程如下圖:
![image-20210115105820011](https://i.loli.net/2021/01/15/YqAh2QEuv4RnmMZ.png)
哨兵最後的狀態會持久化到指定的配置檔案中,之前只是簡單配置了一條監控語句,現在如下:
![image-20210115122612914](https://i.loli.net/2021/01/15/xOUodmnZEAeJGIs.png)
5. 驗證故障轉移結果;
光說6388變成了主伺服器沒證據,連上6388看看,同時再看看6399有沒有換新主人,如下圖:
**6388主從資訊**:
![image-20210114171247927](https://i.loli.net/2021/01/14/3XzTvs7L6oaRVgD.png)
對應的配置檔案中將之前的主從關係配置已經去掉了。
**6399主從資訊**:
![image-20210114171516670](https://i.loli.net/2021/01/14/HOvrR4DiJxFhYSo.png)
對應的配置檔案也已經改了,如下:
![image-20210114171713342](https://i.loli.net/2021/01/14/yeYrFmua1HUO32f.png)
以上就完成了哨兵模式搭建的演示啦,是不是很簡單,只要稍微改改配置檔案即可完成自動化故障恢復。 到這小夥伴可能會問,原來故障的主伺服器恢復了會怎麼樣? 一個哨兵誤判主伺服器下線或高併發抗不住怎麼辦?嘿嘿嘿,接著來搞,接下來邊操作邊總結;
#### 原故障的主伺服器恢復之後只能當小兵
原有通訊異常的主伺服器如果恢復正常,那它還能恢復原來的地位嗎?,還是另有安排呢?這個很好演示,直接將之前shutdown的主伺服器重新起來即可;6377啟動後檢視主從關係資訊如下圖:
![image-20210115111608936](https://i.loli.net/2021/01/15/jbfrxTRk8FZ2sna.png)
如上圖實操驗證,原來異常的主伺服器(6377)恢復之後就變成新主伺服器(6388)的從伺服器了(原來再屌,現在也只是小弟,重新再混等機會)。
#### 哨兵叢集高可用
以上演示就一個哨兵,這樣有很明顯的兩個缺點,如下:
- 單個哨兵容易導致誤判主節點下線,比如主節點正常,只是在與哨兵之間通訊出現短暫異常,如果是單個哨兵,在指定的時間間隔沒有通訊就認為主節點下線了,但其實沒有;如果哨兵叢集,可以詢問多個哨兵指定的主節點是否下線,這樣就顯得更有保障;
- 哨兵掛了,故障轉移就沒法繼續啦,哨兵叢集的話就會選擇其他哨兵繼續處理;
配置哨兵叢集超級簡單,就是增加節點即可,哨兵節點會通過釋出與訂閱功能來自動發現正在監視**相同主伺服器**的其他哨兵 , 這一功能是通過向頻道 **sentinel**:hello 傳送資訊來實現的。如下圖再新增一個哨兵節點,同時增加一個配置檔案,由於預設埠為26379,上一個哨兵已經佔用,這裡在新增的配置檔案中指定新哨兵的埠為:26388;
配置檔名為**sentinel26388.conf**,內容如下:
``` bash
sentinel monitor mymaster 127.0.0.1 6388 1
port 26388
```
指定配置檔案啟動第二個哨兵,啟動命令為``` ./redis-sentinel ZoeConfig/sentinel26388.conf ```,效果如下:
![image-20210115123029803](https://i.loli.net/2021/01/15/9Yd1JyvWzpX8IbF.png)
#### 哨兵如何做到互相交流和監控從伺服器的
到這應該有小夥伴會有疑問:在配置哨兵的時候,只配置監控主伺服器,從伺服器是怎麼知道的?哨兵之間的交流是通過什麼形式實現的?
**關於從伺服器:** 哨兵會自動詢問主伺服器獲得對應從伺服器的資訊,因為從伺服器會在連線主伺服器的時候把相關資訊給主伺服器,所以哨兵能通過主伺服器拿到從伺服器的資訊;
**關於哨兵之間:**哨兵節點會通過釋出與訂閱功能來自動發現正在監視**相同主伺服器**的其他哨兵 , 這一功能是通過向頻道 **sentinel**:hello 傳送資訊來實現的;
注:一個哨兵可以同時監控多個主伺服器;
#### 哨兵配置檔案介紹
以上配置只是為了快速實現演示,其實關於哨兵還有其他很多配置,接下來都過一遍:
- **port:**哨兵的埠,預設是26379,可以通過此配置項進行修改;
- **dir:**哨兵的工作目錄;
- **sentinel