主從複製是指用戶能夠搭建多個服務器,其中幾個服務器當作主服務器,提供寫功能。其他的服務器當作從服務器,提供讀功能。每當主服務器收到寫請求時,同時須要把數據發送給從服務器。保證主從服務器的數據保持最終一致性。利用這個機制,能夠利用廉價的服務器搭建高可用,高併發集羣。主從複製是搭建高可用集羣的必備利器。java
在Redis中可使用slaveof命令讓一個Redis實例去複製另外一個Redis實例的內容。這裏須要注意當A實例執行該命令去複製B實例的內容後,之前A實例的內容都將被B實例的內容覆蓋。同時在從服務器將被設置爲只讀,向從服務器發送寫命令時,將被拒絕。(也能夠在redis.conf中配置該命令,啓動時就發起主從同步)redis
當從服務器發起slaveof命令後,主從服務器之間經過TCP長鏈接進行通訊,主要是如下步驟:緩存
第一次完整的主從同步就完成了。而後主從之間會維持TCP鏈接,每次master收到新的寫命令後,都會發給從服務器。服務器
若是期間鏈接斷了,當從服務器從新連上主服務器後,上述的步驟會從新來一遍。能夠發現這是很低效的,由於主服務器只須要把斷連期間的寫入命令發給從服務器就能夠了,不須要從新生成RDB文件。(生成RDB文件是一個耗時操做,設計磁盤的讀寫)。網絡
注意:從服務器在加載RDB文件過程當中是阻塞的,沒法處理客戶端的請求。併發
基於上述緣由(特別是斷線時間特別短時),Redis推出了新的同步命令psync。高併發
psync將同步過程分爲了兩塊:一、完整同步;二、部分同步。spa
完整同步也叫初次同步,也就是第一次主從同步。步驟跟v1上述是一致的。設計
部分同步主要用戶斷線重連後的同步,它能夠將斷線期間的寫入命令發送給從服務器,而不須要整個RDB文件,極大的節約了資源。當從服務器從新鏈接了主服務器後,會發送psync命令,而後主服務器回覆continue命名,而且發送缺乏的寫入命令到從服務器。code
redis完成部分同步功能主要依賴於如下部分:
一、主服務器的複製偏移量
二、從服務器的複製偏移量
三、命令緩存區(FIFO隊列,默認大小1MB)
四、服務器運行Id
每次主服務器向從服務器傳遞N個字節命令後,就在把本身的偏移量+N。從服務器同理。同時主服務器還會將命令寫入到命令緩存區裏。當從服務器重連是發生以下步驟:
每一個Redis都有本身的惟一標識Id。在啓動時自動生成,由40個隨機的十六進制字符組成。當發送第一次主從同步時,master會將本身的id發送會從服務器,從服務器會將其保存起來。斷線重連時,從服務器請求同步時還會將這個id發送給主服務器,主服務器判斷該id與本身的id是否一致,若是一致則繼續執行部分同步的剩餘步驟。不然執行完整同步。
主從服務器創建鏈接後,默認每隔1秒,從服務器會想主服務器發送REPLCONF_ACK <offset>
報告本身的狀態。
主服務器能夠從這個命令中檢測出幾個問題:
一、主從之間的網絡鏈接狀態
若是主服務器在規則時間內沒有收到從服務器的心跳命令,就能夠認爲主從之間出現了問題。這個時候若是配置了
```java
複製代碼
min-slaves-to-write 3 min-slaves-max-lag 10
//若是從服務器數小於3或者3個服務器的心跳檢測延遲值都大於等於10秒,主服務器將拒絕寫命令 ```
二、檢測新的寫命令是否丟失
每次主服務器收到從服務器心跳命令裏的offset時,都會與本身的offset進行比較,若是小於本身的。那麼能夠知道某次傳遞的寫命令在網絡上丟失或者從服務器加載失敗,這個時候主服務器會主動將這部分缺乏的命令發送給從服務器(須要缺失命令還在緩存區,若是不在猜想應該是發起一次完整同步,未驗證過)。
三、輔助實現min-slaves
主從服務器創建套接字鏈接後,從服務器首先會發起Ping命令檢測套接字的讀寫是否正常。收到主服務器的Pong命令後證實正常。而後在判斷主服務器是否須要身份認證,發起密碼。而後進行復制流程。