【Redis】搭建主從複製
紙上得來終覺淺,絕知此事要躬行。
主從複製
主從複製即將master中的資料即時、有效的複製到slave中。一個master可以擁有多個slave,一個slave只對應一個master
master:
- 寫資料
- 執行寫操作時,將出現變化的資料自動同步到slave
- 讀資料(可忽略)
slave:
- 讀資料
- 寫資料(禁止)
作用
- 讀寫分離:master寫、 slave讀,提高伺服器的讀寫負載能力
- 負載均衡:基於主從結構,配合讀寫分離,由slave分擔master負載,並根據需求的變化,改變slave的數
量,通過多個從節點分擔資料讀取負載,大大提高Redis伺服器併發量與資料吞吐量 - 故障恢復:當master出現問題時,由slave提供服務,實現快速的故障恢復
- 資料冗餘:實現資料熱備份,是持久化之外的一種資料冗餘方式
- 高可用:基於主從複製,構建哨兵模式與叢集,實現Redis的高可用方案
工作流程
RDB資料同步過程
Slave連線Master日誌:
7584:M 03 Jul 2020 17:18:53.366 * Replica 127.0.0.1:6380 asks for synchronization 7584:M 03 Jul 2020 17:18:53.366 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'f4fd0f661173f3aefb89f303a64f66102904a9e7', my replication IDs are '26996ab054c91b070c179919a82ec7c2c9e9c3f5' and '0000000000000000000000000000000000000000') 7584:M 03 Jul 2020 17:18:53.366 * Starting BGSAVE for SYNC with target: disk 7584:M 03 Jul 2020 17:18:53.367 * Background saving started by pid 12618 12618:C 03 Jul 2020 17:18:53.410 * DB saved on disk 12618:C 03 Jul 2020 17:18:53.411 * RDB: 2 MB of memory used by copy-on-write 7584:M 03 Jul 2020 17:18:53.489 * Background saving terminated with success 7584:M 03 Jul 2020 17:18:53.490 * Synchronization with replica 127.0.0.1:6380 succeeded
Slave接受到Master連線響應日誌:
4296:S 03 Jul 2020 17:18:53.365 * Connecting to MASTER 127.0.0.1:6379 4296:S 03 Jul 2020 17:18:53.365 * MASTER <-> REPLICA sync started 4296:S 03 Jul 2020 17:18:53.365 * Non blocking connect for SYNC fired the event. 4296:S 03 Jul 2020 17:18:53.365 * Master replied to PING, replication can continue... 4296:S 03 Jul 2020 17:18:53.366 * Trying a partial resynchronization (request f4fd0f661173f3aefb89f303a64f66102904a9e7:6150). 4296:S 03 Jul 2020 17:18:53.367 * Full resync from master: 26996ab054c91b070c179919a82ec7c2c9e9c3f5:6093 4296:S 03 Jul 2020 17:18:53.367 * Discarding previously cached master state. 4296:S 03 Jul 2020 17:18:53.489 * MASTER <-> REPLICA sync: receiving 210 bytes from master 4296:S 03 Jul 2020 17:18:53.490 * MASTER <-> REPLICA sync: Flushing old data 4296:S 03 Jul 2020 17:18:53.490 * MASTER <-> REPLICA sync: Loading DB in memory 4296:S 03 Jul 2020 17:18:53.490 * MASTER <-> REPLICA sync: Finished with success
連線與斷開
連線
- 客戶端傳送命令:
slaveof <masterip> <masterport>
- 啟動伺服器引數:
redis-server -slaveof <masterip> <masterport>
- 伺服器配置:
slaveof <masterip> <masterport>
斷開
- 客戶端傳送命令
slaveof no one
slave斷開連線後,不會刪除已有資料,只是不再接受master傳送的資料
授權訪問
- master客戶端傳送命令設定密碼
requirepass <password>
- master配置檔案設定密碼
config set requirepass <password>
config get requirepass
- slave客戶端傳送命令設定密碼
auth <password>
- slave配置檔案設定密碼
masterauth <password>
- slave啟動伺服器設定密碼
redis-server –a <password>
主從複製方案
server-6379 | server-6380 | server-6381 |
---|---|---|
port 6379 pidfile /var/run/redis/redis-server.pid logfile /var/log/redis/redis/redis-server.log dbfilename dump.rdb |
port 6380 pidfile /var/run/redis/redis-server-6380.pid logfile /var/log/redis/redis/redis-server-6380.log dbfilename dump6380.rdb |
port 6381 pidfile /var/run/redis/redis-server-6381.pid logfile /var/log/redis/redis/redis-server-6381.log dbfilename dump6380.rdb |
一主二僕
server-6379(主機) | server-6380 | server-6381 |
---|---|---|
檢視配置資訊 |
檢視配置資訊 |
檢視配置資訊 |
127.0.0.1:6379> set name ydy OK 127.0.0.1:6379> set age 20 OK 127.0.0.1:6379> keys * 1) "name" 2) "age" |
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 OK |
127.0.0.1:6381> SLAVEOF 127.0.0.1 6379 OK |
127.0.0.1:6379> set gender male OK |
127.0.0.1:6380> get gender "male" |
127.0.0.1:6381> get gender "male" |
127.0.0.1:6380> get name "male" |
127.0.0.1:6381> get name "male" |
|
情況一:從機設定
server-6379 | server-6380 | server-6381 |
---|---|---|
127.0.0.1:6380> set class 1 (error) READONLY You can't write against a read only replica. |
127.0.0.1:6381> set class 1 (error) READONLY You can't write against a read only replica. |
結論:主從複製中,從機不能寫資料,只能提供讀
情況二: 主機死亡
server-6379 | server-6380 | server-6381 |
---|---|---|
可能以下命令不起作用,可以嘗試service redis stop |
||
127.0.0.1:6380> set k1 v1 (error) READONLY You can't write against a read only replica. |
127.0.0.1:6381> set k2 v2 (error) READONLY You can't write against a read only replica. |
結論:主機死亡,從機處於等待狀態,同樣不能寫資料,也不能自我上位成Master
情況三: 主機起死回生
server-6379 | server-6380 | server-6381 |
---|---|---|
主機復活 |
結論:主機起死回生,主從之間建立連線,恢復正常
情況四: 從機死亡
server-6379 | server-6380 | server-6381 |
---|---|---|
重新連線 |
||
127.0.0.1:6379> get money "1000" |
127.0.0.1:6380> keys * (empty list or set) |
127.0.0.1:6381> get money "1000" |
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 OK 127.0.0.1:6380> get money "1000" |
結論:從機死亡,重新恢復需要手動建立與Master的連線
薪火相傳
一個Master連線多個Slave,而每個Slave又可以成為別的Slave的Master,形成鏈式主從。需要注意處於中間位置的伺服器依舊是Slave,只能讀資料,不能寫資料
server-6379 | server-6380 | server-6381 |
---|---|---|
127.0.0.1:6379> set kkk vvv OK 127.0.0.1:6379> get kkk "vvv" |
127.0.0.1:6380> get kkk "vvv" |
127.0.0.1:6381> get kkk "vvv" |
反客為主
一個Master連線多個Slave,當Master宕機或異常關機,Slave可以通過slave no one
指令斷開與原來Master的連線,自己成為Master,讓其他的Slave連線我。從而形成新的主從關係,這個過程是手動的,也可以通過配置檔案設定slaveof <masterip> <masterport>
。
server-6379 | server-6380 | server-6381 |
---|---|---|
127.0.0.1:6380> set k22 v22 OK |
127.0.0.1:6381> get k22 "v22" |
哨兵模式
哨兵模式可以看作為,自動版的反客為主,在搭建主從複製時,可以指定哨兵進行監督,如果其中主機Master掛掉,哨兵之間就會進行投票選舉出新的Master,重新建立主從關係,而當舊Master重新連線以後,此時舊Master就會作為Slave自動連線到新Master。
啟動 Sentinel
- 對於 redis-sentinel 程式, 你可以用以下命令來啟動 Sentinel 系統:
redis-sentinel /path/to/sentinel.conf
- 對於 redis-server 程式, 你可以用以下命令來啟動一個執行在 Sentinel 模式下的 Redis 伺服器:
redis-server /path/to/sentinel.conf --sentinel
配置Sentinel
配置項 | 示例 | 說明 |
---|---|---|
sentinel auth-pass <伺服器名稱> |
sentinel auth-pass mymaster ydongy |
連線伺服器口令 |
sentinel down-after-milliseconds <自定義服務名稱><主機地址><埠><主從伺服器總量> |
sentinel monitor mymaster 1127.0.0.1 6379 1 |
設定哨兵監聽的主伺服器資訊,最後的引數決定了最終參與選舉的伺服器數量 |
sentinel parallel-syncs <服務名稱><伺服器數(整數)> |
sentinel parallel-syncs mymaster 1 |
指定同時進行主從的slave數量,數值越大,要求網路資源越高,要求約小,同步時間約長 |
sentinel failover-timeout <服務名稱><毫秒數(整數)> |
sentinel failover-timeout mymaster 9000 |
指定出現故障後,故障切換的最大超時時間,超過該值,認定切換失敗,預設3分鐘 |
sentinel notification-script <服務名稱><指令碼路徑> |
伺服器無法正常聯通時,設定的執行指令碼,通常除錯使用。 |
Sentinel案例
sentinel-1 | sentinel-2 | sentinel-3 |
---|---|---|
port 26379 sentinel monitor host6379 127.0.0.1 6379 2 sentinel down-after-milliseconds host6379 60000 sentinel failover-timeout host6379 180000 sentinel parallel-syncs host6379 1 |
port 26380 sentinel monitor host6379 127.0.0.1 6379 2 sentinel down-after-milliseconds host6379 60000 sentinel failover-timeout host6379 180000 sentinel parallel-syncs host6379 1 |
port 26381 sentinel monitor host6379 127.0.0.1 6379 2 sentinel down-after-milliseconds host6379 60000 sentinel failover-timeout host6379 180000 sentinel parallel-syncs host6379 1 |
-
port
:配置哨兵埠 -
sentinel monitor host6379 127.0.0.1 6379 2
:指示 Sentinel 去監視一個名為 mymaster 的主伺服器, 這個主伺服器的 IP 地址為 127.0.0.1 , 埠號為 6379 , 而將這個主伺服器判斷為失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)。 -
down-after-milliseconds
:選項指定了 Sentinel 認為伺服器host6379已經斷線所需的毫秒數。如果伺服器在給定的毫秒數之內, 沒有返回 Sentinel 傳送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 將這個伺服器標記為主觀下線。 只有在足夠數量的 Sentinel 都將一個伺服器標記為主觀下線之後, 伺服器才會被標記為客觀下線,這時自動故障遷移才會執行。-
伺服器對 PING 命令的有效回覆可以是以下三種回覆的其中一種:
- 返回 +PONG 。
- 返回 -LOADING 錯誤。
- 返回 -MASTERDOWN 錯誤。
如果伺服器返回除以上三種回覆之外的其他回覆, 又或者在指定時間內沒有回覆 PING 命令, 那麼 Sentinel 認為伺服器返回的回覆無效(non-valid)。
注意, 一個伺服器必須在 master-down-after-milliseconds 毫秒內, 一直返回無效回覆才會被 Sentinel 標記為主觀下線。
舉個例子, 如果 master-down-after-milliseconds 選項的值為 30000 毫秒(30 秒), 那麼只要伺服器能在每 29 秒之內返回至少一次有效回覆, 這個伺服器就仍然會被認為是處於正常狀態的。
-
-
parallel-syncs
: 選項指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。
工作原理
Redis 的 Sentinel 系統用於管理多個 Redis 伺服器(instance), 該系統執行以下三個任務:
- 監控(Monitoring): Sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。
- 提醒(Notification): 當被監控的某個 Redis 伺服器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程式傳送通知。
- 自動故障遷移(Automatic failover): 當一個主伺服器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器, 並讓失效主伺服器的其他從伺服器改為複製新的主伺服器; 當客戶端試圖連線失效的主伺服器時, 叢集也會向客戶端返回新主伺服器的地址, 使得叢集可以使用新主伺服器代替失效伺服器。
階段一:監控
用於同步各個節點的狀態資訊:
- 獲取master的狀態,master屬性,各個slave的詳細資訊
- 獲取所有slave的狀態(根據master中的slave資訊)
- 各個Sentinel之間資訊同步
階段二:提醒
檢查監視的主從伺服器:
- 每個 Sentinel 會以每兩秒一次的頻率, 通過釋出與訂閱功能, 向被它監視的所有主伺服器和從伺服器的 sentinel:hello 頻道傳送一條資訊, 資訊中包含了 Sentinel 的 IP 地址、埠號和執行 ID (runid)。
- 同步資訊到每個Sentinel
階段三:自動故障遷移
自動故障轉移:
- Sentinel發現Master宕機,主觀下線,同步到其他Sentinel
- 其他的Sentinel去看熱鬧,發現的確是game over了,客觀下線
- Master掛了,所有的Sentinel開始投票選出一個Sentinel去處理故障遷移
- 被選中的Sentinel去所有Slave查詢新Master
- 新master上任,其他slave切換master,原master故障恢復後作為slave連線新Master