redis系列:主從複製

1 簡介

這篇文章主要講述Redis的主從複製功能。會依次從環境搭建、功能測試和原理分析幾個方面進行介紹。node

2 準備工做

服務器架構圖以下
git

啓動主服務器101,使用info replication命令查看狀態,能夠看到role爲master(也就是角色爲主主服務器),connected_salaves的值爲0(從服務器數量爲0)
github

接下來用修改配置文件的方式將102機器加入的主從複製當中redis

而後再用命令的方式一樣將103機器加入的主從複製當中。數據庫

2.1 用修改配置文件的方式將102機器加入到主從

ip地址爲192.168.17.102的機器的Redis配置文件增長slaveof 192.168.17.101 6379
啓動102的redis,狀態以下
緩存

能夠看到role變爲slave(角色爲從服務器),master_host(主服務器IP地址)爲192.168.17.101,master_port(主服務器端口)爲6379。
此時101主服務器的主從狀態以下,能夠看到connected_salaves的值變爲1,以及增長了一行slave0(從服務器的狀態)
bash

2.2 用命令的方式將103機器加入到主從

未執行slaveof命令的主從狀態以下
服務器

開始執行slaveof命令網絡

192.168.17.103:6379> slaveof 192.168.17.101 6379
OK
複製代碼

再次查看狀態,能夠看到角色已經變成從服務器架構

如今再來看看主服務器的狀態,能夠看到從服務器數量變成2,又多了一條從服務器的信息

到這裏主從環境就搭好了,如今來測試一波

2.3 測試

如今主服務器101輸入命令

192.168.17.101:6379> set 101 101
OK
複製代碼

而後在從服務器102上查看全部的鍵,發現有鍵101,接着設置鍵102

192.168.17.102:6379> keys *
1) "101"
192.168.17.102:6379> get 101
"101"
192.168.17.102:6379> set 102 102
(error) READONLY You can't write against a read only slave. 複製代碼

發現出現錯誤(error) READONLY You can't write against a read only slave. 後面在講述出錯緣由

如今在從服務器103上查看全部的鍵,發現也有101

192.168.17.103:6379> keys *
1) "101"
複製代碼

再向主服務器101輸入命令

192.168.17.101:6379> set ip ip
OK
複製代碼

而後到從服務器103上查看全部的鍵

192.168.17.103:6379> keys *
1) "101"
2) "ip"
複製代碼

能夠看到多了一個鍵,說明主服務的數據同步到了從服務器上,操做過程看下圖

2.4 其餘

2.4.1 (error) READONLY You can't write against a read only slave.

出現錯誤(error) READONLY You can't write against a read only slave. 是由於 從節點默認是隻讀的,如需修改能夠再配置文件中修改下面這個屬性

slave-read-only yes
複製代碼

2.4.2 主服務器設置密碼

當主服務設置密碼時,配置文件須要增長如需參數

masterauth <master-password>
複製代碼

3 實現原理

當我在從服務器103上輸入slaveof命令時,出現以下日誌

總的來講主從複製功能的詳細步驟能夠分爲7個步驟:

  1. 設置主服務器的地址和端口
  2. 創建套接字鏈接
  3. 發送PING命令
  4. 身份驗證
  5. 發送端口信息
  6. 同步
  7. 命令傳播

接下來分別敘述每一個步驟

3.1設置主服務器的地址和端口

主從複製的第一步就是設置主服務器的地址和端口,當輸入slaveof命令或者在配置文件中配置信息時,從服務器會將主服務器的ip地址和端口號保存到服務器狀態的屬性裏面。

3.2 創建套接字鏈接

在slaveof命令執行以後,從服務器會根據設置的ip和端口,向主服務器簡歷socket鏈接。

3.3 發送PING命令

socket鏈接成功後,從服務器會發送一PING命令給主服務器。

這時候PING命令能夠檢查socket的讀寫狀態是否正常,還能夠檢查主服務器可否正常處理命令請求。

從服務器在發送PING命令時可能趕上的狀況以下圖

圖片來自Redis設計與實現

3.4 身份驗證

從服務器收到主服務器的PONG回覆後,會檢查從服務器是否設置masterauth,設置則進行身份驗證,未設置則跳過該步驟。從服務器在身份驗證時可能趕上的狀況以下

圖片來自Redis設計與實現

3.5 發送端口信息

身份驗證經過後,從服務器會向主服務器發送本身的監聽端口號。主服務器收到以後會將端口號記錄到從服務器對應的狀態屬性中。在主服務器調用info replication能夠看到從服務器的port,以下

3.6 同步

發送端口信息以後,從服務器會向主服務器發送PSYNC命令,執行同步操做,並將本身的數據庫同步至主服務器數據庫當前的狀態。

同步這塊內容會在後面詳細描述

3.7 命令傳播

當完成同步操做以後,主從服務器便會進入命令傳播階段。這時候主從服務器的數據是一致的,當主服務器有新的寫命令時,會將改命令發送給從服務器,從服務器接收命令並執行即可以保證與主服務器的數據保持一致。
那麼Redis是如何保證主從服務器一致處於鏈接狀態以及命令是否丟失?
答:命令傳播階段,從服務器會利用心跳檢測機制定時的向主服務發送消息。
從服務器發送的命令以下

REPLCONF ACK <replication_offset>
複製代碼

replication_offset表示從服務器當前的複製偏移量
接下來看看心跳機制

3.7.1 心跳檢測機制

心跳檢測機制的做用有三個:

  1. 檢查主從服務器的網絡鏈接狀態
  2. 輔助實現min-slaves選項
  3. 檢測命令丟失

3.7.1.1 檢查主從服務器的網絡鏈接狀態

主服務器信息中能夠看到所屬的從服務器的鏈接信息,state表示從服務器狀態,offset表示複製偏移量,lag表示延遲值(幾秒以前有過心跳檢測機制)

3.7.1.2 輔助實現min-slaves選項

Redis.conf配置文件中有下方兩個參數

# 未達到下面兩個條件時,寫操做就不會被執行
# 最少包含的從服務器
# min-slaves-to-write 3
# 延遲值
# min-slaves-max-lag 10
複製代碼

若是將兩個參數的註釋取消,那麼若是從服務器的數量少於3個,或者三個從服務器的延遲(lag)大於等於10秒時,主服務器都會拒絕執行寫命令。

3.7.1.3 檢測命令丟失

在從服務器的鏈接信息中能夠看到複製偏移量,若是此時主服務器的複製偏移量與從服務器的複製偏移量不一致時,主服務器會補發缺失的數據。

4 同步原理

同步分爲全量重同步和部分重同步。那麼是什麼決定採起全量重同步仍是部分重同步操做?

圖片來自Redis設計與實現

4.1 全量重同步

全量重同步的步驟以下

  1. 主節點收到從服務器的全量重同步請求時,主服務器便開始執行bgsave命令,同時用一個緩衝區記錄從如今開始執行的全部寫命令。
  2. 當主服務器的bgsave命令執行完畢後,會將生成的RDB文件發送給從服務器。從服務器接收到RDB文件時,會將數據文件保存到硬盤,而後加載到內存中。
  3. 主服務器將緩衝區全部緩存的命令發送到從服務器,從服務器接收並執行這些命令,將從服務器同步至主服務器相同的狀態。

4.2 部分重同步

要想了解部分重同步的步驟,須要先了解部分重同步所須要的幾個屬性

  1. 複製偏移量
  2. 複製緩衝區
  3. 運行ID

4.2.1 複製偏移量

從主服務器的複製信息能夠看到從服務器slave0和slave1都有一個參數offset,這個參數就是從服務器的複製偏移量。master_repl_offset這個參數就是主服務器的偏移量。以下圖

主服務器的複製偏移量保存向從服務器發送過的字節數據。
從服務器的複製偏移量保存着從主服務器接收的字節數據。
經過對比主服務器和從服務器的複製偏移量就能夠知道命令是否丟失,丟失則補發複製偏移量相差的字節命令。
那麼這些字節數據是存放在哪裏的呢?

4.2.2 複製緩衝區

這些字節數據都是存放在主服務器的複製緩衝區裏的。複製緩衝區是一個固定長度(fixed-size)先進先出(FIFO)的隊列,默認大小爲1MB。默認大小能夠對下方的參數進行修改

# repl-backlog-size 1mb
複製代碼

那麼複製緩衝區的數據是何時加入進去的呢?

答:在命令傳播階段,主節點除了將寫命令發送給從節點,還會發送一份給複製積壓緩衝區。

複製緩衝區裏面會保存着一部分最傳播的寫命令和每一個字節相應的複製偏移量。

因爲複製緩衝區的大小是有限制的,因此保存的數據也是有限制的。若是從服務器與主服務器的複製偏移量相差的數據大於複製緩衝去存儲的數據時,一樣不會執行部分重同步。

舉個例子,主服務器的複製偏移量爲20000、緩衝區能保存的數據只有5000,從服務器的複製偏移量爲10000。這時從服務器與主服務器複製偏移量10000,而緩衝區只有5000,那麼仍是會執行全量重同步。若是相差的複製偏移量小於5000,纔會執行部分重同步。

4.2.3 運行ID

每一個Redis服務器啓動時,都會有自動生成本身的運行ID。
當從服務器對主服務器進行初次複製時,主服務器會發送本身的運行ID給從服務器。
當從服務器斷線重連時,會將以前主服務器的運行ID發送給當前鏈接的主服務器。這時候會出現下面兩種狀況

  1. 運行ID和主服務器一致,主服務器能夠嘗試執行部分重同步操做。
  2. 運行ID和主服務器不一致,說明以前鏈接的主服務器與此次鏈接不一樣,開始執行全量重同步操做。

5 相關配置

################################# REPLICATION #################################

# slaveof <主服務器ip> <主服務器端口>
# slaveof <masterip> <masterport>

# masterauth <主服務器Redis密碼>
# masterauth <master-password>

# 當slave丟失master或者同步正在進行時,若是發生對slave的服務請求
# yes則slave依然正常提供服務
# no則slave返回client錯誤:"SYNC with master in progress"
slave-serve-stale-data yes

# 指定slave是否只讀
slave-read-only yes

# 無硬盤複製功能
repl-diskless-sync no

# 無硬盤複製功能間隔時間
repl-diskless-sync-delay 5

# 從服務器發送PING命令給主服務器的週期
# repl-ping-slave-period 10

# 超時時間
# repl-timeout 60

# 是否禁用socket的NO_DELAY選項
repl-disable-tcp-nodelay no

# 設置主從複製容量大小,這個backlog 是一個用來在 slaves 被斷開鏈接時存放 slave 數據的 buffer
# repl-backlog-size 1mb

# master 再也不鏈接 slave時backlog的存活時間。
# repl-backlog-ttl 3600

# slave的優先級
slave-priority 100

# 未達到下面兩個條件時,寫操做就不會被執行
# 最少包含的從服務器
# min-slaves-to-write 3
# 延遲值
# min-slaves-max-lag 10
複製代碼

結語

主從的配置文件:[https://github.com/rainbowda/learnWay/tree/master/learnRedis/replication,有須要能夠下載。

Redis的主從複製功能就介紹到這裏了。雖說主從解決了讀寫分離,讀數據的負載均衡,可是一旦某個節點出現故障,不能自動回覆,主從切換等功能。因此就有了哨兵的功能。

相關文章
相關標籤/搜索