Redis05-進階-主從
1、搭建主從架構
(1)概述
單節點Redis的并發能力是有上限的,要進一步提高Redis的并發能力,就需要搭建主從集群,實現讀寫分離。
(2)集群概況
我們搭建的主從集群共包含三個節點,一個主節點,兩個從節點。操作系統是 CentOS7.9。 這里我們會在同一臺虛擬機中開啟3個redis實例,模擬主從集群,信息如下:
IP 配置文件路徑 PORT 角色 192.168.119.171 /etc/redis/7001/redis.conf 7001 master 192.168.119.171 /etc/redis/7002/redis.conf 7002 slave 192.168.119.171 /etc/redis/7003/redis.conf 7003 slave
(3)準備實例配置
**創建目錄:**要在同一臺虛擬機開啟3個實例,必須準備三份不同的配置文件和目錄,配置文件所在目錄也就是工作目錄。我們創建三個文件夾,名字分別叫7001、7002、7003。
cd /etc/redis/
mkdir 7001 7002 7003
配置文件/etc/redis/7001/redis.conf 配置如下,這個是 master 節點的配置
bind 0.0 .0.0
protected-mode no
daemonize yes
save 3600 1
save 300 100
save 60 10000
appendonly no
replica-announce-ip 192.168 .119.171
port 7001
dir /etc/redis/7001/
配置文件/etc/redis/7002/redis.conf 配置如下,這個是 slave 節點的配置
bind 0.0 .0.0
protected-mode no
daemonize yes
save 3600 1
save 300 100
save 60 10000
appendonly no
replica-announce-ip 192.168 .119.171
port 7002
dir /etc/redis/7002/
slaveof 192.168 .119.171 7001
配置文件/etc/redis/7003/redis.conf 配置如下,這個是 slave 節點的配置
bind 0.0 .0.0
protected-mode no
daemonize yes
save 3600 1
save 300 100
save 60 10000
appendonly no
replica-announce-ip 192.168 .119.171
port 7003
dir /etc/redis/7003/
slaveof 192.168 .119.171 7001
配置說明: **持久化配置:**持久化模式改為默認的RDB模式,AOF保持關閉狀態。 修改 **bind**
** 參數:** bind 0.0.0.0
允許所有 IP 連接。**修改實例的聲明IP:**虛擬機本身有多個IP,為了避免混亂,我們需要指定每一個實例的 IP 信息。 **修改每個實例的端口、工作目錄:**修改每個文件夾內的配置文件,將端口分別修改為7001、7002、7003,將rdb文件保存位置都修改為自己所在目錄。 **為每個slave 節點開啟主從關系:**slaveof 192.168.119.171 7001
(4)啟動實例
sudo systemctl stop firewalld
sudo systemctl disable firewalld
我們打開3個ssh窗口,分別啟動3個redis實例,啟動命令:
redis-server /etc/redis/7001/redis.conf
redis-server /etc/redis/7002/redis.conf
redis-server /etc/redis/7003/redis.conf
printf '%s\n ' 7001 7002 7003 | xargs -I{ } -t redis-cli -p { } shutdown
(5)開啟主從關系
要配置主從可以使用replicaof 或者slaveof(5.0以前)命令。 有臨時和永久兩種模式: 永久:修改配置文件,在redis.conf中添加一行配置:slaveof <masterip> <masterport>
。 臨時:使用redis-cli客戶端連接到redis服務,執行slaveof命令(重啟后失效)。 注意:在5.0以后新增命令replicaof,與salveof效果一致。 上面已經用配置文件實現了主從關系,現在演示命令方式。
redis-cli -p 7002
slaveof 192.168 .119.171 7001
redis-cli -p 7003
slaveof 192.168 .119.171 7001
redis-cli -p 7001
info replication
role:master
connected_slaves:2
slave0:ip= 192.168 .119.171,port= 7002 ,state= online,offset= 56 ,lag= 1
slave1:ip= 192.168 .119.171,port= 7003 ,state= online,offset= 56 ,lag= 1
master_failover_state:no-failover
master_replid:9416e12727f8b889f6293c3eedcb9f07de1670d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56
(6)測試
利用redis-cli連接7001,執行set num 123
利用redis-cli連接7002,執行get num
,再執行set num 666
127.0 .0.1:7002 > get num
"123"
127.0 .0.1:7002 > set num 666
( error) READONLY You can't write against a read only replica.
利用redis-cli連接7003,執行get num
,再執行set num 888
127.0 .0.1:7003 > get num
"123"
127.0 .0.1:7003 > set num 888
( error) READONLY You can't write against a read only replica.
可以發現,只有在7001這個master節點上可以執行寫操作,7002和7003這兩個slave節點只能執行讀操作。
(7)設置開機啟動
為了使 Redis 在系統啟動時自動運行,可以創建一個 systemd 服務文件:
vi /etc/systemd/system/redismaster.service[ Unit]
Description = redismaster
After = network.target[ Service]
Type = forking
ExecStart = /usr/local/bin/redis-server /tmp/7001/redis.conf
PrivateTmp = true[ Install]
WantedBy = multi-user.target
systemctl daemon-reload
systemctl start redismaster
systemctl stop redismaster
systemctl restart redismaster
systemctl status redismaster
systemctl enable redismaster
vi /etc/systemd/system/redisslave01.service[ Unit]
Description = redisslave01
After = network.target[ Service]
Type = forking
ExecStart = /usr/local/bin/redis-server /tmp/7002/redis.conf
PrivateTmp = true[ Install]
WantedBy = multi-user.target
vi /etc/systemd/system/redisslave02.service[ Unit]
Description = redisslave02
After = network.target[ Service]
Type = forking
ExecStart = /usr/local/bin/redis-server /tmp/7003/redis.conf
PrivateTmp = true[ Install]
WantedBy = multi-user.target
2、數據同步原理
(1)主從第一次執行全量同步
slave節點請求增量同步 master節點判斷replid,發現不一致,拒絕增量同步 master將完整內存數據生成RDB,發送RDB到slave slave清空本地數據,加載master的RDB master將RDB期間的命令記錄在repl_baklog,并持續將log中的命令發送給slave slave執行接收到的命令,保持與master之間的同步
(2)如何判斷是第一次同步數據
Replication Id:簡稱replid,是數據集的標記,id一致則說明是同一數據集。每一個master都有唯一的replid,slave則會繼承master節點的replid offset:偏移量,隨著記錄在repl_baklog中的數據增多而逐漸增大。slave完成同步時也會記錄當前同步的offset。如果slave的offset小于master的offset,說明slave數據落后于master,需要更新。 因此slave做數據同步,必須向master聲明自己的replication id 和offset,master才可以判斷到底需要同步哪些數據。
(3)slave重啟后執行增量同步
repl_baklog大小有上限,寫滿后會覆蓋最早的數據。如果slave斷開時間過久,導致尚未備份的數據被覆蓋,則無法基于log做增量同步,只能再次全量同步。
(4)主從集群優化
在master中配置repl-diskless-sync yes啟用無磁盤復制,避免全量同步時的磁盤IO。 Redis單節點上的內存占用不要太大,減少RDB導致的過多磁盤IO 適當提高repl_baklog的大小,發現slave宕機時盡快實現故障恢復,盡可能避免全量同步 限制一個master上的slave節點數量,如果實在是太多slave,則可以采用主-從-從鏈式結構,減少master壓力