例如,如今有兩臺redis服務器,地址爲127.0.0.1:6379 和 127.0.0.1:6380,如今在6380端口這臺機子執行命令:redis
127.0.0.1:6380>slaveof 127.0.0.1 6379 ok
那麼127.0.0.1:6380將成爲127.0.0.1:6379的從服務器,而服務器127.0.0.1:6379會成爲127.0.0.1:6380的主服務器。數據庫
進行復制中的主從服務器雙方的數據庫將保存相同的數據,概念上將這種現象稱爲"數據庫狀態一致",或者簡稱'一致'。安全
redis的複製功能分爲同步和命令傳播兩個操做:bash
(1).同步操做就是將從服務器的數據庫狀態更新至主服務器當前所處的狀態。服務器
(2).命令傳播操做用於在主服務器的數據庫狀態被修改,致使主從服務器的數據庫狀態出現不一致的時候,讓主從狀態從新回到一致狀態。網絡
同步的具體步驟以下:blog
1) 從服務器向主服務器發送sync命令隊列
2) 收到sync命令的主服務器執行bgsave命令,在後臺生成一個rdb文件,並使用一個緩衝區記錄從如今開始執行的全部寫命令。同步
3)當服務器的bgsave命令執行完畢後,主服務器會將rdb文件發送給從服務器,從服務器接受並載入rdb文件,將本身的數據庫狀態更新到主服務器執行bgsave時的數據庫狀態it
4) 主服務器將記錄在緩衝區裏面的全部寫命令發送給從服務器,從服務器執行這些寫命令,將本身的數據庫狀態更新到主服務器當前所在的狀態。
命令傳播詳解:
經過上面的同步操做後,主從服務器的數據庫狀態達到了一致,但這種一致並非一成不變的。假如主服務器執行了客戶端發送的寫命令,那麼二者的狀態再也不一致。爲了讓主從服務器再次回到一致狀態,主服務器須要對從服務器執行命令傳播操做:主服務器會將本身執行的寫命令,發送給從服務器執行,當從服務器執行了這個命令以後,主從服務器再次回到一致狀態。
在redis中,主從複製分爲 初次複製 和 斷線後複製 兩種狀況。
斷線後複製就是 處於命令傳播階段的主從服務器由於網絡緣由而中斷了複製,可是從服務器經過自動重連從新連上了主服務器,並繼續複製主服務器。缺陷就在於 舊版複製功能雖然也能讓主從服務器回到一致狀態,可是效率很低。由於斷線後重連,從服務器會向主服務器發送sync命令,從新接收並導入rdb文件,這就很耗時,作了一些無用功,由於rdb文件中不少鍵的數據從服務器中原本就有。
爲了解決舊版斷線後複製的低效率問題,redis從2.8版本開始,使用PSYNC命令代替原先的sync命令來執行復制時的同步操做。PSYNC命令具備完整重同步和部分重同步兩種模式:
完整重同步用於處理初次複製的狀況。而部分重同步用於斷線後重複製的狀況,當從服務器重連上主服務器時,若是條件容許,主服務器能夠將從服務器鏈接斷開期間執行的寫命令發送給從服務器,從服務器執行後,從新回到一致狀態。
部分重同步由下面3個部分組成:
1.主服務器的複製偏移量和從服務器的複製偏移量
2.主服務器的複製積壓緩衝區
3.服務器的運行ID
當主服務器在進行命令傳播時,它不只會將寫命令發送給全部從服務器,還會將寫命令入隊到複製積壓緩衝區。複製積壓緩衝區是主服務器維護的一個固定長度的先進先出(FIFO)隊列,默認大小是1MB。因此以前說的若是條件容許就能夠理解了,就是指若是從服務器重連後,offset偏移量以後的數據仍然存在於緩衝區中,那麼執行部分重同步操做,反之執行完整重同步操做。
在命令傳播階段,從服務器默認會以每秒1次的頻率向服務器發送命令:
REPLCONF ACK <replication_offset>,其中replication_offset是從服務器當前的複製偏移量。
發送REPLCONF ACK 命令對於主從服務器有三個做用:
1.檢測主從服務器的網絡鏈接狀態 - 經過info replication命令獲得的lag值能夠知道,從服務器最後一次向主服務器發送REPLCONF ACK命令距離如今過了多少秒,正常狀況下,lag值在0-1之間跳動。
2.輔助實現min-slaves選項 - min-slaves-to-write 和 min-slaves-max-lag這兩個選項能夠防止主服務器在不安全的狀況下執行寫命令。
例如在主服務器配置了:
min-slaves-to-write 3
min-slaves-max-lag 10
那麼在從服務器數量少於3個或者三個從服務器延遲(lag)值大於或等於10s時,主服務器拒絕執行寫命令。
3.檢測命令丟失 - 若是由於故障,主服務器傳播給從服務器的命令在半路丟失,那麼當從服務器向主服務器發送REPLCONF ACK命令時,主服務器將發覺從服務器當前的複製偏移值少於自身的複製偏移值,而後主服務器就會根據從服務器提交的複製偏移值,在複製積壓緩衝區裏面找到從服務器缺乏的數據,並將這些數據從新發送給從服務器。
sentinel(哨兵)是redis的高可用解決方案:由一個或多個Sentinel實例組成的Sentinel系統能夠監視任意多個主服務器,以及這些主服務器屬下的全部從服務器,並在被監視的主服務器進入下線狀態時,自動將下線的主服務器屬下的某個從服務器升級爲新的主服務器,而後由新的主服務器代替已下線的主服務器繼續處理命令。