Redis數據庫主從複製
第1章 主從複製介紹
Redis 支持簡單且易用的主從複製(master-slave replication)功能, 該功能可以讓從服務器(slave server)成爲主服務器(master server)的精確複製品。以下是關於Redis複製功能的幾個重要方面:
q Redis 使用異步複製。從Redis 2.8 開始,從服務器會以每秒一次的頻率向主服務器報告複製流(replication stream)的處理進度。
q 一個主服務器可以有多個從服務器。
q 不僅主服務器可以有從服務器,從服務器也可以有自己的從服務器,多個從服務器之間可以構成一個圖狀結構。
q 複製功能不會阻塞主服務器:即使有一個或多個從服務器正在進行初次同步,主服務器也可以繼續處理命令請求。
q 複製功能也不會阻塞從服務器:只要在 redis.conf 文件中進行了相應的設置,即使從服務器正在進行初次同步,服務器也可以使用舊版本的數據集來處理命令查詢。不過,在從服務器刪除舊版本數據集並載入新版本數據集的那段時間內,連接請求會被阻塞。可以配置從服務器, 讓它在與主服務器之間的連接斷開時, 向客戶端發送一個錯誤。
q 複製功能可以單純地用於數據冗餘(data redundancy), 也可以通過讓多個從服務器處理只讀命令請求來提升擴展性(scalability):比如說,繁重的SORT命令可以交給附屬節點去運行。
q 可以通過複製功能來讓主服務器免於執行持久化操作:只要關閉主服務器的持久化功能,然後由從服務器去執行持久化操作即可。
第2章 持久化對數據的影響
當配置Redis複製功能時,強烈建議打開主服務器的持久化功能。 否則的話,由於延遲等問題,部署的服務應該要避免自動拉起。
爲了幫助理解主服務器關閉持久化時自動拉起的危險性,參考一下以下會導致主從服務器數據全部丟失的例子:
1. 假設節點A爲主服務器,並且關閉了持久化。 並且節點B和節點C從節點A複製數據
2. 節點A崩潰,然後由自動拉起服務重啓了節點A. 由於節點A的持久化被關閉了,所以重啓之後沒有任何數據
3. 節點B和節點C將從節點A複製數據,但是A的數據是空的, 於是就把自身保存的數據副本刪除。
在關閉主服務器上的持久化,並同時開啓自動拉起進程的情況下,即便使用Sentinel來實現Redis的高可用性,也是非常危險的。 因爲主服務器可能拉起得非常快,以至於Sentinel在配置的心跳時間間隔內沒有檢測到主服務器已被重啓,然後還是會執行上面的數據丟失的流程。
無論何時,數據安全都是極其重要的,所以應該禁止主服務器關閉持久化的同時自動拉起。
注:在開啓主從複製的時候,強烈建議開啓持久化功能。
第3章 主從複製過程
1、無論是初次連接還是重新連接, 當建立一個從服務器時, 從服務器都將向主服務器發送一個 SYNC 命令。
2、接到 SYNC 命令的主服務器將開始執行 BGSAVE , 並在保存操作執行期間, 將所有新執行的寫入命令都保存到一個緩衝區裏面。
3、當 BGSAVE 執行完畢後, 主服務器將執行保存操作所得的 .rdb 文件發送給從服務器, 從服務器接收這個 .rdb 文件, 並將文件中的數據載入到內存中。
4、之後主服務器會以 Redis 命令協議的格式, 將寫命令緩衝區中積累的所有內容都發送給從服務器。
從服務器可以在主從服務器之間的連接斷開時進行自動重連, 在 Redis 2.8 版本之前, 斷線之後重連的從服務器總要執行一次完整重同步(full resynchronization)操作, 但是從 Redis 2.8 版本開始, 從服務器可以根據主服務器的情況來選擇執行完整重同步還是部分重同步(partial resynchronization)。
第4章 部分重同步
從 Redis 2.8 開始, 在網絡連接短暫性失效之後, 主從服務器可以嘗試繼續執行原有的複製進程(process), 而不一定要執行完整重同步操作。
這個特性需要主服務器爲被髮送的複製流創建一個內存緩衝區(in-memory backlog), 並且主服務器和所有從服務器之間都記錄一個複製偏移量(replication offset)和一個主服務器 ID (master run id), 當出現網絡連接斷開時, 從服務器會重新連接, 並且向主服務器請求繼續執行原來的複製進程:
如果從服務器記錄的主服務器 ID 和當前要連接的主服務器的 ID 相同, 並且從服務器記錄的偏移量所指定的數據仍然保存在主服務器的複製流緩衝區裏面, 那麼主服務器會向從服務器發送斷線時缺失的那部分數據, 然後複製工作可以繼續執行。否則的話, 從服務器就要執行完整重同步操作。
Redis 2.8 的這個部分重同步特性會用到一個新增的 PSYNC 內部命令, 而 Redis 2.8 以前的舊版本只有 SYNC 命令, 不過, 只要從服務器是 Redis 2.8 或以上的版本, 它就會根據主服務器的版本來決定到底是使用 PSYNC 還是 SYNC :
q 如果主服務器是 Redis 2.8 或以上版本,那麼從服務器使用 PSYNC 命令來進行同步。
q 如果主服務器是 Redis 2.8 之前的版本,那麼從服務器使用 SYNC 命令來進行同步。
第5章 主從複製的配置
5.1 配置主從服務器
配置一個從服務器非常簡單, 只要在配置文件中增加以下的這一行就可以了:
slaveof 10.0.0.16 6379 #<==主服務器的IP和端口
另外一種方法是調用 SLAVEOF 命令, 輸入主服務器的 IP 和端口, 然後同步就會開始:
10.0.0.11:6379> SLAVEOF 10.0.0.16 6379 OK
5.2 配置從服務器只讀
從 Redis 2.6 開始, 從服務器支持只讀模式, 並且該模式爲從服務器的默認模式。只讀從服務器會拒絕執行任何寫命令, 所以不會出現因爲操作失誤而將數據不小心寫入到了從服務器的情況。
即使從服務器是隻讀的, DEBUG 和 CONFIG 等管理式命令仍然是可以使用的, 所以我們還是不應該將服務器暴露給互聯網或者任何不可信網絡。 不過, 使用 redis.conf 中的命令改名選項, 我們可以通過禁止執行某些命令來提升只讀從服務器的安全性。
配置參數如下:
slave-read-only yes
5.3 配置主服務器密碼
如果主服務器通過 requirepass 選項設置了密碼, 那麼爲了讓從服務器的同步操作可以順利進行, 我們也必須爲從服務器進行相應的身份驗證設置。
對於一個正在運行的服務器, 可以使用客戶端輸入以下命令:
config set masterauth <password>
要永久地設置這個密碼, 那麼可以將它加入到配置文件中:
masterauth <password>
5.4 配置寫操作最小從服務器節點
從 Redis 2.8 開始, 爲了保證數據的安全性, 可以通過配置, 讓主服務器只在有至少 N 個當前已連接從服務器的情況下, 才執行寫命令。
不過, 因爲 Redis 使用異步複製, 所以主服務器發送的寫數據並不一定會被從服務器接收到, 因此, 數據丟失的可能性仍然是存在的。
以下是這個特性的運作原理:
1、從服務器以每秒一次的頻率 PING 主服務器一次, 並報告複製流的處理情況。
2、主服務器會記錄各個從服務器最後一次向它發送 PING 的時間。
3、用戶可以通過配置, 指定網絡延遲的最大值 min-slaves-max-lag , 以及執行寫操作所需的至少從服務器數量 min-slaves-to-write 。
如果至少有 min-slaves-to-write 個從服務器, 並且這些服務器的延遲值都少於 min-slaves-max-lag 秒, 那麼主服務器就會執行客戶端請求的寫操作。你可以將這個特性看作 CAP 理論中的 C 的條件放寬版本: 儘管不能保證寫操作的持久性, 但起碼丟失數據的窗口會被嚴格限制在指定的秒數中。
另一方面, 如果條件達不到 min-slaves-to-write 和 min-slaves-max-lag 所指定的條件, 那麼寫操作就不會被執行, 主服務器會向請求執行寫操作的客戶端返回一個錯誤。
以下是這個特性的兩個選項和它們所需的參數:
min-slaves-to-write <number of slaves> min-slaves-max-lag <number of seconds>
5.5 其他相關配置
1) slave-serve-stale-data yes
#<==與master失聯的應對方式,yes時會回覆客戶端舊的數據;no會提示報錯“SYNC with master in progress”
2) repl-diskless-sync no
#<==是否啓動無盤同步方式,即使用socket做同步策略而不會使用到disk。(磁盤IO慢,且帶寬足夠大時可選擇採用。但該功能目前還不處實驗狀態,建議選擇關閉)
3) repl-diskless-sync-delay 5
#<==當repl-diskless-sync設置爲yes時,設置傳輸前的等待時間。要禁用該功能可配置爲0。
4) repl-disable-tcp-nodelay no
#<==tcp延時的優化,默認爲no。在非常高的網絡trafiic條件或者主備距離遠時,可開啓爲yes。
5) slave-priority 100
#<==從節點的優先級。數字越低級別越高,0表示不會被提升帶master。