1. 程式人生 > 實用技巧 >【Redis】搭建主從複製

【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

連線與斷開

連線

  1. 客戶端傳送命令:
slaveof <masterip> <masterport>
  1. 啟動伺服器引數:
redis-server -slaveof <masterip> <masterport>
  1. 伺服器配置:
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 會開始一次自動故障遷移操作, 它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器, 並讓失效主伺服器的其他從伺服器改為複製新的主伺服器; 當客戶端試圖連線失效的主伺服器時, 叢集也會向客戶端返回新主伺服器的地址, 使得叢集可以使用新主伺服器代替失效伺服器。

階段一:監控

用於同步各個節點的狀態資訊:

  1. 獲取master的狀態,master屬性,各個slave的詳細資訊
  2. 獲取所有slave的狀態(根據master中的slave資訊)
  3. 各個Sentinel之間資訊同步

階段二:提醒

檢查監視的主從伺服器:

  1. 每個 Sentinel 會以每兩秒一次的頻率, 通過釋出與訂閱功能, 向被它監視的所有主伺服器和從伺服器的 sentinel:hello 頻道傳送一條資訊, 資訊中包含了 Sentinel 的 IP 地址、埠號和執行 ID (runid)。
  2. 同步資訊到每個Sentinel

階段三:自動故障遷移

自動故障轉移:

  1. Sentinel發現Master宕機,主觀下線,同步到其他Sentinel
  2. 其他的Sentinel去看熱鬧,發現的確是game over了,客觀下線
  3. Master掛了,所有的Sentinel開始投票選出一個Sentinel去處理故障遷移
  4. 被選中的Sentinel去所有Slave查詢新Master
  5. 新master上任,其他slave切換master,原master故障恢復後作為slave連線新Master

參考連線:
http://www.redis.cn/topics/sentinel.html