您好,登錄后才能下訂單哦!
小編給大家分享一下Redis中主從同步機制的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
之前的文章中詳細分析了redis的特性和核心原理,從本篇開始將對redis的部署結構和運行模式進行分析解讀。真正生產環境當中我們基本不會使用單節點的redis來提供服務,至少是主從結構的哨兵或者集群模式,以保障redis服務的可靠性。本篇就來詳細解讀下redis的主從同步機制。
一主N從的這種復制結構復制關系只有一級,也是使用最多的形式,通常搭建哨兵或者集群結構的redis都是采用的這種復制結構,能夠通過一級從節點的復制關系很好的保證服務的可用性,做到異常情況主從切換。
級聯復制結構的復制關系可以有多級,一個主節點的從節點可以是下屬從節點的主節點。級聯復制結構的應用相對比較少,這種結構能夠在有多個從節點的結構下一定程度上緩解主節點的復制壓力。
redis的主從同步始于命令SLAVEOF host port,通過這個命令能夠建立主從關系,SLAVEOF 命令用于在 Redis 運行時動態地修改復制功能的行為。通過執行 SLAVEOF host port 命令,可以將當前服務器轉變為指定服務器的從屬服務器(slave server)。如果當前服務器已經是某個主服務器(master server)的從屬服務器,那么執行 SLAVEOF host port 將使當前服務器停止對舊主服務器的同步,丟棄舊數據集,轉而開始對新主服務器進行同步。另外,對一個從屬服務器執行命令 SLAVEOF NO ONE 將使得這個從屬服務器關閉復制功能,并從從屬服務器轉變回主服務器,原來同步所得的數據集不會被丟棄。利用 SLAVEOF NO ONE 不會丟棄同步所得數據集這個特性,在沒有搭建哨兵和集群的情況下,可以在主服務器失敗的時候,將從屬服務器用作新的主服務器,從而實現無間斷運行。
下圖為主從關系建立流程:
注意:
根據上執行流程這里有一個需要注意點,當我們對一個已有主從關系的節點執行slaveof命令時,會結束掉現有的主從關系并清空節點下的所以數據,在生成環境當中這是比較威脅的操作。有沒有更安全的方式了?上面介紹slavelof命令的時候提到可以傳遞NO ONE參數,也就是執行SLAVEOF NO ONE命令,這個命令是只會結束主從復制關系不會清空數據的,相對安全很多。
建立好主從關系后就要進入主從數據同步的過程了,這里主要分三種情況,剛建立主從關系后的數據全量同步;初始化同步完成后的命令傳播階段;主從關系異常中斷重連后的同步方式選擇,這里會有全量和增量同步兩種場景。
當slave節點啟動后或斷開重連后(重連不滿足增量同步條件),會向master數據庫發送SYNC命令。
master節點收到SYNC命令后會開始在后臺保存快照(即RDB持久化,在主從復制時,會無條件觸發RDB),并將保存快照期間接收到的命令緩存起來。
master節點執行RDB持久化完成后,向所有slave節點發送快照RDB文件,并在發送快照期間繼續記錄被執行的寫命令。
slave節點收到快照文件后丟棄所有舊數據(會清空所有數據),載入收到的快照。
master節點快照發送完畢、slave節點載入快照完畢后,master節點開始向slave節點發送緩沖區中的寫命令。
slave節點完成對快照的載入,開始接收命令請求,并執行來自主數據庫緩沖區的寫命令。(從數據庫初始化完成)
master節點每執行一個寫命令就會向slave節點發送相同的寫命令,slave節點接收并執行收到的寫命令。(命令傳播操作,slave節點初始化完成后的操作)
全量同步流程如下圖:
在redis2.8之前,從節點無論是初始化還是斷線重連后都是采用全量同步的方式,在2.8之后版本,引入PSYNC命令,在從節點斷線重連后會判斷是否采用增量同步。
PSYNC具備了數據全量重同步和增量同步模式。
全量重同步:跟舊版復制基本是一致的,可以理解為“全量”復制。
部分重同步:salve斷開又重新連時,在命令傳播階段,只需要發送與master斷開這段時間執行的寫命給slave即可,可以理解為“增量”復制。
PSYNC執行過程中比較重要的概念有3個:runid、offset(復制偏移量)以及復制積壓緩沖區。
1.runid
每個Redis服務器都會有一個表明自己身份的ID。在PSYNC中發送的這個ID是指之前連接的Master的ID,如果沒保存這個ID,PSYNC的命令會使用”PSYNC ? -1” 這種形式發送給Master,表示需要全量復制。
2.offset(復制偏移量)
在主從復制的Master和Slave雙方都會各自維持一個offset。Master成功發送N個字節的命令后會將Master里的offset加上N,Slave在接收到N個字節命令后同樣會將Slave里的offset增加N。Master和Slave如果狀態是一致的那么它的的offset也應該是一致的。
3.復制積壓緩沖區
復制積壓緩沖區是由Master維護的一個固定長度環形積壓隊列(FIFO隊列),它的作用是緩存已經傳播出去的命令。當Master進行命令傳播時,不僅將命令發送給所有Slave,還會將命令寫入到復制積壓緩沖區里面。PSYNC執行過程和SYNC的區別在于:salve連接時,判斷是否需要全量同步,全量同步的邏輯過程和SYNC一樣。PSYNC執行步驟如下:
客戶端向服務器發送SLAVEOF命令,即salve向master發起連接請求時,slave根據自己是否保存Master runid來判斷是否是第一次連接。
如果是第一次同步則向Master發送 PSYNC ? -1 命令來進行完整同步;如果是重連接,會向Master發送PSYNC runid offset命令(runid是master的身份ID,offset是從節點同步命令的全局遷移量)。
Master接收到PSYNC 命令后,首先判斷runid是否和本機的id一致,如果一致則會再次判斷offset偏移量和本機的偏移量相差有沒有超過復制積壓緩沖區大小,如果沒有那么就給Slave發送CONTINUE,此時Slave只需要等待Master傳回失去連接期間丟失的命令。如果runid和本機id不一致或者offset差距超過了復制積壓緩沖區大小,那么就會返回FULLRESYNC runid offset,Slave將runid保存起來,并進行全量同步。
主節點在命令傳播時,主數據庫會將每一個寫命令傳遞給從數據庫的同時,都會將寫命令存放到積壓隊列,并記錄當前積壓隊列中存放命令的全局偏移量offset。當salve重連接時,master會根據從節點傳的offset在環形積壓隊列中找到斷開這段時間執行的命令,并同步給salve節點,達到增量同步結果。
PSYNC執行流程如下圖:
從以上PSYNC的執行流程可以看出當slave節點斷線重連以后判斷是否采用增量同步的核心是slave的offset偏移量和master的偏移量相差有沒有超過復制積壓緩沖區大小,那么這個大小是由以下參數來配置的。復制積壓緩沖區本質上是一個固定長度的循環隊列,默認情況下積壓隊列的大小為1MB,可以通過配置文件設置隊列大小:設置復制積壓緩沖區大小,積壓隊列越大,允許主從數據庫斷線的時間就越長
repl-backlog-size 1mb
Redis同時也提供了當沒有slave需要同步的時候,多久可以釋放環形隊列,默認一小時,沒有salve連接時,多久釋放一次復制積壓緩沖區
repl-backlog-ttl 3600
Redis采用了樂觀復制的策略,也就是在一定程度內容忍主從數據庫的內容不一致,但是保持主從數據庫數據的最終一致性。具體來說,Redis在主從復制的過程中,本身就是異步的,在主從數據庫執行完客戶端請求后會立即將結果返回給客戶端,并異步的將命令同步給從數據庫,但是這里并不會等待從數據庫完全同步之后,再返回客戶端。這一特性雖然保證了主從復制期間性能不受影響,但是也會產生一個數據不一致的時間窗口,如果在這個時間窗口期間網絡突然斷開連接,就會導致兩者數據不一致。如果不在配置文件中添加其他策略,那就默認會采用這種方式。為了防止主從不一致不可控,redis提供了以下兩個參數來做約束:
min-slaves-to-write 3 min-slaves-max-lag 10
當slave數量小于min-slaves-to-write,且延遲小于等于min-slaves-max-lag時,master停止寫入操作。
還有一個參數也會影響主從之間的延時:
repl-disable-tcp-nodelay:
設置成yes,則redis會合并小的TCP包從而節省帶寬,但會增加同步延遲,造成master與slave數據不一致。設置成no,則redis master會立即發送同步數據,幾乎沒有延遲。
Redis的主從同步無論那種場景可以抽象為以下七個步驟:
1.建立socket連接
從服務器根據設置的套接字創建連向主服務器的套接字連接,主服務器接收從服務器的套接字連接之后,為該套接字創建響應的客戶端狀態,并將此時的從服務器看做是主服務器的客戶端,也就是該從服務器同時具備服務器與客戶端兩個身份。
2.發送PING命令
PING命令主要有兩種作用:雖然建立了套接字連接,但是還未使用過,通過發送PING命令檢查套接字的讀寫狀態是否正常;通過發送PING命令檢查主服務器能否正常處理命令請求,能處理主服務器回復PONG。
3.身份驗證
從服務器接收到主服務器返回的“PONG”回復,接下來就需要考慮身份驗證的事。如果從服務器設置了masterauth選項,那么進行身份驗證,如果從服務器沒有設置masterauth選項,那么不進行身份驗證。
4.發送端口信息
在身份驗證步驟之后,從服務器將執行命令REPLCONF listening-port ,向主服務器發送從服務器的監聽端口號。
5.數據同步
從服務器向主服務器發送SYNC命令、PSYNC命令,執行同步操作。
6.命令傳播
主從服務器就會進入命令傳播階段,主服務器只要將自己執行的寫命令發送給從服務器,而從服務器只要一直執行并接收主服務器發來的寫命令。
以上是“Redis中主從同步機制的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。