一、簡介 Redis的replication機制允許slave從master那裡通過網路傳輸拷貝到完整的數據備份。具有以下特點: 非同步複製 可以配置一主多從 可以配置從伺服器可以級聯從伺服器,既 M->S->S M replication時是非阻塞的(在replication期間,M依然能夠處理客戶
一、簡介
Redis的replication機制允許slave從master那裡通過網路傳輸拷貝到完整的數據備份。具有以下特點:
-
非同步複製
-
可以配置一主多從
-
可以配置從伺服器可以級聯從伺服器,既 M->S->S
-
M replication時是非阻塞的(在replication期間,M依然能夠處理客戶端的請求)
-
S replication期間也是非阻塞的(也可以接受來自客戶端的請求,但是它用的是之前的舊數據)可以通過配置來決定S是否在進行replication時用舊數據響應客戶端的請求,如果配置為否,那麼slave將會返回一個錯誤消息給客戶端。不過當新的數據接收完全後,必須將新數據與舊數據替換,即刪除舊數據,在替換數據的這個時間視窗內,slave將會拒絕客戶端的請求和連接
-
能夠通過replication來避免master每次持久化時都將整個數據集持久化到硬碟中。只需把master配置為不進行save操作,然後連接上一個slave,這個slave則被配置為不時地進行save操作的。不過需要註意的是,在這個用例中,必須確保master不會自動啟動
二、Master持久化功能關閉時Replication的安全性
當有需要使用到replication機制時,一般都會強烈建議把master的持久化開關打開。即使為了避免持久化帶來的延遲影響,不把持久化開關打開,那麼也應該把master配置為不會自動啟動的
為了更好地理解當一個不進行持久化的master如果允許自動啟動所帶來的危險性。可以看看下麵這種失敗情形:
假設我們有一個redis節點A,設置為master,並且關閉持久化功能,另外兩個節點B和C是它的slave,並從A複製數據。
-
如果A節點崩潰了導致所有的數據都丟失了,它會有重啟系統來重啟進程。但是由於持久化功能被關閉了,所以即使它重啟了,它的數據集是空的。而B和C依然會通過replication機制從A複製數據,所以B和C會從A那裡複製到一份空的數據集,並用這份空的數據集將自己本身的非空的數據集替換掉。於是就相當於丟失了所有的數據
-
即使使用一些HA工具,比如說sentinel來監控master-slaves集群,也會發生上述的情形,因為master可能崩潰後迅速恢復。速度太快而導致sentinel無法察覺到一個failure的發生
-
數據的安全很重要、持久化開關被關閉並且有replication發生的時候,應該禁止實例的自啟動
三、M/S replication的工作原理
-
當master和slave啟動時,不管這個slave是否是第一次連接上Master,它都會發送一個
SYNC
命令給master請求複製數據 -
master收到
SYNC
命令後,會在後臺進行數據持久化,持久化期間,master會繼續接收客戶端的請求,它會把這些可能修改數據集的請求緩存在記憶體中。當持久化進行完畢以後,master會把這份數據集發送給slave,slave會把接收到的數據進行持久化,然後再載入到記憶體中。然後,master再將之前緩存在記憶體中的命令發送給slave -
當master與slave之間的連接由於某些原因而斷開時,slave能夠自動重連Master,如果master收到了多個slave併發連接請求,它只會進行一次持久化,然後再把這一份持久化的數據發送給多個併發連接的slave
-
當master和slave斷開重連後,一般都會對整份數據進行複製。但從redis2.8版本開始,支持部分複製
數據部分複製
從2.8版本開始,slave與master能夠在網路連接斷開重連後只進行部分數據複製。
master會在其記憶體中創建一個複製流的等待隊列,master和它所有的slave都維護了複製的數據下標和master的進程id,因此,當網路連接斷開後,slave會請求master繼續進行未完成的複製,從所記錄的數據下標開始。如果進程id變化了,或者數據下標不可用,那麼將會進行一次全部數據的複製。支持部分數據複製的命令是PSYNC
不需硬碟參與的Replication
一般情況下,一次複製需要將記憶體的數據寫到硬碟中,再將數據從硬碟讀進記憶體,再發送給slave。對於速度比較慢的硬碟,這個操作會給master帶來性能上的損失。Redis2.8版本開始,實驗性地加上了無硬碟複製的功能。這個功能能將數據從記憶體中直接發送到slave,而不用經過硬碟的存儲。不過這個功能目前處於實驗階段,還未正式發佈
四、配置M/S
slaveof <masterip> <masterport> slave實例需要配置該項,指向master的(ip, port) masterauth <master-password> 如果master實例啟用了密碼保護,則該配置項需填master的啟動密碼;若master未啟用密碼,該配置項需要註釋掉 slave-serve-stale-data 指定slave與master連接中斷時的動作。預設為yes,表明slave會繼續應答來自client的請求,但這些數據可能已經過期(因為連接中斷導致無法從master同步) 若配置為no,則slave除正常應答"INFO"和"SLAVEOF"命令外,其餘來自客戶端的請求命令均會得到"SYNC with master in progress"的應答, 直到該slave與master的連接重建成功或該slave被提升為master。 slave-read-only 指定slave是否只讀,預設為yes。若配置為no,這表示slave是可寫的,但寫的內容在主從同步完成後會被刪掉 repl-ping-slave-period Redis部署為Replication模式後,slave會以預定周期(預設10s)發PING包給master,該配置可以更改這個預設周期 repl-timeout 有2種情況的超時均由該配置指定:1) Bulk transfer I/O timeout; 2) master data or ping response timeout 需要特別註意的是:若修改預設值,則用戶輸入的值必須大於repl-ping-slave-period的配置值,否則在主從鏈路延時較高時,會頻繁timeout repl-disable-tcp-nodelay 指定向slave同步數據時,是否禁用socket的NO_DELAY選項。 若配置為yes,則禁用NO_DELAY,則TCP協議棧會合併小包統一發送,這樣可以減少主從節點間的包數量並節省帶寬,但會增加數據同步到slave的時間 若配置為no,表明啟用NO_DELAY,則TCP協議棧不會延遲小包的發送時機,這樣數據同步的延時會減少,但需要更大的帶寬 通常情況下,應該配置為no以降低同步延時,但在主從節點間網路負載已經很高的情況下,可以配置為yes 備註:socket的NO_DELAY選項涉及到TCP協議棧的擁塞控制演算法—Nagle's Algorithm slave-priority 指定slave的優先順序。在不只1個slave存在的部署環境下,當master宕機時,Redis Sentinel會將priority值最小的slave提升為master 需要註意的是,若該配置項為0,則對應的slave永遠不會被Redis Sentinel自動提升為master
replication相關的配置比較簡單,只需要把下麵一行加到slave的配置文件中
slaveof 192.168.1.1 6379
你也可以通過客戶端發送SLAVEOF
命令給slave。無硬碟複製功能可以通過repl-diskless-sync
來配置,另外一個配置項repl-diskless-sync-delay
用來配置當收到第一個請求時,等待多個slave一起來請求之間的間隔時間
1、同時啟動兩個Redis伺服器,可以考慮在同一臺機器上啟動兩個Redis伺服器,分別監聽不同的埠,如6379和6380
2、配置文件為6379.conf 6380.conf
3、啟動並配置
./src/redis-server 6380.conf ./src/redis-server 6379.conf
4、測試
[root@localhost redis]# ./src/redis-cli -p 6379 127.0.0.1:6379> flushdb OK 127.0.0.1:6379> set aa 1 OK 127.0.0.1:6379> set bb 2 OK 127.0.0.1:6379> set cc 3 OK 127.0.0.1:6379> exit [root@localhost redis]# ./src/redis-cli -p 6380 127.0.0.1:6380> keys * 1) "bb" 2) "aa" 3) "cc" 127.0.0.1:6380> get aa "1" 127.0.0.1:6380> get bb "2"
五、only read slave
從redis2.6版本開始,slave支持只讀模式,而且是預設的。可以通過配置項slave-read-only
來進行配置,並且支持客戶端使用CONFIG SET
命令來動態修改配置
只讀的slave會拒絕所有的寫請求,只讀的slave並不是為了防範不可信的客戶端,畢竟一些管理命令例如DEBUG
和CONFIG
在只讀模式下還是可以使用的。如果確實要確保全全性,那麼可以在配置文件中將一些命令重新命名。也許你會感到很奇怪,為什麼能夠將一個只讀模式的slave恢復為可寫的呢,儘管可寫,但是只要slave一同步master的數據,就會丟失那些寫在slave的數據。不過還是有一些合法的應用場景需要存儲瞬時數據會用到這個特性。不過,之後可能會考慮廢除掉這個特性。Setting a slave to authenticate to a master
如果master通過requirepass
配置項設置了密碼,slave每次同步操作都需要驗證密碼,可以通過在slave的配置文件中添加以下配置項:
masterauth <password>
也可以通過客戶端在運行時發送以下命令:
config set masterauth <password>
六、至少N個slave才允許向master寫數據
從redis2.8版本開始,master可以被配置為只有當master當前有至少N個slave連接著的時候才接受寫數據的請求;由於redis是非同步複製的,所以它並不能保證slave會收到一個寫請求,所以總有一個數據丟失的時間視窗存在
這個機制的工作原理如下所示:
-
slave每秒發送ping心跳給master,詢問當前複製了多少數據
-
master會記錄下它上次收到某個slave的ping心跳是什麼時候
-
使用者可以配置一個時間,來指定ping心跳的發送不應超過的一個超時時間
如果master有至少N個slave,並且ping心跳的超時不超過M秒,那麼它就會接收寫請求。也許你會認為這情形好似CAP理論中弱化版的C(consistency),因為寫請求並不能保證數據的一致性,但這樣做,至少數據丟失被限制在了限定的時間內,即M秒
如果N和M的條件都無法達到,那麼master會回覆一個錯誤信息。寫請求也不會被處理
有兩個配置項用來配置上文中提到的N和M:
min-slaves-to-write <number of slaves> min-slaves-max-lag <number of seconds>
參考文章
https://support.pivotal.io/hc/en-us/articles/205309278-How-to-setup-Redis-Master-and-Salve-replication