Redis主從複製機制

本文將分享關於redis主從複製的實現原理。主從複製在操作上很簡單,
但大家未必瞭解它的底層實現,下面就分享一下redis是如何實現主從
複製的。

引言

主從複製有兩種方式,分別爲同步和命令傳播。在從服務器上通過命令slave of host port來實現從主服務器上同步數據。

老版本主從複製

主從複製分爲兩步,同步(SYNC)和命令傳播:
主從複製流程
上圖是主從複製的流程:

  • 首先從服務器發起同步請求給主服務器,主服務器接到請求後,將在後臺執行bgsave生成rdb持久化文件,在此過程中接收到客戶端的請求會將命令存放到緩衝區中。
  • 主服務器生成rdb持久化文件完成後,將文件發送給從服務器,從服務器執行rdb文件後,將返回給主服務器一個響應。
  • 主服務器接收到從服務器發過來的響應後,將緩衝區中的所有命令發送給從服務器。
  • 從服務器接收到主服務器發來的命令後,執行這些命令,即完成了一次複製的過程。

但是這個模式是有問題的,如果從服務器在命令傳播的時候與主服務器斷開了連接,之後又重新發起了連接,然後在進行主從複製操作,但此時,主服務器不知道從服務器複製到哪個命令了,無法重新進行命令傳播,只能從新全量同步目前主服務器上的數據,這樣就造成了不必要的IO。爲了解決這個問題,在新版本的redis中,通過PSYNC同步操作來實現全量複製和部分複製。

新版本主從複製

在新版本中,主從複製的流程和老版本大致一致,只是在主服務器執行bgsave的時候,如果此時客戶端發來請求,服務器會將請求命令存入到一個叫做複製積壓緩衝區中,這個複製積壓緩衝區大小默認爲1M,數據結構爲一個鏈表,記錄着當前命令的偏移量和當前命令。當從服務器執行完bgsave的時候,主服務器會將複製積壓緩衝區中的所有命令發給從服務器,並記錄發送的最後一個命令的偏移量,當從服務器接受到指令後,記錄主服務器發來的最後一個偏移量並進行執行命令,如果此時主從服務器斷開連接,那麼在從新連接上後,從服務器再次發起複製請求後,會將之前從服務器處理完的最後一個命令的偏移量發送給主服務器,主服務器就會在複製積壓緩衝區中找到對應的偏移量所屬的命令,從這個命令開始到複製積壓緩存區中最後的命令全部發送給從服務器,也叫做部分複製;如果從服務器給主服務器的偏移量已經不在複製積壓緩存區了,那麼就會進行全量複製,也就是主服務器在後臺執行bgsave操作,然後發給從服務器。這樣就不會每次斷開連接,再重新連接上後都做一次全量複製,避免了不必要的開銷。

心跳檢測

從服務器每一秒中會向主服務器發送一個REPLCONF ACK 指令,來進行心跳檢測。其中是從服務器的複製偏移量。心跳檢測有三個作用:

  • 檢測主從服務器網絡連接狀態。當主服務器超過1秒沒有接受到從服務器的心跳請求後,那麼主服務器就知道該從服務器與自己的連接出現了故障。
  • 檢測min-slave配置項。當在主服務器上配置
    min-slave-to-write=3
    min-slave-max-lag=10
    也就是如果主服務器的從服務器數量少於3個或者存在從服務器超過10秒沒有與主服務器進行心跳請求,那麼此時主服務器就拒絕接收客戶端發來的寫命令。
  • 檢測命令丟失。通過參數可以確定命令是否丟失。在進行命令傳播的過程中,主服務器發送給從服務器命令後會記錄複製偏移量,然後將命令發送給從服務器。從服務器執行後也會記錄複製偏移量。offset就是從服務器執行的最後一個命令的偏移量。如果主服務當前的複製偏移量爲200,但是從服務器發來的是198,那麼199和200這兩個命令就是在傳輸過程中丟失了,此時主服務器會將199和200這兩個命令再次發送給從服務器。

最後

如果本文對你有價值,哪怕一點點,請記得關注、點贊,有不足或疑問之處請留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章