Redis的主從複制
概述
與mysql的主從複制思想類似,主伺服器資料更新後根據配置和政策自動同步到從伺服器上。Master以寫為主,Slave以讀為主。
主從複制可以實作資料的讀寫分離以及資料的容災恢複(若master節點崩潰,可根據slave節點的rdb檔案恢複資料)
原理
slave啟動成功後連接配接到master後會發送一個sync指令,master接到指令啟動背景的存盤程序,同時收集所有接收到的用于修改資料集的指令,在背景程序執行完畢後,master将傳送整個檔案到slave,以完成一次完全同步。
而slave服務在接收到資料庫檔案資料後,将其存盤并加載到記憶體中(這是一次全量複制)。master繼續将新的所有收集到的修改目錄依次傳給slave,完成同步(增量複制)。
隻要是重新連接配接master,首先會自動執行一次全量複制
使用
原則:配從(庫)不配主(庫)
配置方式:
- 在從伺服器上輸入指令 slaveof 主庫ip 主庫端口。但是每次與master端開連接配接之後,都需要重新連接配接。
- 直接配置到redis.conf中。比如我使用的redis版本中,配置檔案中不存在slaveof,取而代之的是replicaof。配置方式一樣:replicaof <masterip> <masterport>
info replication檢視主從複制資訊,預設每個redis節點都是一個master節點
127.0.0.1:6379> INFO REPLICATION
# Replication
role:master
connected_slaves:0
master_replid:cde1187a5488fe33a59dced3537a8d2c44c1e6d1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
示範1主2從的主從複制的配置操作
主 redis配置名稱 redis6379.conf,端口6379,pid檔案名稱 /var/run/redis_6379.pid,log名稱 redis6379.log,rdb檔案名稱 dump6379.rdb
1從 redis配置名稱 redis6380conf,端口6380,pid檔案名稱 /var/run/redis_6380.pid,log名稱 redis6380.log,rdb檔案名稱 dump6380.rdb
另一從 redis配置名稱 redis6381.conf,端口6381,pid檔案名稱 /var/run/redis_6381.pid,log名稱 redis6381.log,rdb檔案名稱 dump6381.rdb
配置完畢後,分别啟動這三個服務,如
可以看到初始情況下,各個節點預設都是master節點。
下面将6380端口服務、6381端口服務設定為6379端口服務的從節點。
6380服務:
slaveof 127.0.0.1 6379
6381服務:
REPLICAOF 127.0.0.1 6379
指令執行均ok,但是通過info replication檢視主從資訊時 發現master節點中**connected_slaves:0,而slave節點中master_link_status:down。**這意味着主從配置似乎沒成功,檢視slave6380的日志,發現端倪:
報錯資訊NOAUTH Authentication required似乎與密碼認證有關。突然想到我們的master節點設定了登入密碼。通過排查,隻需要在slave節點的配置檔案中添加配置:masterauth 123456(我的master登入密碼是123456)。
随後重新開機從節點,重新執行slaveof指令,運作成功:
是以,如果master不設定密碼,那麼直接在slave伺服器配置slaveof/replicaof即可;master設定密碼的情況下同步資料,我們隻要讓slave能連上master就可以了,即我們在slave的配置檔案中加上"masterauth 密碼"即可。
示範主從複制的基本使用
現在我們模拟的三台服務已具備主從關系
正常使用
主節點寫入兩個key,從節點立刻可以讀到資料
疑問
-
切入點問題。從節點6380、6381是從master的頭開始複制資料還是隻複制這兩個節點成為為從節點時刻後之後的資料呢?
針對這個問題,這裡6379節點先設定三個字元串值,分别是k1-v1,k2-v2,k3-v3。然後6380節點和6381節點才成為6379節點的從節點。然後立刻在從節點中擷取k1/k2/k3的值,如果擷取到舊說明是從頭開始複制的
結論:從頭開始複制
2.主節點可讀可寫,那麼從節點是否可以寫呢?
## 在從節點上執行寫操作 報錯
127.0.0.1:6380> set k4 v4
(error) READONLY You can't write against a read only replica.
通過報錯資訊可知,從節點隻讀。
3.主節點當機了,從節點是什麼都不做,還是會從衆多從節點中重新選出一個主節點呢?
這裡使用shutdown來模拟,主節點當機
可以發現,從節點什麼都沒做,主節點還是指向127.0.0.1:6379。由于master當機了,從節點隻是顯示與主節點未連接配接master_link_status:down
結論:從節點什麼都不做
4.原主節點重新啟動後,在主節點上新增記錄,從節點還能成功同步嗎?
重新啟動原6379主節點
當主節點啟動成功後,新增一條記錄,該記錄迅速地在從節點被擷取到。
這個時候,通過info replication 檢視從節點master_link_status:up,也從側面印證成功連上主節點
結論:還能成功同步
5.一台從節點當機了之後情況如何?
模拟從節點6380當機,将其shutdown
6380節點機器重新開機後,通過info replication檢視此時它為master節點,應該是還沒與其他節點建立主從關系
重新讓6380節點成為6379節點的從節點,發現以前在master上的資料,一個不落的全同步到目前節點了。
注意:為了排除rdb檔案的影響,這次6380節點時将dump6380.rdb檔案删除後才啟動的。這些key确實由主節點同步而來
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
OK
127.0.0.1:6380> keys *
1) "k4"
2) "k2"
3) "k3"
4) "k1"
總結
這種主從複制關系類似于下圖:
這種方式無疑是加劇了主節點的寫壓力,而且以主節點為中心,也無法做到高可用,如果主節點當機,那麼就會有很多資料丢失。
是以可以去中心化
去中心化的主從配置
思想:上一個slave節點是下一個slave節點的master,slave節點可以接收其他slave節點的連接配接和同步請求。同時該slave作為了鍊路中下一個的master節點,也可以有效減輕master的寫壓力。
舉例
以6379節點作為主節點,以6380節點作為從節點,以6381節點作為6380節點的從節點。
是以,隻需要在6381節點上執行指令
SLAVEOF 127.0.0.1 6380
檢視主從關系
可以看到,6380節點同時是6379節點的從節點,也是6381節點的父節點。注意:這裡6380節點的role角色仍然是slave,是以還是不能寫入資料舉例如下圖
可以看出,在master上設定k6-v6,在6380節點和6381節點均能讀取到。想當于對資料做了接力續傳一樣,使從節點不都從主節點擷取資料,降低了主節點的壓力。
手動從節點–>master節點
前提:根據我們之前的認知,主從複制中如果主節點崩潰,那麼從節點隻是靜默什麼都不做。
如果主節點長時間恢複不了,可以使用
slaveof no one
指令,将某個從節點手動設定為主節點,将其他的從節點作為指向目前新主節點。
slaveof no one指令,使目前資料庫停止與其他資料庫的同步,轉為成為主資料庫。
我們把服務恢複成一主二從的情況,主節點6379,從節點6380,6381。
模拟主節點當機,從節點上位
主節點當機後,将6380節點設定為新的主節點,将6381節點作為6380節點的從節點,組成6380節點-6381節點的新的主從關系。
6381節點如果此時不做操作,那麼等待原主節點恢複後,仍然可以組成6379節點-6381節點的主從。
這個時候,6380節點與6381節點就可以完成主從複制了,而原主節點啟動後,也與這兩個節點沒關系了。
主從複制的缺點
由于所有的寫操作都是先在Master上操作,然後同步更新到Slave上,是以從Master同步到Slave機器有一定的延遲,當系統很繁忙的時候,延遲問題會更加嚴重,Slave機器數量的增加也會使這個問題更加嚴重。
哨兵模式
概述
可以自動地進行master節點的選舉,它能夠在背景監控主節點是否故障,如果故障了根據投票數,将投票數都的從節點轉為新的主節點。
配置與啟動
redis安裝包下有sentinel.conf的配置,這裡我備份了sentinel.conf,重建立一個sentin.conf,隻進行少量的配置,重在示範結果。
把服務恢複成一主二從的情況,主節點6379,從節點6380,6381。
sentinel.conf
# Generated by CONFIG REWRITE
port 26379
dir "/Users/wojiushiwo/test_redis"
sentinel monitor redis6379 127.0.0.1 6380 1
sentinel down-after-milliseconds redis6379 15000
sentinel failover-timeout redis6379 900000
## 主節點設定了密碼 是以這裡需要配上認證密碼
sentinel auth-pass redis6379 123456
其中,
sentinel monitor <master-name> <ip> <redis-port> <quorum>
## <master-name> 自己給主節點設定的名稱
## ip 主節點的ip位址
## redis-port 主節點的端口号
如這裡配置的是sentinel monitor redis6379 127.0.0.1 6380 1,其中最後一個數字1,表示主機挂掉後salve投票看讓誰接替成為主機,得票數多少後成為主機
啟動哨兵:
sudo /usr/local/bin/redis-sentinel ~/redis/sentinel.conf
可以從啟動日志可以看出,哨兵一啟動就監控到了從節點
示範主節點挂了後,能否選出新主節點
先在主節點上執行shutdown操作
先從哨兵服務日志看
可以看出6380節點是主節點了,并且把還活着的6381節點也作為了自己的新從節點,甚至把當機的6379節點也作為了自己的新子節點
從info replication來看
确實如我們所說,6380節點變成主節點了,6381節點變成6380節點的從節點了。
重新開機原主節點,看是否如我們所說,它真的變成了6380節點的從節點了。
确實,它變成了從節點