和MySQL主從複製的緣由同樣,Redis雖然讀取寫入的速度都特別快,可是也會產生讀壓力特別大的狀況。爲了分擔讀壓力,Redis支持主從複製,Redis的主從結構能夠採用一主多從或者級聯結構,Redis主從複製能夠根據是不是全量分爲全量同步和增量同步。node
1、概念redis
主從複製,是指將一臺Redis服務器的數據,複製到其餘的Redis服務器。前者稱爲主節點(master),後者稱爲從節點(slave);數據的複製是單向的,只能由主節點到從節點。默認狀況下,每臺Redis服務器都是主節點;且一個主節點能夠有多個從節點(或沒有從節點),但一個從節點只能有一個主節點。服務器
2、做用網絡
1.主從複製實現了數據的熱備份,是持久化以外的一種數據冗餘方式。併發
2.當主節點出現問題時,能夠由從節點提供服務,實現快速的故障恢復;其實是一種服務的冗餘。負載均衡
3.在主從複製的基礎上,配合讀寫分離,能夠由主節點提供寫服務,由從節點提供讀服務(即寫Redis數據時應用鏈接主節點,讀Redis數據時應用鏈接從節點),分擔服務器負載;尤爲是在寫少讀多的場景下,經過多個從節點分擔讀負載,能夠大大提升Redis服務器的併發量。異步
4.高可用基石:除了上述做用之外,主從複製仍是哨兵和集羣可以實施的基礎,所以說主從複製是Redis高可用的基礎。socket
3、創建複製tcp
須要注意,主從複製的開啓,徹底是在從節點發起的;不須要咱們在主節點作任何事情。函數
從節點開啓主從複製,有3種方式:
(1)配置文件
在從服務器的配置文件中加入:slaveof masterip masterport
(2)啓動命令
redis-server啓動命令後加入 --slaveof masterip masterport
(3)客戶端命令
Redis服務器啓動後,直接經過客戶端執行命令:slaveof masterip masterport,則該Redis實例成爲從節點。
上述3種方式是等效的,下面以客戶端命令的方式爲例,看一下當執行了slaveof後,Redis主節點和從節點的變化。
經過slaveof masterip masterport命令創建主從複製關係之後,能夠經過slaveof no one斷開。須要注意的是,從節點斷開復制後,不會刪除已有的數據,只是再也不接受主節點新的數據變化。
4、實現步驟
創建鏈接
1、保存主節點信息
從節點服務器內部維護了兩個字段,即masterhost和masterport字段,用於存儲主節點的ip和port信息。
須要注意的是,slaveof是異步命令,從節點完成主節點ip和port的保存後,向發送slaveof命令的客戶端直接返回OK,實際的複製操做在這以後纔開始進行。
2、創建socket鏈接
從節點每秒1次調用複製定時函數replicationCron(),若是發現了有主節點能夠鏈接,便會根據主節點的ip和port,建立socket鏈接。若是鏈接成功,則:
從節點:爲該socket創建一個專門處理複製工做的文件事件處理器,負責後續的複製工做,如接收RDB文件、接收命令傳播等。
主節點:接收到從節點的socket鏈接後(即accept以後),爲該socket建立相應的客戶端狀態,並將從節點看作是鏈接到主節點的一個客戶端,後面的步驟會以從節點向主節點發送命令請求的形式來進行。
3、發送ping命令
從節點成爲主節點的客戶端以後,發送ping命令進行首次請求,目的是:檢查socket鏈接是否可用,以及主節點當前是否可以處理請求。
從節點發送ping命令後,可能出現3種狀況:
(1)返回pong:說明socket鏈接正常,且主節點當前能夠處理請求,複製過程繼續。
(2)超時:必定時間後從節點仍未收到主節點的回覆,說明socket鏈接不可用,則從節點斷開socket鏈接,並重連。
(3)返回pong之外的結果:若是主節點返回其餘結果,如正在處理超時運行的腳本,說明主節點當前沒法處理命令,則從節點斷開socket鏈接,並重連。
4、身份驗證
若是從節點中設置了masterauth選項,則從節點須要向主節點進行身份驗證;沒有設置該選項,則不須要驗證。從節點進行身份驗證是經過向主節點發送auth命令進行的,auth命令的參數即爲配置文件中的masterauth的值。
若是主節點設置密碼的狀態,與從節點masterauth的狀態一致(一致是指都存在,且密碼相同,或者都不存在),則身份驗證經過,複製過程繼續;若是不一致,則從節點斷開socket鏈接,並重連。
5、發送從節點端口信息
身份驗證以後,從節點會向主節點發送其監聽的端口號(前述例子中爲6380),主節點將該信息保存到該從節點對應的客戶端的slave_listening_port字段中;該端口信息除了在主節點中執行info Replication時顯示之外,沒有其餘做用。
數據同步
主從節點之間的鏈接創建之後,即可以開始進行數據同步,該階段能夠理解爲從節點數據的初始化。具體執行的方式是:從節點向主節點發送psync命令(Redis2.8之前是sync命令),開始同步。
數據同步階段是主從複製最核心的階段,根據主從節點當前狀態的不一樣,能夠分爲全量複製和部分複製,下面會有一章專門講解這兩種複製方式以及psync命令的執行過程,這裏再也不詳述。
須要注意的是,在數據同步階段以前,從節點是主節點的客戶端,主節點不是從節點的客戶端;而到了這一階段及之後,主從節點互爲客戶端。緣由在於:在此以前,主節點只須要響應從節點的請求便可,不須要主動發請求,而在數據同步階段和後面的命令傳播階段,主節點須要主動向從節點發送請求(如推送緩衝區中的寫命令),才能完成複製。
命令傳播
數據同步階段完成後,主從節點進入命令傳播階段;在這個階段主節點將本身執行的寫命令發送給從節點,從節點接收命令並執行,從而保證主從節點數據的一致性。
在命令傳播階段,除了發送寫命令,主從節點還維持着心跳機制:PING和REPLCONF ACK。因爲心跳機制的原理涉及部分複製,所以將在介紹了部分複製的相關內容後單獨介紹該心跳機制。
延遲與不一致
須要注意的是,命令傳播是異步的過程,即主節點發送寫命令後並不會等待從節點的回覆;所以實際上主從節點之間很難保持實時的一致性,延遲在所不免。數據不一致的程度,與主從節點之間的網絡情況、主節點寫命令的執行頻率、以及主節點中的repl-disable-tcp-nodelay配置等有關。
repl-disable-tcp-nodelay no:該配置做用於命令傳播階段,控制主節點是否禁止與從節點的TCP_NODELAY;默認no,即不由止TCP_NODELAY。當設置爲yes時,TCP會對包進行合併從而減小帶寬,可是發送的頻率會下降,從節點數據延遲增長,一致性變差;具體發送頻率與Linux內核的配置有關,默認配置爲40ms。當設置爲no時,TCP會立馬將主節點的數據發送給從節點,帶寬增長但延遲變小。
通常來講,只有當應用對Redis數據不一致的容忍度較高,且主從節點之間網絡情況很差時,纔會設置爲yes;多數狀況使用默認值no。
5、缺陷
主從複製雖然解決或緩解了數據冗餘、故障恢復、讀負載均衡等問題,但其缺陷仍很明顯,如故障恢復沒法自動化;寫操做沒法負載均衡;存儲能力受到單機的限制。每次slaveof斷開後,(不管是主動斷開,仍是網絡故障),再鏈接master;都要master所有dump出來rdb,再aof,即同步的過程都要從新執行1遍。因此不要多臺slaveof同時啓動,不然master可能IO劇增。