redis sentinel 主從切換(failover)解決方案,詳細配置
阿新 • • 發佈:2018-12-25
《Redis原始碼學習筆記》文章列表
由於圖片較大,縮放較為模糊,請雙擊開啟檢視原圖 ^_^
主從複製簡單來說就是把一臺redis資料庫中的資料同步到另一臺redis資料庫,並且按照資料流向,資料的傳送者我們稱作master,資料的接受者我們稱作slave(master/slave的劃分並不是那麼一定的,譬如B可以作為A的slave,但同時也可以作為C的master),下面就從slave和master的角度分別說明主從複製流程。
首先是slave端,對於slave端來說,主從複製主要經歷四個階段:
第一階段:與master建立連線
第二階段:向master發起同步請求(SYNC)
第三階段:接受master發來的RDB資料
第四階段:載入RDB檔案
下面我們就通過一個圖來概述在每一個階段中,slave究竟做了些什麼:
關於上圖,有一點說明下:redis接收到slaveof master_host master_port命令後並沒有馬上與master建立連線,而是當執行伺服器例行任務serverCron,發現自己正處於REDIS_REPL_CONNECT狀態,這時才真正的向maser發起連線,虛擬碼:
Python程式碼
接著我們來看下主從複製過程中,master這邊的流程是如何,在具體看細節之前,我們先綜合來看master這邊主要做的幾件事情:
看完這個圖,你也許會有以下幾個疑問:
1. 為什麼在master傳送完RDB檔案後,還要定期的向slave傳送PING命令?
2. 在傳送完RDB檔案之後,master傳送的“變更”命令又是什麼,有什麼用?
在回答問題之前1,我們先回答問題2:
master儲存RDB檔案是通過一個子程序進行的,所以master依然可以處理客戶端請求而不被阻塞,但這也導致了在儲存RDB檔案期間,“鍵空間”可能發生變化(譬如接收到一個客戶端請求,執行"set name diaocow"命令),因此為了保證資料同步的一致性,master會在儲存RDB檔案期間,把接受到的這些可能變更資料庫“鍵空間”的命令儲存下來,然後放到每個slave的回覆列表中,當RDB檔案傳送完master會發送這些回覆列表中的內容,並且在這之後,如果資料庫發生變更,master依然會把變更的命令追加到回覆列表傳送給slave,這樣就可以保證master和slave資料的一致性!相關虛擬碼:
Python程式碼
由於在傳送完RDB檔案之後,master會不定時的給slave傳送“變更”命令,可能過1s,也可能過1小時,所以為了防止slave無意義等待(譬如master已經掛掉的情況),master需要定時傳送“保活”命令PING,以此告訴slave:我還活著,不要中斷與我的連線
現在我們就看下,當master接受到slave傳送的sync同步命令後究竟發生了哪些事:
上圖看似分支複雜,但我們抓住以下幾點即可:
1.儲存RDB檔案是在一個子程序中進行的;
2.如果master已經在儲存RDB檔案,但是沒有客戶端正在等待這次BGSAVE,新新增的slave需要等到下次BGSAVE,而不能直接使用這次生成的RDB檔案(原因圖中已經說明)
3.master會定期檢查RDB檔案是否儲存完畢(時間事件serverCron);
接下來我們看下,master是如何給每一個slave傳送RDB檔案的:
好了,至此我們已經分析完在主從複製過程中,master和slave兩邊分別是怎麼一個處理流程;最後,我繪製了一個圖,綜述了主從複製這一過程(我們可以邊看圖,邊回憶其中的具體細節):
PS:在主從複製過程中,任何一步發生錯誤,都會導致整個過程重頭開始,所以若RDB檔案很大又或是此時正處在業務高峰期,對系統性能將會有非常大的影響!
總結:
1. 瞭解主從複製master和slave的概念;
2. 瞭解主從複製執行過程,特別是其中關鍵的幾步;
3. 瞭解目前主從複製過程中尚存的不足之處;
由於圖片較大,縮放較為模糊,請雙擊開啟檢視原圖 ^_^
主從複製簡單來說就是把一臺redis資料庫中的資料同步到另一臺redis資料庫,並且按照資料流向,資料的傳送者我們稱作master,資料的接受者我們稱作slave(master/slave的劃分並不是那麼一定的,譬如B可以作為A的slave,但同時也可以作為C的master),下面就從slave和master的角度分別說明主從複製流程。
首先是slave端,對於slave端來說,主從複製主要經歷四個階段:
第一階段:與master建立連線
第二階段:向master發起同步請求(SYNC)
第三階段:接受master發來的RDB資料
第四階段:載入RDB檔案
下面我們就通過一個圖來概述在每一個階段中,slave究竟做了些什麼:
關於上圖,有一點說明下:redis接收到slaveof master_host master_port命令後並沒有馬上與master建立連線,而是當執行伺服器例行任務serverCron,發現自己正處於REDIS_REPL_CONNECT狀態,這時才真正的向maser發起連線,虛擬碼:
Python程式碼
- def serverCron():
- # 伺服器處於REDIS_REPL_CONNECT狀態
- if redisServer.repl_state == REDIS_REPL_CONNECT:
- # 向master發起連線
-
connectWithMaster()
- # 其他例行任務(省略)...
接著我們來看下主從複製過程中,master這邊的流程是如何,在具體看細節之前,我們先綜合來看master這邊主要做的幾件事情:
看完這個圖,你也許會有以下幾個疑問:
1. 為什麼在master傳送完RDB檔案後,還要定期的向slave傳送PING命令?
2. 在傳送完RDB檔案之後,master傳送的“變更”命令又是什麼,有什麼用?
在回答問題之前1,我們先回答問題2:
master儲存RDB檔案是通過一個子程序進行的,所以master依然可以處理客戶端請求而不被阻塞,但這也導致了在儲存RDB檔案期間,“鍵空間”可能發生變化(譬如接收到一個客戶端請求,執行"set name diaocow"命令),因此為了保證資料同步的一致性,master會在儲存RDB檔案期間,把接受到的這些可能變更資料庫“鍵空間”的命令儲存下來,然後放到每個slave的回覆列表中,當RDB檔案傳送完master會發送這些回覆列表中的內容,並且在這之後,如果資料庫發生變更,master依然會把變更的命令追加到回覆列表傳送給slave,這樣就可以保證master和slave資料的一致性!相關虛擬碼:
Python程式碼
- def processCommand(cmd, argc, argv):
- # 處理命令
- call(cmd, argc, argv)
- # 如果該命令造成資料庫鍵空間變化and當前redis是一個master,則同步變更命令
- if redisServer.update_key_space and len(redisServer.slaves) > 0:
- replicationFeedSlaves(cmd, argc, argv)
- def replicationFeedSlaves(cmd, argc, argv):
- # 把變更命令傳送給每一個處於:REDIS_REPL_WAIT_BGSAVE_END狀態的slave節點
- for slave in redisServer.slaves:
- if slave.replstate == REDIS_REPL_WAIT_BGSAVE_START:
- continue
- slave.updateNotify(cmd, argc, argv)
由於在傳送完RDB檔案之後,master會不定時的給slave傳送“變更”命令,可能過1s,也可能過1小時,所以為了防止slave無意義等待(譬如master已經掛掉的情況),master需要定時傳送“保活”命令PING,以此告訴slave:我還活著,不要中斷與我的連線
現在我們就看下,當master接受到slave傳送的sync同步命令後究竟發生了哪些事:
上圖看似分支複雜,但我們抓住以下幾點即可:
1.儲存RDB檔案是在一個子程序中進行的;
2.如果master已經在儲存RDB檔案,但是沒有客戶端正在等待這次BGSAVE,新新增的slave需要等到下次BGSAVE,而不能直接使用這次生成的RDB檔案(原因圖中已經說明)
3.master會定期檢查RDB檔案是否儲存完畢(時間事件serverCron);
接下來我們看下,master是如何給每一個slave傳送RDB檔案的:
好了,至此我們已經分析完在主從複製過程中,master和slave兩邊分別是怎麼一個處理流程;最後,我繪製了一個圖,綜述了主從複製這一過程(我們可以邊看圖,邊回憶其中的具體細節):
PS:在主從複製過程中,任何一步發生錯誤,都會導致整個過程重頭開始,所以若RDB檔案很大又或是此時正處在業務高峰期,對系統性能將會有非常大的影響!
總結:
1. 瞭解主從複製master和slave的概念;
2. 瞭解主從複製執行過程,特別是其中關鍵的幾步;
3. 瞭解目前主從複製過程中尚存的不足之處;