redis主从复制

目录

一、什么是redis主从复制

1、主从复制架构

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave)。

数据的复制是单向的,只能由主节点到从节点。

Redis Replication是一种 master-slave 模式的复制机制,这种机制使得 slave 节点可以成为与 master 节点完全相同的副本,可以采用一

主多从或者级联结构。架构如下:

  • 一个master可以有多个slave
  • 一个slave只能有一个master
  • 数据流向是单向的,master到slave

2、redis为什么需要主从复制

使用redis主从复制的原因在于redis单台节点存在以下问题:

(1)、Redis虽然读写的速度都很快,单节点的Redis能够支撑QPS大概在5w左右,如果上千万的用户访问,Redis就承载不了,成为了高并发的瓶颈。

(2)、单节点的Redis不能保证高可用,当Redis因为某些原因意外宕机时,会导致缓存不可用

(3)、CPU的利用率上,单台Redis实例只能利用单个核心,这单个核心在面临海量数据的存取和管理工作时压力会非常大。

二、搭建主从复制

1、涉及主机

角色 主机名 IP地址
master master 192.168.112.40
slave slave1 192.168.112.50
slave slave2 192.168.112.60

2、编译安装redis

所有主机

2.1、获取软件安装包,安装编译环境

yum install -y make gcc tcl
wget https://download.redis.io/releases/redis-5.0.9.tar.gz
tar xf redis-5.0.9.tar.gz

2.2、编译安装

cd redis-5.0.9/src/
make
make PREFIX=/apps/redis install

2.3、配置变量

echo "PATH=/apps/redis/bin:$PATH" > /etc/profile.d/redis.sh
. /etc/profile.d/redis.sh

2.4、验证目录结构

tree /apps/redis/

2.5、准备目录及文件

mkdir /apps/redis/{etc,log,data,run}
cp ~/redis-5.0.9/redis.conf /apps/redis/etc/

3、前台启动redis

redis-server /apps/redis/etc/redis.conf

3.1、消除三个警告提示

不难发现,前台启动时会出现三个WARNING,默认情况, redis配置文件的参数和内核参数不匹配, 因此还需要修改配置参数, 否则启动时会有警告, 但是并不影响使用

echo "net.core.somaxconn = 1024" >> /etc/sysctl.conf
[root@master src]# sysctl -p
net.core.somaxconn = 1024
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
[root@master src]# sysctl -p
net.core.somaxconn = 1024
vm.overcommit_memory = 1
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local

再次启动redis可以看到警告消除

redis-server /apps/redis/etc/redis.conf

4、使用systemctl管理redis

4.1、创建redis用户

useradd -r -s /sbin/nologin redis
chown -R redis.redis /apps/redis/

4.2、编辑redis服务启动文件

vim /lib/systemd/system/redis.service

[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target

4.3、验证redis启动

reids的默认启动端口是6379

systemctl daemon-reload
systemctl enable --now redis
ss -ntl

5、使用客户端连接redis

  • 格式:

    redis-cli -h IP/HOSTNAME -p PORT -a PASSWORD
    
  • 连接实例:

    redis-cli
    127.0.0.1:6379> info
    127.0.0.1:6379> exit
    

6、设置登陆密码、修改监听地址、数据目录、日志,PID文件路径

6.1、修改配置文件

 sed -i -e "s/bind 127.0.0.1/bind 0.0.0.0/" -e "/# requirepass/a requirepass centos" -e "/^dir .*/c dir /apps/redis/data/" -e "/logfile .*/c logfile /apps/reids/log/redis_6379.log" -e "/^pidfile .*/c pidfile /apps/redis/run/redis_6379.pid" /apps/redis/etc/redis.conf

6.2、重启redis

systemctl restart redis
redis-cli
127.0.0.1:6379> info
NOAUTH Authentication required.
127.0.0.1:6379> auth centos
OK

7、创建命令软链接

ln -s /apps/redis/bin/ /usr/bin/

8、启用主从同步

  • 默认redis 状态为master,需要转换为slave角色并指向master服务器的IP+PORT+Password
  • REPLICAOF MASTER_IP PORT 指令可以启用主从同步复制功能,早期版本使用 SLAVEOF 指令

8.1、在master上设置key1

[root@master ~]# redis-cli -a centos
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:f4efa528f4a3d63441a78ae714b3165a2c962fa4
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
127.0.0.1:6379> set key1 v1-master
OK
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> get key1
"v1-master"
127.0.0.1:6379>

8.2、slave登录设置key1

slave1

[root@slave1 ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:53bb55466d846a521874f723a093                                               512a4ebcd55b
master_replid2:000000000000000000000000000                                               0000000000000
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
127.0.0.1:6379> set key1 v1-slave1
OK
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> get key1
"v1-slave1"
127.0.0.1:6379>

slave2

[root@slave2 ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:ba138fa5f600850d0339b347f388                                               af2655504162
master_replid2:000000000000000000000000000                                               0000000000000
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
127.0.0.1:6379> set key1 v1-slave2
OK
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> get key1
"v1-slave2"
127.0.0.1:6379>

8.3、所有slave设置master的IP和端口

slave1:

127.0.0.1:6379> replicaof 192.168.112.40 6379
OK
127.0.0.1:6379> config set masterauth centos
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.40
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2132feee25664555e9ef7b6c1d20d105ee308e3d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0
127.0.0.1:6379> get key1
"v1-master"·

slave2:

127.0.0.1:6379> replicaof 192.168.112.40 6379
OK
127.0.0.1:6379> config set masterauth centos
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.40
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:70
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2132feee25664555e9ef7b6c1d20d105ee308e3d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:57
repl_backlog_histlen:14
127.0.0.1:6379> get key1
"v1-master"

这里特地在两台slave上设置不同的数据是为了验证Slave 端切换master同步后会丢失之前的所有数据

8.4、master端验证slave信息

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.112.50,port=6379,state=online,offset=378,lag=1
slave1:ip=192.168.112.60,port=6379,state=online,offset=378,lag=1
master_replid:2132feee25664555e9ef7b6c1d20d105ee308e3d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:378
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:378

9、删除主从同步

9.1、slave节点取消主从复制

REPLICAOF NO ONE 指令可以取消主从复制

在任意一台slave上操作:

127.0.0.1:6379> replicaof no one
OK
127.0.0.1:6379> info replication
# Replication
role:master		#角色变为master
connected_slaves:0
master_replid:e8839adba5e81db5da86007a3b2bbdcc7d84de7d
master_replid2:2132feee25664555e9ef7b6c1d20d105ee308e3d
master_repl_offset:2464
second_repl_offset:2465
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:57
repl_backlog_histlen:2408

9.2、在master上验证

可以看到slave数量减少为1

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.112.50,port=6379,state=online,offset=2492,lag=0
master_replid:2132feee25664555e9ef7b6c1d20d105ee308e3d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2492
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2492

10、同步日志

10.1、各个节点上观察日志

master上:

[root@master ~]# tail /apps/redis/log/redis_6379.log
22618:M 15 Apr 2024 15:35:25.707 * Synchronization with replica 192.168.112.50:6379 succeeded
22618:M 15 Apr 2024 15:36:09.639 * Replica 192.168.112.60:6379 asks for synchronization
22618:M 15 Apr 2024 15:36:09.639 * Full resync requested by replica 192.168.112.60:6379
22618:M 15 Apr 2024 15:36:09.639 * Starting BGSAVE for SYNC with target: disk
22618:M 15 Apr 2024 15:36:09.639 * Background saving started by pid 22639
22639:C 15 Apr 2024 15:36:09.640 * DB saved on disk
22639:C 15 Apr 2024 15:36:09.640 * RDB: 0 MB of memory used by copy-on-write
22618:M 15 Apr 2024 15:36:09.647 * Background saving terminated with success
22618:M 15 Apr 2024 15:36:09.647 * Synchronization with replica 192.168.112.60:6379 succeeded
22618:M 15 Apr 2024 16:05:22.257 # Connection with replica 192.168.112.60:6379 lost.

slave节点:

[root@slave1 ~]# tail /apps/redis/log/redis_6379.log
12569:S 15 Apr 2024 15:35:25.702 * Connecting to MASTER 192.168.112.40:6379
12569:S 15 Apr 2024 15:35:25.702 * MASTER <-> REPLICA sync started
12569:S 15 Apr 2024 15:35:25.703 * Non blocking connect for SYNC fired the event.
12569:S 15 Apr 2024 15:35:25.703 * Master replied to PING, replication can continue...
12569:S 15 Apr 2024 15:35:25.703 * Partial resynchronization not possible (no cached master)
12569:S 15 Apr 2024 15:35:25.704 * Full resync from master: 2132feee25664555e9ef7b6c1d20d105ee308e3d:0
12569:S 15 Apr 2024 15:35:25.709 * MASTER <-> REPLICA sync: receiving 196 bytes from master
12569:S 15 Apr 2024 15:35:25.709 * MASTER <-> REPLICA sync: Flushing old data
12569:S 15 Apr 2024 15:35:25.709 * MASTER <-> REPLICA sync: Loading DB in memory
12569:S 15 Apr 2024 15:35:25.709 * MASTER <-> REPLICA sync: Finished with success

10.2、修改slave节点

slave1:

[root@slave1 ~]# echo "replicaof 192.168.112.40 6379" >> /apps/redis/etc/redis.conf
[root@slave1 ~]# echo "masterauth centos" >> /apps/redis/etc/redis.conf
[root@slave1 ~]# systemctl restart redis

slave2:

[root@slave2 ~]# echo "replicaof 192.168.112.40 6379" >> /apps/redis/etc/redis.conf
[root@slave2 ~]# echo "masterauth centos" >> /apps/redis/etc/redis.conf
[root@slave2 ~]# systemctl restart redis

10.3、登录查看master和slave状态

master:

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.112.50,port=6379,state=online,offset=4816,lag=0
slave1:ip=192.168.112.60,port=6379,state=online,offset=4816,lag=0

slave1:

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.40
master_port:6379
master_link_status:up

slave2:

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.40
master_port:6379
master_link_status:up

三、模拟master节点宕机

1、停止master的redis服务

[root@master ~]# systemctl stop redis

slave节点观察:

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.40
master_port:6379
master_link_status:down		#显示down,表示无法连接master

2、观察slave节点日志

[root@slave1 ~]# tail /apps/redis/log/redis_6379.log
23515:S 15 Apr 2024 16:51:45.023 # Error condition on socket for SYNC: Connection refused
23515:S 15 Apr 2024 16:51:46.043 * Connecting to MASTER 192.168.112.40:6379
23515:S 15 Apr 2024 16:51:46.043 * MASTER <-> REPLICA sync started
23515:S 15 Apr 2024 16:51:46.043 # Error condition on socket for SYNC: Connection refused
23515:S 15 Apr 2024 16:51:47.055 * Connecting to MASTER 192.168.112.40:6379
23515:S 15 Apr 2024 16:51:47.056 * MASTER <-> REPLICA sync started
23515:S 15 Apr 2024 16:51:47.056 # Error condition on socket for SYNC: Connection refused
23515:S 15 Apr 2024 16:51:48.078 * Connecting to MASTER 192.168.112.40:6379
23515:S 15 Apr 2024 16:51:48.078 * MASTER <-> REPLICA sync started
23515:S 15 Apr 2024 16:51:48.079 # Error condition on socket for SYNC: Connection refused

3、观察slave状态

[root@slave1 ~]# redis-cli -a centos
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> set key1 v1-slave1
(error) READONLY You can't write against a read only replica.
127.0.0.1:6379> get key1
"v1-master"

发现slave状态只读无法写入数据

四、主从复制故障恢复

1、slave节点故障与恢复

client指向另一个从节点即可,并及时修复故障从节点

2、master节点故障与恢复

需要提升slave为新的master

master故障后,只能手动提升一个slave为新master,不支持自动切换。master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致从而会引发所有slave的全量同步

3、主从复制故障恢复实现

当前主从复制中master节点故障

[root@master ~]# systemctl stop redis

3.1、停止slave1主从同步并提升为新的master

slave1:

127.0.0.1:6379> replicaof no one
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:a3bc41f15f4e2f0f701c452eeaf24a6080ade51c
master_replid2:2132feee25664555e9ef7b6c1d20d105ee308e3d
master_repl_offset:5488
second_repl_offset:5489
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:5488
127.0.0.1:6379> set keytest1 vtest1
OK

3.2、修改剩下的slave指向新的master节点

slave2:

127.0.0.1:6379> replicaof 192.168.175.20 6379
OK
127.0.0.1:6379> config set masterauth centos
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.50
master_port:6379
master_link_status:up
127.0.0.1:6379> set key100 v100
(error) READONLY You can't write against a read only replica.		#只读
127.0.0.1:6379> get keytest1
"vtest1"

3.3、在新的master节点查看slave信息

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.112.60,port=6379,state=online,offset=5830,lag=1

五、实现redis的级联复制

Redis 的级联复制(Cascade Replication)是指在主从复制的基础上,通过创建多级复制链路,使得一个 Redis 从节点不仅作为其直接主节点的副本,还能充当其他从节点的主节点。这种结构允许数据复制跨越多个层级,形成一种树状拓扑结构。

1、涉及主机

角色 主机名 IP地址
主节点 master 192.168.112.10
一级从节点 slave1 192.168.112.20
二级从节点 slave2 192.168.112.30
二级从节点 slave3 192.168.112.40

2、所有主机安装reids

3、搭建一主一从

3.1、主节点创建验证数据

master:

[root@master ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> set key-test1 test1
OK
127.0.0.1:6379> keys *
1) "key-test1"
127.0.0.1:6379> get key-test1
"test1"

3.2、一级从节点设置master的IP和端口

slave1:

[root@slave1 ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> replicaof 192.168.112.10 6379
OK
127.0.0.1:6379> config set masterauth centos
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.10
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:14
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:c8e3d3769a39454be02a13bec0324b01b43c81b7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
127.0.0.1:6379> get key-test1
"test1"

4、修改二级从节点指向一级从节点作为master

slave2:

[root@slave2 ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> replicaof 192.168.112.20 6379
OK
127.0.0.1:6379> config set masterauth centos
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.20
master_port:6379
master_link_status:up
127.0.0.1:6379> keys *
1) "key-test1"
127.0.0.1:6379> get key-test1
"test1"

slave3:

[root@slave3 ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> replicaof 192.168.112.20 6379
OK
127.0.0.1:6379> config set masterauth centos
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.20
master_port:6379
master_link_status:up
127.0.0.1:6379> keys *
1) "key-test1"
127.0.0.1:6379> get key-test1
"test1"

5、在master上设置key,观察是否同步

127.0.0.1:6379> set name misaki
OK
127.0.0.1:6379> get name
"misaki"

5.1、在slave上进行验证

127.0.0.1:6379> get name
"misaki"

6、在一级从节点上查看状态

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.112.10
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6	#最近一次与master通信已经过去多少秒
master_sync_in_progress:0	#是否正在与master通信
slave_repl_offset:1332		#当前同步的偏移量
slave_priority:100		 #slave优先级,master故障后优先级值越小越优先同步
slave_read_only:1
connected_slaves:2
slave0:ip=192.168.112.30,port=6379,state=online,offset=1332,lag=1
slave1:ip=192.168.112.40,port=6379,state=online,offset=1332,lag=1
master_replid:c8e3d3769a39454be02a13bec0324b01b43c81b7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1332
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1332

热门相关:天王的专属恋人:独家宝贝   重生田园贵媛:名门暖婚   回应我   逼婚首席:影后前妻很抢手   甜蜜婚令:首长的影后娇妻