從零單排學Redis【鉑金一】

前言

只有光頭才能變強git

好的,今天咱們要上鉑金段位了,若是還沒經歷過青銅和白銀和黃金階段的,能夠先去蹭蹭經驗再回來:github

這篇文章主要講的是Redis主從複製。由於Redis集羣的知識點有點多,因此鉑金上分得要好幾篇~數據庫

文本力求簡單講清每一個知識點,但願你們看完能有所收穫服務器

1、主從架構

1.1爲何要主從架構

Redis也跟關係型數據(MySQL)同樣,若是有過多請求仍是撐不住的。網絡

一臺Redis撐不住

由於Redis若是隻有一臺服務器的話,那隨着請求愈來愈多:架構

  • Redis的內存是有限的,可能放不下那麼多的數據
  • 單臺Redis支持的併發量也是有限的
  • 萬一這臺Redis掛了,全部的請求全走關係數據庫了,那就更炸了。

顯然,出現的上述問題是由於一臺Redis服務器不夠,因此多搞幾臺Redis服務器就能夠了併發

多搞幾臺Redis服務器

爲了實現咱們服務的高可用性,能夠將這幾臺Redis服務器作成是主從來進行管理設計

主從架構

tip:Redis做者已將Master/Slave架構更名爲Master/Replica3d

1.2主從架構的特色

下面咱們來看看Redis的主從架構特色:code

  • 服務器負責接收請求
  • 服務器負責接收請求
  • 從服務器的數據由主服務器複製過去。主從服務器的數據是一致

主從架構特色

主從架構的好處

  • 讀寫分離(主服務器負責寫,從服務器負責讀)
  • 高可用(某一臺從服務器掛了,其餘從服務器還能繼續接收請求,不影響服務)
  • 處理更多的併發量(每臺從服務器均可以接收讀請求,讀QPS就上去了)

主從架構除了上面的形式,也有下面這種的(只不過用得比較少):

從服務器又掛着從服務器

2、複製功能

主從架構的特色之一:主服務器和從服務器的數據是一致的。

由於主服務器是能接收寫請求的,主服務器處理完寫請求,會作什麼來保證主從數據的一致性呢?若是主從服務器斷開了,過一陣子才重連,又會怎麼處理呢?下面將會了解到這些細節~

在Redis中,用戶能夠經過執行SALVEOF命令或者設置salveof選項,讓一個服務器去複製(replicate)另外一個服務器,咱們稱呼被複制的服務器爲主服務器(master),而對主服務器進行復制的服務器則被稱爲從服務器(salve)

複製

2.1複製功能的具體實現

複製功能分爲兩個操做:

  • 同步(sync)
    • 將從服務器的數據庫狀態更新至主服務器的數據庫狀態
  • 命令傳播(command propagate)
    • 主服務器的數據庫狀態被修改,致使主從服務器的數據庫狀態不一致,讓主從服務器的數據庫狀態從新回到一致狀態

主從數據一致性

從服務器對主服務器的同步又能夠分爲兩種狀況

  • 初次同步:從服務器沒有複製過任何的主服務器,或者從服務器要複製的主服務器跟上次複製的主服務器不同
  • 斷線後同步:處於命令傳播階段的主從服務器由於網絡緣由中斷了複製,從服務器經過自動重連從新鏈接主服務器,並繼續複製主服務器

在Redis2.8之前,斷線後複製這部分其實缺乏的只是部分的數據,可是要讓主從服務器從新執行SYNC命令,這樣的作法是很是低效的。(由於執行SYNC命令是把全部的數據再次同步,而不是隻同步丟失的數據)

接下來咱們來詳細看看Redis2.8之後複製功能是怎麼實現的:

2.1.1複製的前置工做

首先咱們來看一下前置的工做

  • 從服務器設置主服務器的IP和端口
  • 創建與主服務器的Socket鏈接
  • 發送PING命令(檢測Socket讀寫是否正常與主服務器的通訊情況)
  • 身份驗證(看有沒有設置對應的驗證配置)
  • 從服務器給主服務器發送端口的信息,主服務器記錄監聽的端口

Redis複製的前置工做

前面也提到了,Redis2.8以前,斷線後同步會從新執行SYNC命令,這是很是低效的。下面咱們來看一下Redis2.8以後是怎麼進行同步的。

Redis從2.8版本開始,使用PSYNC命令來替代SYNC命令執行復制時同步的操做。

PSYNC命令具備完整重同步和部分重同步兩種模式(其實就跟上面所說的初次複製和斷線後複製差很少個意思)。

2.1.2完整重同步

下面先來看看完整重同步是怎麼實現的:

  • 從服務器向主服務器發送PSYNC命令
  • 收到PSYNC命令的主服務器執行BGSAVE命令,在後臺生成一個RDB文件。並用一個緩衝區來記錄從如今開始執行的全部寫命令
  • 當主服務器的BGSAVE命令執行完後,將生成的RDB文件發送給從服務器,從服務器接收和載入RBD文件。將本身的數據庫狀態更新至與主服務器執行BGSAVE命令時的狀態。
  • 主服務器將全部緩衝區的寫命令發送給從服務器,從服務器執行這些寫命令,達到數據最終一致性。

完整重同步

2.1.2部分重同步

接下來咱們來看看部分重同步,部分重同步可讓咱們斷線後重連只須要同步缺失的數據(而不是Redis2.8以前的同步所有數據),這是符合邏輯的!

部分重同步功能由如下部分組成:

  • 主從服務器的複製偏移量
  • 主服務器的複製積壓緩衝區
  • 服務器運行的ID(run ID)

首先咱們來解釋一下上面的名詞:

複製偏移量:執行復制的雙方都會分別維護一個複製偏移量

  • 主服務器每次傳播N個字節,就將本身的複製偏移量加上N
  • 從服務器每次收到主服務器的N個字節,就將本身的複製偏移量加上N

經過對比主從複製的偏移量,就很容易知道主從服務器的數據是否處於一致性的狀態!

複製偏移量

那斷線重連之後,從服務器向主服務器發送PSYNC命令,報告如今的偏移量是36,那麼主服務器該對從服務器執行完整重同步仍是部分重同步呢??這就交由複製積壓緩衝區來決定。

當主服務器進行命令傳播時,不只僅會將寫命令發送給全部的從服務器,還會將寫命令入隊到複製積壓緩衝區裏面(這個大小能夠調的)。若是複製積壓緩衝區存在丟失的偏移量的數據,那就執行部分重同步,不然執行完整重同步。

服務器運行的ID(run ID)實際上就是用來比對ID是否相同。若是不相同,則說明從服務器斷線以前複製的主服務器和當前鏈接的主服務器是兩臺服務器,這就會進行完整重同步。

因此流程大概如此:

同步的流程

2.1.3命令傳播

當完成了同步以後,主從服務器就會進入命令傳播階段。這時主服務器只要將本身的寫命令發送給從服務器,而從服務器接收並執行主服務器發送過來的寫命令,就能夠保證主從服務器一直保持數據一致了!

在命令傳播階段,從服務器默認會以每秒一次的頻率,向服務器發送命令REPLCONF ACK <replication_offset> 其中replication_offset是從服務器當前的複製偏移量

發送這個命令主要有三個做用:

  • 檢測主從服務器的網絡狀態
  • 輔助實現min-slaves選項
  • 檢測命令丟失

5、最後

畫了很久很久的圖,終於寫完啦。

拋個問題:若是從服務器掛了,不要緊,咱們通常會有多個從服務器,其餘的請求能夠交由沒有掛的從服務器繼續處理。若是主服務器掛了,怎麼辦?由於咱們的寫請求由主服務器處理,只有一臺主服務器,那就沒法處理寫請求了?

問題留到下篇解決~~

參考資料:

  • 《Redis設計與實現》
  • 《Redis實戰》

若是你以爲我寫得還不錯,瞭解一下:

  • 堅持原創的技術公衆號:Java3y。
  • 文章的目錄導航(精美腦圖+海量視頻資源):github.com/ZhongFuChen…
相關文章
相關標籤/搜索