12.Redis 主从复制
Redis 主从复制
- Redis 主从复制
- 1. Redis 主从复制架构
- 2. 主从复制实现
- 2.1 主从命令配置
- 2.1.1 启用主从同步
- 2.1.2 查看日志观察同步状态
- 2.1.3 修改 Slave 节点配置文件
- 2.1.4 删除主从同步
- 3. 主从复制故障恢复
- 3.1 Slave 节点故障和恢复
- 3.2 Master 节点故障和恢复
- 3.3 常见主从复制故障
- 4. 主从复制优化
- 4.1 避免全量复制
- 4.2 避免复制风暴
- 4.3 性能相关配置
Redis 主从复制
Redis单机服务存在数据和服务的单点问题,而且单机性能也存在着上限,可以利用Redis的集群相关技术来解决这些问题
1. Redis 主从复制架构
Redis和MySQL的主从模式类似,也支持主从模式(master/slave),可以实现Redis数据的跨主机的远程备份
常见客户端连接主从的架构:
程序APP先连接到高可用性 LB 集群提供的虚拟IP,再由LB调度将用户的请求至后端Redis 服务器来真正提供服务
主从复制特点
- 一个master可以有多个slave
- 一个slave只能有一个master
- 数据流向是从master到slave单向的
- master 可读可写 slave 只读
2. 主从复制实现
当master出现故障后,可以自动提升一个slave节点变成新的Mster,因此Redis Slave 需要设置和master相同的连接密码
此外当一个Slave提升为新的master时需要通过持久化实现数据的恢复
当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的主节点Redis服务应该要避免自动启动
导致主从服务器数据全部丢失
- 假设节点A为主服务器,并且关闭了持久化。并且节点B和节点C从节点A复制数据
- 节点A崩溃,然后由自动拉起服务重启了节点A,由于节点A的持久化被关闭了,所以重启之后没有任何数据
- 节点B和节点C将从节点A复制数据,但是A的数据是空的,于是就把自身保存的数据副本删除。
在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用Sentinel来实现Redis的高可用性,也是非常危险的。因为主服务器可能拉起得非常快,以至于Sentinel在配置的心跳时间间隔内没有检测到主服务器已被重启,然后还是会发生上面描述的情况,导致数据丢失
无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动启动
主从复制过程
Redis主从复制分为全量同步和增量同步
Redis 的主从同步是非阻塞的,即同步过程不会影响主服务器的正常访问
注意:主节点重启会导致全量同步,从节点重启只会导致增量同步
全量复制过程 Full resync
- 主从节点建立连接,验证身份后,从节点向主节点发送PSYNC(2.8版本之前是SYNC)命令
- 主节点向从节点发送FULLRESYNC命令,包括master_replid(runID)和offset
- 从节点保存主节点信息
- 主节点执行BGSAVE保存RDB文件,同时记录新的记录到buffer中
- 主节点发送RDB文件给从节点
- 主节点将新收到buffer中的记录发送至从节点
- 从节点删除本机的旧数据
- 从节点加载RDB
- 从节点同步主节点的buffer信息
全量复制发生在下面情况
- 从节点首次连接主节点(无master_replid/run_id)
- 从节点的复制偏移量不在复制积压缓冲区内
- 从节点无法连接主节点超过一定的时间
增量复制过程
在主从复制首次完成全量同步之后再次需要同步时,从服务器只要发送当前的offset位置(类似于MySQL的 binlog的位置)给主服务器,然后主服务器根据相应的位置将之后的数据(包括写在缓冲区的积压数据)发送给从服务器,再次将其保存到从节点内存即可。 即首次全量复制,之后的复制基本增量复制实现。
主从同步完整过程
- slave发起连接master,验证通过后,发送PSYNC命令
- master接收到PSYNC命令后,执行BGSAVE命令将全部数据保存至RDB文件中,并将后续发生的写操作记录至buffer中
- master向所有slave发送RDB文件
- master向所有slave发送后续记录在buffer中写操作
- slave收到快照文件后丢弃所有旧数据
- slave加载收到的RDB到内存
- slave 执行来自master接收到的buffer写操作
- 当slave完成全量复制后,后续master只会先发送slave_repl_offset信息
- 以后slave比较自身和master的差异,只会进行增量复制的数据即可
注意:Redis 重启服务后,master_replid(runID)会发生变化。
复制缓冲区(环形队列)配置参数
#master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如:master每秒最大写入64mb,最大允许60秒,那么就要设置为64mb*60秒=3840MB(3.8G),建议此值是设置的足够大,默认值为1M
repl-backlog-size 1mb #如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则表示永远不释放这部份内存。
repl-backlog-ttl 3600
2.1 主从命令配置
2.1.1 启用主从同步
Redis Server 默认为 master节点,如果要配置为从节点,需要指定master服务器的IP,端口及连接密码
在从节点执行 REPLICAOF MASTER_IP PORT 指令可以启用主从同步复制功能,早期版本使用 SLAVEOF 指令
127.0.0.1:6379> REPLICAOF MASTER_IP PORT #新版推荐使用
127.0.0.1:6379> SLAVEOF MasterIP Port #旧版使用,将被淘汰
127.0.0.1:6379> CONFIG SET masterauth <masterpass>
先通过一键编译脚本在三台主机上安装好redis,搭建一主两从
主机IP | 节点 |
---|---|
10.0.0.100 | 主 |
10.0.0.101 | 从 |
10.0.0.102 | 从 |
准备阶段:
# 在mater上设置一些key方便观察
[root@ubuntu2204 ~]#redis-cli -a 123456 info keyspace
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Keyspace
db0:keys=1000,expires=0,avg_ttl=0# 两个从节点目前没有key
[root@ubuntu2204 ~]#redis-cli -a 123456 info keyspace
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Keyspace# 三个节点默认都是master
[root@ubuntu2204 ~]#redis-cli -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:b60b6478f2bb8d8a2e356b9d3c8540492e828708
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
具体搭建步骤:
# 两个从节点都执行
[root@ubuntu2204 ~]#redis-cli -a 123456
# 在slave上设置master的IP和端口
127.0.0.1:6379> replicaof 10.0.0.100 6379
OK# 在slave上设置master的密码,才可以同步
127.0.0.1:6379> config set masterauth 123456
OK# 查看是否成为slave
127.0.0.1:6379> info replication# 查看是否同步成功
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1000,expires=0,avg_ttl=0# 主节点上查看
# 在master上可以看到所有slave信息
127.0.0.1:6379> info replication
2.1.2 查看日志观察同步状态
# 主从节点分别在同步之前打开日志观察
[root@ubuntu2204 ~]#tail -f /apps/redis/log/redis_6379.log
2.1.3 修改 Slave 节点配置文件
[root@ubuntu2204 ~]#vim /apps/redis/etc/redis.conf(大约在533、540行附近)
replicaof 10.0.0.100 6379
masterauth 123456注意:requirepass 123456 的密码要和masterauth保持一致,用于将来从节点提升主后使用。# 重启redis服务
[root@ubuntu2204 ~]#systemctl restart redis# Master和Slave查看状态
[root@ubuntu2204 ~]#redis-cli -a 123456
127.0.0.1:6379> info replication注意:
master_link_status:up
master_last_io_seconds_ago:6 # 如果主从复制通信正常,每10秒重新从0计数,此值无法修改,如果无法通信,当计数到60时,master_link_status显示为down
master_sync_in_progress:0 # 0表示同步完成,1表示正在同步# 查看是否同步成功
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1000,expires=0,avg_ttl=0# Slave 只读状态
127.0.0.1:6379> set key1 v1
(error) READONLY You can't write against a read only replica.
2.1.4 删除主从同步
在从节点执行 REPLICAOF NO ONE 或 SLAVEOF NO ONE 指令可以取消主从复制
取消复制会断开和master的连接而不再有主从复制关联, 但不会清除slave上已有的数据
# 新版
127.0.0.1:6379> REPLICAOF NO ONE# 旧版
127.0.0.1:6379> SLAVEOF NO ONE
3. 主从复制故障恢复
3.1 Slave 节点故障和恢复
当 slave 节点故障时,将Redis Client指向另一个 slave 节点即可,并及时修复故障从节点
3.2 Master 节点故障和恢复
当 master 节点故障时,需要提升slave为新的master
master故障后,当前还只能手动提升一个slave为新master,不能自动切换。
之后将其它的slave节点重新指定新的master为master节点
Master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致从而会引发所有 slave的全量同步。
具体操作步骤:
1.查看当前节点的状态为是否为slave,master指向是否是故障的master节点
2.停止slave同步并提升为新的master 使用命令 REPLICAOF NO ONE ,配置文件也要修改
3.修改所有slave 指向新的master节点使用命令 replicaof 新masterIP地址 6379 ,配置文件也要修改
4.在新master节点上查看状态
3.3 常见主从复制故障
主从硬件和软件配置不一致
主从节点的maxmemory不一致,主节点内存大于从节点内存,主从复制可能丢失数据
rename-command 命令不一致,如在主节点启用flushdb,从节点禁用此命令,结果在master节点执行 flushdb后,导致slave节点不同步
Master 节点密码错误
如果slave节点配置的master密码错误,导致验证不通过,自然将无法建立主从同步关系。
Redis 版本不一致
不同的redis 版本之间尤其是大版本间可能会存在兼容性问题,如:Redis 3,4,5,6之间
因此主从复制的所有节点应该使用相同的版本
安全模式下无法远程连接
如果开启了安全模式,并且没有设置bind地址和密码,会导致无法远程连接
4. 主从复制优化
4.1 避免全量复制
- 第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),业务低峰时进行全量
- 节点RUN_ID不匹配:主节点重启会导致RUN_ID变化,可能会触发全量复制,可以利用config命令动态修改配置,故障转移例如哨兵或集群选举新的主节点也不会全量复制,而从节点重启动,不会导致全量复制,只会增量复制
- 复制积压缓冲区不足: 当主节点生成的新数据大于缓冲区大小,从节点恢复和主节点连接后,会导致全量复制 解决方法将repl-backlog-size 调大
4.2 避免复制风暴
单主节点复制风暴
当主节点重启,多从节点复制
解决方法:更换复制拓扑(级联复制)
单机器多实例复制风暴
机器宕机后,大量全量复制
解决方法:主节点分散多机器
4.3 性能相关配置
Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从2.8版本开始增加了部分复制的功能。
repl-diskless-sync no # 是否使用无盘方式进行同步RDB文件,默认为no(编译安装默认为yes),no表示不使用无盘,需要将RDB文件保存到磁盘后再发送给slave,yes表示使用无盘,即RDB文件不需要保存至本地磁盘,而且直接通过网络发送给slaverepl-diskless-sync-delay 5 # 无盘时复制的服务器等待的延迟时间repl-ping-slave-period 10 # slave向master发送ping指令的时间间隔,默认为10srepl-timeout 60 # 指定ping连接超时时间,超过此值无法连接,master_link_status显示为down状态,并记录错误日志repl-disable-tcp-nodelay no # 是否启用TCP_NODELAY
# 设置成yes,则redis会合并多个小的TCP包成一个大包再发送,此方式可以节省带宽,但会造成同步延迟时长的增加,导致master与slave数据短期内不一致
# 设置成no,则master会立即同步数据repl-backlog-size 1mb # master的写入数据缓冲区,用于记录自上一次同步后到下一次同步前期间的写入命令,计算公式:repl-backlog-size = 允许slave最大中断时长 * master节点offset每秒写入量,如:master每秒最大写入量为32MB,最长允许中断60秒,就要至少设置为32*60=1920MB,建议此值是设置的足够大,如果此值太小,会造成全量复制repl-backlog-ttl 3600 # 指定多长时间后如果没有slave连接到master,则backlog的内存数据将会过期。如果值为0表示永远不过期。 slave-priority 100 # slave参与选举新的master的优先级,此整数值越小则优先级越高。当master故障时将会按照优先级来选择slave端进行选举新的master,如果值设置为0,则表示该slave节点永远不会被选为master节点。min-replicas-to-write 1 # 指定master的可用slave不能少于个数,如果少于此值,master将无法执行写操作,默认为0,生产建议设为1,min-slaves-max-lag 20 # 指定至少有min-replicas-to-write数量的slave延迟时间都大于此秒数时,master将不能执行写操作,默认为10s