玩轉 Redis 集羣之 Sentinel

Redis做爲內存數據庫,須要具有高可用的特色,否則若是服務器宕機,還在內存裏的數據就會丟失。咱們最經常使用的高可用方法就是搭建集羣,master機器掛了,可讓slave機器頂上,繼續提供服務。可是Redis集羣是不會自動進行主從切換的,也就是說,若是主節點很是不爭氣的在凌晨3點掛了,那麼運維同窗就要立刻起牀,把從節點改爲主節點,這樣的操做是很是繁瑣低效的。爲此,Redis官方提供了一種解決方案:Redis Sentinelredis

簡介sql

Redis Sentinel集羣一般由3到5個節點組成,若是個別節點掛了,集羣還能夠正常運做。它負責監控Redis集羣的健康狀況。若是主節點掛掉,Sentinel集羣會經過投票選擇一個新的主節點。當原來的主節點恢復時,它會被當作新的主節點的從節點從新加入Redis集羣。數據庫

基本原理服務器

Sentinel集羣經過指定的配置文件發現master,對其進行監控,而且會發送info指令獲取master的從節點信息。Sentinel集羣中的節點經過向其監控的主從節點發送hello信息(包含Sentinel自己的ip、端口和id等內容)來向其餘Sentinel宣告本身的存在。架構

Sentinel集羣經過訂閱鏈接來接收其餘Sentinel的hello信息。併發

Sentinel集羣經過ping命令來檢查監控的實例狀態,若是在指定時間內沒有返回,則認爲該實例下線。運維

Sentinel觸發failover主從切換後,並不會立刻進行,只有指定(quorum)Sentinel受權後,master節點被標記爲ODOWN狀態。這時才真正開始投票選擇新的master。socket

Sentinel選擇新的master的原則是:首先判斷優先級,選擇優先級較小的;若是優先級相同,查看複製下標,選擇複製數據較多的;若是複製下標也相同,就選擇進程ID較小的。分佈式

Sentinel被受權後,它將會得到宕掉的master的一份最新配置版本號(config-epoch),當failover執行結束之後,這個版本號將會被用於最新的配置,經過廣播形式通知其它Sentinel,其它的Sentinel則更新對應master的配置。高併發

基本使用

咱們以Python爲例,簡單說明一下在客戶端如何使用Sentinel

1from redis.sentinel import Sentinel
 2
 3if __name__ == '__main__':
 4    sentinel = Sentinel(['localhost', 26379], socket_timeout=0.1)
 5    print(sentinel.discover_master('mymaster'))
 6    print(sentinel.discover_slaves('mymaster'))
 7    master = sentinel.master_for('mymaster', socket_timeout=0.1)
 8    slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
 9    master.set('follow', 'Jackeyzhe2018')
10    follow = slave.get('follow')
11    print(follow)

master_for和slave_for方法會從鏈接池中拿出一個鏈接來使用,若是從地址有多個,則會採用輪詢的方法。

當redis發生了主從切換時,客戶端如何知道地址已經變動了呢?咱們從redis-py的源碼裏找一找答案。

 

 

 

 

 

 

 

 

 

 

能夠看到,redis在建立一個新的鏈接時,會調用get_master_address方法來獲取主節點地址。get_master_address方法中,客戶端先查詢主節點地址,而後與內存中的地址進行比較。若是不一致,則會斷開鏈接,而後使用新的地址從新進行鏈接。

若是主節點沒有掛,而Sentinel主動進行了主從切換,對於這種狀況redis-py也作了處理。就是捕獲一個ReadOnlyError的異常,而後斷開鏈接,後續指令都須要從新進行鏈接了。固然,若是沒有修改性指令,那麼鏈接就不會切換,不過數據也不會被破壞,因此影響不大。

動手搭建

關於Sentinel的工做原理和使用方法咱們已經有了大概的認識,爲了加深理解,咱們來本身動手搭建一套Sentinel集羣。

首先搭建咱們我須要的redis集羣環境

安裝好redis後,將redis目錄下的配置文件redis.conf複製3份。分別命名爲redis6379.conf,redis6380.conf,redis6381.conf。

在redis6381.conf文件中修改如下幾項

1bind 127.0.0.1
2port 6381
3logfile "6381.log"
4dbfilename "dump-6381.rdb"

在redis6379.conf中修改

1bind 127.0.0.1
2port 6379
3logfile "6379.log"
4dbfilename "dump-6379.rdb"
5slaveof 127.0.0.1 6381

redis6380.conf的修改參照redis6379.conf。修改完成後,分別啓動三個實例。就搭建好了咱們想要的redis主從環境了。

 

 

 

 

 

咱們鏈接上master節點,能夠看到它的主從配置信息

 

 

 

 

 

接着,咱們來配置Sentinel集羣。這裏咱們一樣配置三個實例。複製3份sentinel.conf文件,分別命名爲sentinel-26379.conf,sentinel-26380.conf和sentinel-26381.conf。

sentinel-26379.conf文件中編輯如下內容

1port 26379  
2daemonize yes  
3logfile "26379.log"  
4dir /home/xxx/redis/data  
5sentinel monitor mymaster 127.0.0.1 6381 2
6sentinel down-after-milliseconds mymaster 30000  
7sentinel parallel-syncs mymaster 1  
8sentinel failover-timeout mymaster 180000

sentinel-26380.conf和sentinel-26381.conf的內容與上述相似。配置好後,咱們使用命令redis-sentinel來啓動3個sentinel實例。

 

 

 

 

 

此時,咱們用redis-cli命令鏈接26379的實例,查看sentinel的信息。

 

 

 

 

 

發現它已經開始監控咱們的3個redis節點了。這時咱們的整個集羣就部署好了,接下來測試一下。

kill掉master節點,查看sentinel的日誌,會發現sentinel已經按照咱們前面說的步驟選擇了新的master。

 

此時再來看sentinel信息。

此時,6380已經成了新的master。

恭喜你,之後都不須要在凌晨起牀切換Redis主從實例了。

歡迎工做一到五年的Java工程師朋友們加入Java架構開發: 855835163 羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索