958
技術社區[雲棲]
《Redis官方文檔》主從複製
Redis主從複製的配置十分簡單,它可以使從服務器是主服務器的完全拷貝。下麵是關於Redis主從複製的幾點重要內容:
- Redis使用異步複製。但從Redis 2.8開始,從服務器會周期性的應答從複製流中處理的數據量。
- 一個主服務器可以有多個從服務器。
- 從服務器也可以接受其他從服務器的連接。除了多個從服務器連接到一個主服務器之外,多個從服務器也可以連接到一個從服務器上,形成一個圖狀結構
- Redis主從複製不阻塞主服務器端。也就是說當若幹個從服務器在進行初始同步時,主服務器仍然可以處理請求。
- 主從複製也不阻塞從服務器端。當從服務器進行初始同步時,它使用舊版本的數據來應對查詢請求,假設你在redis.conf配置文件是這麼配置的。否則的話,你可以配置當複製流關閉時讓從服務器給客戶端返回一個錯誤。但是,當初始同步完成後,需要刪除舊的數據集和加載新的數據集,在這個短暫的時間內,從服務器會阻塞連接進來的請求。
- 主從複製可以用來增強擴展性,使用多個從服務器來處理隻讀的請求(比如,繁重的排序操作可以放到從服務器去做),也可以簡單的用來做數據冗餘。
- 使用主從複製可以為主服務器免除把數據寫入磁盤的消耗:在主服務器的redis.conf文件中配置“避免保存”(注釋掉所有“保存“命令),然後連接一個配置為“進行保存”的從服務器即可。但是這個配置要確保主服務器不會自動重啟(要獲得更多信息請閱讀下一段)
當主服務器不進行持久化時複製的安全性
在進行主從複製設置時,強烈建議在主服務器上開啟持久化,當不能這麼做時,比如考慮到延遲的問題,應該將實例配置為避免自動重啟。
為什麼不持久化的主服務器自動重啟非常危險呢?為了更好的理解這個問題,看下麵這個失敗的例子,其中主服務器和從服務器中數據庫都被刪除了。
- 我們設置節點A為主服務器,關閉持久化,節點B和C從節點A複製數據。
- 這時出現了一個崩潰,但Redis具有自動重啟係統,重啟了進程,因為關閉了持久化,節點重啟後隻有一個空的數據集。
- 節點B和C從節點A進行複製,現在節點A是空的,所以節點B和C上的複製數據也會被刪除。
當在高可用係統中使用Redis Sentinel,關閉了主服務器的持久化,並且允許自動重啟,這種情況是很危險的。比如主服務器可能在很短的時間就完成了重啟,以至於Sentinel都無法檢測到這次失敗,那麼上麵說的這種失敗的情況就發生了。
如果數據比較重要,並且在使用主從複製時關閉了主服務器持久化功能的場景中,都應該禁止實例自動重啟。
(校對注: 關閉持久化並允許自動重啟的主服務器,在做主從同步時,可能導致所有服務器的數據都被清空)
Redis主從複製是如何工作的
如果你設置了一個從服務器,在連接時它發送了一個SYNC命令,不管它是第一次連接還是再次連接都沒有關係。
然後主服務器開始後台存儲,並且開始緩存新連接進來的修改數據的命令。當後台存儲完成後,主服務器把數據文件發送到從服務器,從服務器將其保存在磁盤上,然後加載到內存中。然後主服務器把剛才緩存的命令發送到從服務器。這是作為命令流來完成的,並且和Redis協議本身格式相同。
你可以通過telnet自己嚐試一下。在Redis服務器工作時連接到Redis端口,發送SYNC命令,會看到一個批量的傳輸,並且主服務器接收的每一個命令都會通過telnet會話重新發送一遍。
當主從服務器之間的連接由於某些原因斷開時,從服務器可以自動進行重連接。當有多個從服務器同時請求同步時,主服務器隻進行一個後台存儲。
當連接斷開又重新連上之後,一般都會進行一個完整的重新同步,但是從Redis2.8開始,隻重新同步一部分也可以。
部分重新同步
從Redis 2.8開始,如果遭遇連接斷開,重新連接之後可以從中斷處繼續進行複製,而不必重新同步。
它的工作原理是這樣,主服務器端為複製流維護一個內存緩衝區(in-memory backlog)。主從服務器都維護一個複製偏移量(replication offset)和master run id ,當連接斷開時,從服務器會重新連接上主服務器,然後請求繼續複製,假如主從服務器的兩個master run id相同,並且指定的偏移量在內存緩衝區中還有效,複製就會從上次中斷的點開始繼續。如果其中一個條件不滿足,就會進行完全重新同步(在2.8版本之前就是直接進行完全重新同步)。因為主運行id不保存在磁盤中,如果從服務器重啟了的話就隻能進行完全同步了。
部分重新同步這個新特性內部使用PSYNC命令,舊的實現中使用SYNC命令。Redis2.8版本可以檢測出它所連接的服務器是否支持PSYNC命令,不支持的話使用SYNC命令。
無磁盤複製
通常來講,一個完全重新同步需要在磁盤上創建一個RDB文件,然後加載這個文件以便為從服務器發送數據。
如果使用比較低速的磁盤,這種操作會給主服務器帶來較大的壓力。Redis從2.8.18版本開始嚐試支持無磁盤的複製。使用這種設置時,子進程直接將RDB通過網絡發送給從服務器,不使用磁盤作為中間存儲。
這一特性目前隻是實驗性的。
配置
主從複製的配置十分簡單:把下麵這行加入到從服務器的配置文件中即可。
slaveof 192.168.1.1 6379
當然你需要把其中的192.168.1.1 6379替換為你自己的主服務器IP(或者主機名hostname)和端口。另外你可以調用SLAVEOF命令,主服務器就會開始與從服務器同步。
關於部分重新同步,還有一些針對複製內存緩衝區的優化參數。查看Redis介質中的Redis.conf示例獲得更多信息。
使用repl-diskless-sync配置參數來啟動無磁盤複製。使用repl-diskless-sync-delay 參數來配置傳輸開始的延遲時間,以便等待更多的從服務器連接上來。查看Redis介質中的Redis.conf示例獲得更多信息。
隻讀從服務器
從Redis 2.6開始,從服務器支持隻讀模式,並且是默認模式。這個行為是由Redis.conf文件中的slave-read-only 參數控製的,可以在運行中通過CONFIG SET來啟用或者禁用。
隻讀的從服務器會拒絕所有寫命令,所以對從服務器不會有誤寫操作。但這不表示可以把從服務器實例暴露在危險的網絡環境下,因為像DEBUG或者CONFIG這樣的管理命令還是可以運行的。不過你可以通過使用rename-command命令來為這些命令改名來增加安全性。
你可能想知道為什麼隻讀限製還可以被還原,使得從服務器還可以進行寫操作。雖然當主從服務器進行重新同步或者從服務器重啟後,這些寫操作都會失效,還是有一些使用場景會想從服務器中寫入臨時數據的,但將來這個特性可能會被去掉。
設置從服務器到主服務器驗證
如果主服務器設置了密碼,配置從服務器在所有同步中使用這個密碼十分簡單。
對於運行中的實例,使用redis-cli並輸入:
</pre> <pre><code>config set masterauth <password></code></pre> <pre>
要使配置永久生效,把如下命令加入到配置文件中:
</pre> <pre><code>masterauth <password></code></pre> <pre>
限製有N個以上從服務器才允許寫入
從Redis 2.8版本開始,可以配置主服務器連接N個以上從服務器才允許對主服務器進行寫操作。但是,因為Redis使用的是異步主從複製,沒辦法確保從服務器確實收到了要寫入的數據,所以還是有一定的數據丟失的可能性。
這一特性的工作原理如下:
- 從服務器每秒鍾ping一次主服務器,確認處理的複製流數量。
- 主服務器記住每個從服務器最近一次ping的時間。
- 用戶可以配置最少要有N個服務器有小於M秒的確認延遲。
如果有N個以上從服務器,並且確認延遲小於M秒,主服務器接受寫操作。
你可以把這看做是CAP原則(一致性,可用性,分區容錯性)不嚴格的一致性實現,雖然不能百分百確保一致性,但至少保證了丟失的數據不會超過M秒內的數據量。
如果條件不滿足,主服務器會拒絕寫操作並返回一個錯誤。
- min-slaves-to-write(最小從服務器數)
- min-slaves-max-lag(從服務器最大確認延遲)
查看Redis介質中的Redis.conf示例獲得更多信息。
最後更新:2017-05-22 10:03:00