Redis 主從 Replication 的配置

本專欄與Redis相關的文章redis

Redis Sentinel機制與用法(一)
Redis Sentinel機制與用法(二)
Jedis的JedisSentinelPool源代碼分析
Jedis的Sharded源代碼分析
Redis 主從 Replication 的配置
詳解Redis SORT命令
JedisCommand接口說明segmentfault

本文參考翻譯自 《Redis Replication documentation》

概述

Redis的replication機制容許slave從master那裏經過網絡傳輸拷貝到完整的數據備份。具備如下特色:緩存

  • 異步複製。從2.8版本開始,slave能不時地從master那裏獲取到數據。
  • 容許單個master配置多個slave
  • slave容許其它slave鏈接到本身。一個slave除了能夠鏈接master外,它還能夠鏈接其它的slave。造成一個圖狀的架構。
  • master在進行replication時是非阻塞的,這意味着在replication期間,master依然可以處理客戶端的請求。
  • slave在replication期間也是非阻塞的,也能夠接受來自客戶端的請求,可是它用的是以前的舊數據。能夠經過配置來決定slave是否在進行replication時用舊數據響應客戶端的請求,若是配置爲否,那麼slave將會返回一個錯誤消息給客戶端。不過當新的數據接收徹底後,必須將新數據與舊數據替換,即刪除舊數據,在替換數據的這個時間窗口內,slave將會拒絕客戶端的請求和鏈接。
  • 通常使用replication來能夠實現擴展性,例如說,能夠將多個slave配置爲「只讀」,或者是純粹的數據冗餘備份。
  • 可以經過replication來避免master每次持久化時都將整個數據集持久化到硬盤中。只需把master配置爲不進行save操做(把配置文件中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發生的時候,那麼應該禁止實例的自啓動。架構

replication工做原理

若是你爲master配置了一個slave,無論這個slave是不是第一次鏈接上Master,它都會發送一個SYNC命令給master請求複製數據。併發

master收到SYNC命令後,會在後臺進行數據持久化,持久化期間,master會繼續接收客戶端的請求,它會把這些可能修改數據集的請求緩存在內存中。當持久化進行完畢之後,master會把這份數據集發送給slave,slave會把接收到的數據進行持久化,而後再加載到內存中。而後,master再將以前緩存在內存中的命令發送給slave。less

當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,而不用通過硬盤的存儲。

不過這個功能目前處於實驗階段,還未正式發佈。

相關配置

與replication相關的配置比較簡單,只須要把下面一行加到slave的配置文件中:

slaveof 192.168.1.1 6379

你只須要把ip地址和端口號改一下。固然,你也能夠經過客戶端發送SLAVEOF命令給slave。

部分數據複製有一些可調的配置參數,請參考redis.conf文件。

無硬盤複製功能能夠經過repl-diskless-sync來配置,另一個配置項repl-diskless-sync-delay用來配置當收到第一個請求時,等待多個slave一塊兒來請求之間的間隔時間。

只讀的slave

從redis2.6版本開始,slave支持只讀模式,並且是默認的。能夠經過配置項slave-read-only來進行配置,而且支持客戶端使用CONFIG SET命令來動態修改配置。

只讀的slave會拒絕全部的寫請求,只讀的slave並非爲了防範不可信的客戶端,畢竟一些管理命令例如DEBUGCONFIG在只讀模式下仍是可使用的。若是確實要確保安全性,那麼能夠在配置文件中將一些命令從新命名。

也許你會感到很奇怪,爲何可以將一個只讀模式的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>

若是須要了解更多,請查閱redis.conf配置文件。

掃一掃關注個人微信公衆號

相關文章
相關標籤/搜索