經過SLAVEOF命令或者設置slaveof選項,讓一個服務器(從服務器)去複製另外一個服務器(主服務器),達到「數據庫狀態一致」效果。redis
同步(sync)數據庫
命令傳播(command propagate)安全
同步後主服務器數據庫被修改,爲了讓主從服務器保持一致狀態,主服務器將本身執行的寫命令發送給從服務器執行相同的寫命令。服務器
複製可分爲初次複製和斷線後重複製網絡
斷線後重複製每次都須要執行一次SYNC命令,從新複製全部的數據庫數據,很是低效。ui
區別線程
Redis從2.8版本開始,使用PSYNC命令代替SYNC命令來執行復制時的同步問題。3d
PSYNC命令具備完整重同步和部分重同步兩種模式blog
完整重同步隊列
用於處理初次複製狀況,和SYNC初次複製基本一致。
部分重同步
用於處理斷線後重複製狀況,從服務器斷線重連後,在必定條件下,主服務器能夠將斷開期間執行的寫命令發送給從服務器。
部分重同步功能由如下三個部分構成:
1. 複製偏移量
主服務器每次向從服務器傳播N個字節數據,就將本身的複製偏移量的值加上N;
從服務器每次接收主服務器傳播來的N個字節數據,就將本身的複製偏移量的值加N。
經過對比主從服務器的偏移量就能夠判斷主從服務器是否處於一致狀態
2. 複製積壓緩衝區
複製積壓緩衝區是由主服務器維護的一個固定長度(fixed_size)先進先出(FIFO)隊列,默認大小爲1MB。
主服務器在進行命令傳播時,不只會將寫命令發送給從服務器,還會將寫命令入隊到複製積壓緩衝區,複製積壓緩衝區會爲隊列中的每一個字節記錄相應的複製偏移量。
從服務器斷開重連後會經過PSYNC命令將本身的複製偏移量offset發送給主服務器,主服務器根據這個複製偏移量決定執行何種同步操做。
offset偏移量以後的數據仍存在於複製積壓緩衝區,則執行部分重同步;
offset偏移量以後的數據不存在於複製積壓緩衝區,則執行完整重同步。
複製積壓緩衝區的大小能夠根據公式second * write_size_per_second來估算
secoond爲從服務器斷線重連所需的平均時間(以秒計算)
write_size_per_second爲主服務器平均每秒產生的寫命令數據量
通常修改配置文件中repl-backlog-size選項將複製積壓緩衝區大小設爲
2 * second * write_size_per_second
3. 服務器運行ID
每一個Redis服務器有本身的運行ID,運行ID在服務器啓動時自動生成,由40個隨機的十六進制字符組成。
從服務器對主服務器進行初次複製時,主服務器會將本身的運行ID傳送給從服務器,從服務器會將這個運行ID保存起來。
當從服務器斷線重連上一個主服務器時,從服務器會向當前鏈接的主服務器發送以前保存的運行ID。
從服務器:
若是從服務器沒有複製過任何主服務器或者執行過SLAVEOF no one命 令,則從服務器向主服務器發送PSYNC ? -1命令。請求完整重同步。
若是從服務器複製過某個主服務器,則從服務器向主服務器發送
PSYNC <runid> <offset>命令,主服務器根據兩個參數判斷執行哪一種同步操做。
主服務器:
經過SLAVEOF <master_ip> <master_port>,設置主從服務器
從服務器將主服務器的IP地址及端口保存到服務器狀態的masterhost屬性和masterport屬性。
從服務器根據命令中的IP地址和端口,建立連向主服務器的套接字鏈接
若是成功鏈接,從服務器爲該套接字關聯一個專門用於處理複製工做的文件事件處理器,如接受RDB文件,接受主服務器傳來的寫命令等。
若是接受鏈接,主服務器爲該套接字建立相應的客戶端狀態,這時候從服務器同時具備服務器和客戶端兩個身份。
從服務器成爲主服務器的客戶端以後,第一件事就是發送一個PING命令。
PING命令的做用:
- 檢查套接字的讀寫狀態是否正常
- 檢查主服務器可否正常處理命令請求,爲後續步驟作檢查
PING命令返回狀況:
主服務器返回了一個命令回覆,但從服務器不能在規定時限(timeout)內讀取出命令回覆內容,表示主從服務器之間的網絡鏈接狀態不佳,沒法繼續執行後續步驟。
(從服務器斷開並從新建立連向主服務器的套接字)
主服務器返回了一個錯誤,表示主服務器暫時無法處理從服務器的命令請求,沒法繼續執行後續步驟。
(從服務器斷開並從新建立連向主服務器的套接字)
從服務器讀取到「pong」回覆,表示主從服務器之間的網絡鏈接狀態正常,主服務器能正常處理命令請求,能夠繼續執行後續步驟。
根據從服務器是否設置了masterauth選項,決定是否進行身份驗證。
設置了masterauth:
從服務器向主服務器發送一條AUTH命令,命令參數爲從服務器masterauth選項的值
身份驗證的三種狀況:
主服務器沒有設置requirepass選項,從服務器也沒有設置masterauth選項,主服務器繼續執行從服務器發送的命令,複製工做繼續進行。
從服務器經過AUTH命令發送的密碼和主服務器requirepass選項設置的密碼相同,主服務器繼續執行從服務器發送的命令,複製工做繼續進行。若是不相同,主服務器返回一個invalid password錯誤。
若是主服務器設置了requirepass選項,從服務器沒有設置masterauth選項,主服務器返回一個NOAUTH錯誤;
若是主服務器沒有設置requirepass選項,從服務器設置了masterauth選項,主服務器返回一個no password is set錯誤。
從服務器執行命令REPLCONF listening-port <port-number>,向主服務器發送從服務器的監聽端口號。
主服務器將端口號記錄在從服務器對應的客戶端狀態的slave_listening_port屬性中,該屬性目前惟一的做用是在主服務器執行INFO replication命令時打印從服務器的端口號。
從服務器向主服務器發送PSYNC命令,執行同步操做
執行同步操做前,只有從服務器是主服務器的客戶端,執行同步操做後,主從服務器互爲對方的客戶端
(只有成爲客戶端,才能夠互相向對方發送命令請求或者返回命令回覆)
主服務器一直將執行的寫命令發送給從服務器,從服務器一直接收並執行主服務器發來的寫命令,保持主從一致。
命令傳播階段,從服務器每秒一次向主服務器發送命令:
REPLCONF ACK <replication_offset>,其中replication_offset爲從服務器當前的複製偏移量。
REPLCONF ACK命令的做用
主服務器超過一秒鐘沒有收到從服務器發來的REPLCONF ACK命令,則說明主從服務器之間的鏈接出現問題。
能夠經過INFO replication命令,在服務器列表的lag屬性查看從服務器上一次發送REPLCONF ACK距離如今的時間。(通常在0~1秒之間跳動)
Redis中的min-slaves-to-write和min-slaves-max-lag能夠防止主服務器在不安全的狀況下執行寫命令,這裏的min-slaves-max-lag就是上面提到的讀取的lag值。
從服務器在發送REPLCONF ACK命令時發送複製偏移量,若是由於網絡故障發生命令丟失,主從服務器複製偏移量不一樣,主服務器會根據從服務器提交的複製偏移量,在複製積壓緩衝區找到丟失的數據從新發送。
(不一樣於部分重同步,區別是有沒有斷線)