天天看點

Docker化高可用redis叢集

最近遇到部分系統因為redis服務挂掉,導緻部分服務不可用。是以希望搭建一個redis叢集鏡像,把原先散落各處的redis伺服器統一管理起來,并且保障高可用和故障自動遷移。
Docker化高可用redis叢集

關于它的介紹:

redis 的 sentinel 系統用于管理多個 redis 伺服器(instance), 該系統執行以下三個任務:

監控(monitoring): sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。

提醒(notification): 當被監控的某個 redis 伺服器出現問題時, sentinel 可以通過 api 向管理者或者其他應用程式發送通知。

自動故障遷移(automatic failover): 當一個主伺服器不能正常工作時, sentinel 會開始一次自動故障遷移操作, 它會将失效主伺服器的其中一個從伺服器更新為新的主伺服器, 并讓失效主伺服器的其他從伺服器改為複制新的主伺服器; 當用戶端試圖連接配接失效的主伺服器時, 叢集也會向用戶端傳回新主伺服器的位址, 使得叢集可以使用新主伺服器代替失效伺服器。

整個叢集可以分為一個master,n個slave,m個sentinel,本次以2個slave和3個sentinel為例:

Docker化高可用redis叢集

首先增加<code>redis.conf</code>

預設為master,<code>#slaveof</code>注釋去掉後變為slave,這裡固化了master的域名<code>redis-master</code>。

增加<code>sentinel.conf</code>

增加啟動腳本,根據入參判斷啟動master,slave,sentinel

其中$redis_port和$master_port,$sentinel_port都是取自環境變量,通過docker啟動時候傳入。

編寫<code>dockerfile</code>

選取redis-alpine鏡像作為基礎鏡像,因為它非常小,隻有9m,修改時區和把一些配置拷貝進去後,變更下權限和使用者組,因為基礎鏡像是redis使用者組。<code>entrypoint</code>和<code>cmd</code>組合,預設以master方式啟動。

build完成後,鏡像隻有15m。

采用docker-compose格式:

首先啟動master,傳入端口16379,host模式,在啟動slave,成為16379 master 的slave,并且設定排程政策為盡可能分散的方式,sentinels也類似。

java用戶端測試(片段):

此時kill掉一台sentinel,會提示:

資料正常讀寫,當把所有sentinel都kill掉後,任然能夠正常讀寫,并且不斷在重連sentinel,說明sentinel隻是重新選取master和failover時才頂用,一旦選好後,及時全挂了,redis也能照常運作。

而如果這是重新去初始化redispool的時候,會報錯:

sentinel之間不需要互相配置,大家都通過訂閱master和slave的sentinel:hello 頻道,上報自己的ip,port等資訊,然後每個sentinel就都維護了一份已知的sentinel清單。

此時kill掉一台slave,對用戶端沒有任何影響,也不會有感覺,master會有失聯日志:

sentinel也有日志:

此時恢複那台slave

馬上從master恢複資料,最終保持一緻。

此時用戶端出現異常:

并且sentinel開始發現這個情況,首先主觀判斷master(ip_address 16379)已經挂了,然後通過詢問其他sentinel,是否master挂了,判斷得到2個sentinel都認為master挂了(這裡的2個為之前sentinel.conf中配置,一般建議選擇多餘一半的sentinel的個數),此時客觀判斷master挂了。開始新的一輪master投票,投票給了ip_address:16380,進行failover,完成後切換至新主。并且通知其餘slave,有了新主。以下是詳細日志:注意的是,再選取過程中,出現了短暫的用戶端不可用。

此時若老master恢複後,發現自己被sentinel定義為新master的slave,是以隻能乖乖的變成slave,從master同步一下資料,保證資料一緻性。

總的來說,隻要叢集中有一台redis執行個體存活,叢集就能對外提供服務,而sentinel隻會在master或slave挂掉才會有實際的作用。

這次的鏡像大小隻有15m,非常小。采用啟動時配置角色和端口,包括master,slave,和sentinel3個角色,通過服務編排啟動一個redis叢集。

繼續閱讀