一站式学习Redis, 从入门到高可用分布式实践-07-08复制与哨兵sentinel保证redis的高可用
redis复制的原理与优化
- 复制是实现高可用的基石,但复制同样是运维的痛点,我们来分析复制的原理与运维过程中可能遇到的问题
- 什么是主从复制
- 单机有什么问题呢:机器故障、容量瓶颈、QPS瓶颈
机器故障是高可用问题,容量瓶颈和QPS瓶颈是分布式问题 - 主从复制的作用:数据副本、读写分离
- 小结:一个master可以有多个slaver,一个slaver只能有一个master,数据流向是单向的,只能从master流向slaver
- 主从复制的配置
- 两种实现方式:slaveof命令,配置
(1)slaveof命令
slaveof 127.0.0.1 6380
- 命令取消复制
slaveof no one
注意:此时如果想把当前节点同步到另一个主节点,另一个主节点将数据同步过来之前会把该节点的所有数据清除掉
(2)配置
修改配置
slaveof ip port
修改从节点只读
slave-read-only yes
(3)两种方式的优缺点
(4)只从复制配置
- 主配置
# bind 127.0.0.1 -::1
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dbfilename dump-6379.rdb
dir /opt/soft/redis/data/
# replicaof <masterip> <masterport>
# masterauth <master-password>
replica-read-only no
requirepass 123456
- 从配置
# bind 127.0.0.1 -::1
port 6380
daemonize yes
pidfile /var/run/redis_6380.pid
logfile "6380.log"
dbfilename dump-6380.rdb
dir /opt/soft/redis/data/
replicaof 127.0.0.1 6379
masterauth 123456
replica-read-only yes
requirepass 456789
- 查看复制信息(主从关系信息)
info replication
- 取消从节点的命令
slaveoff no one
- 然后重新设置从节点
slave off 127.0.0.1 6379
当前6380节点又变成了6379的从节点,而且会先把当前6380节点的数据删除,然后再把6379的所有数据拷贝过来,保持数据一致性
- 全量复制和部分复制
- 全量复制
- 全量复制的开销
bgsave时间、rdb文件网络传输时间、从节点清空数据、从节点加载rdb的时间,可能的AOF重写时间 - 部分复制
- 故障处理
- 主从结构故障转移:slave故障、master故障
- 开发运维常见问题
-
读写分离会产生的问题
读写分离读流量分摊到从节点,可能遇到问题,数据复制延迟,读到过期数据(redis.3.2中已经解决了这个问题),从节点故障 -
主从配置不一致
maxmemory不一致:丢失数据,
数据结构优化参数:hash-max-ziplist-entried:内存不一致 -
规避全量复制
第一次全量复制不可避免,小主节点,低峰
节点运行run_id不匹配,主节点重启,run_id变化, 故障转移,例如哨兵或集群
复制积压缓冲区不足,网络中断,部分复制无法满足,增大复制缓冲区配置rel_backlog_size,网络"增强" -
规避复制风暴
单主节点复制风暴
主节点重启,多个从节点会产生复制,解决:更换复制拓扑
单机器复制风暴,机器宕机后,会产生大量全量复制
redis sentinel
- 主从复制问题
- 手动故障转移
- 写能力和存储能力受限
-
redis sentinel架构
-
redis sentinel故障转移
- 多个sentinel发现并确认redis master有问题
- 从多个sentinel中选举出一个作为leader
- 从多个redis slaver中选出一个作为redis master
- 通知其余salver成为新的master的slaver
- 通知客户端主从变化
- 等待老的master复活成为新的master的slaver
注意:一套redis sentinel可以监控多套redis master-slaver
- redis-sentinel的安装与配置
- 配置开启主从节点
- 配置开启sentinel监控主节点,(sentinel是特殊的redis)
- 实际应该多台机器
- 详细配置节点
-
sentinel主要配置
-
redis master-slaver安装演示
- 建立三个节点,一个主节点,两个从节点的配置文件
master:
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
dir "/opt/soft/redis/data/"
slaver01
port 7001
daemonize yes
pidfile /var/run/redis-7001.pid
logfile "7001.log"
dir "/opt/soft/redis/data/"
slaveof ip 7000
slaver02
port 7002
daemonize yes
pidfile /var/run/redis-7002.pid
logfile "7002.log"
dir "/opt/soft/redis/data/"
slaveof ip 7000
- 查看主从关系
info replication
- redis-sentinel安装演示
sudo cat sentinel.conf | grep -v "#" | grep -v "^$" > redis-sentinel-26379.conf
配置文件
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "26379.log"
dir "/opt/soft/redis-stable/data"
sentinel monitor mymaster 127.0.0.1 7000 2
acllog-max-len 128
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames no
sentinel announce-hostnames no
启动sentinel
redis-sentinel redis-sentinel-26379.conf
创建第2个sentinel配置文件
sed "s/26379/26380/g" redis-sentinel-26379.conf > redis-sentinel-26380.conf
启动
redis-sentinel redis-sentinel-26380.conf
然后再按照这种方法启动一个redis-sentinel-26381.conf
- redis-py连接sentinel并进行故障转移演练
import time
from redis.sentinel import Sentinel
sentinel = Sentinel(
[("xxx.cn", 26379), ("xxx.cn", 26380), ("xxx.cn", 26381)],
socket_timeout=0.1,
)
for i in range(10000):
try:
# 通过sentinel获取redis主节点
master_ip, master_port = sentinel.discover_master("mymaster")
print(master_ip, master_port) # 127.0.0.1 7000
# 通过sentinel获取redis从节点
slaver_list = sentinel.discover_slaves("mymaster")
print(slaver_list) # [('127.0.0.1', 7001), ('127.0.0.1', 7002)]
# 通过sentinel获取主节点然后设置值
master = sentinel.master_for('mymaster', socket_timeout=0.5, db=15)
master.set(f'foo{i}', f'bar{i}')
# 通过sentinel获取从节点然后获取值
slaver = sentinel.slave_for("mymaster", socket_timeout=0.5, db=15)
print(slaver.get(f"foo{i}"))
except Exception as err:
print(err)
finally:
time.sleep(1)
- redis-sentinel内部有三个定时任务完成了故障转移的功能
第一个定时任务
- 每10秒每个sentinel会对master节点和slaver节点执行info
- 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
第二个定时任务
第三个定时任务
每1秒每个sentinel对其它sentinel和redis执行ping的操作
- 主观下线和客观下线
sentinel monitor
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
- 主观下线,每个sentinel节点对redis节点失败的"偏见"
- 客观下线,所有sentinel节点对redis节点失败"达成共识",(超过quorum个同意)
客观下线只针对于master节点,主观下线针对于slaver节点
注意:sentinel节点要3个以上,而且最好是一个基数
-
领导者选举
原因:只有一个sentinel节点来完成故障转移
选举:通过sentinel,is-master-down-by-addr命令都希望称为领导者,
-
故障转移(sentinel领导者选举完成)
- 从slaver节点中选出一个"合适"的节点作为master节点
- 对上面的slaver节点执行slaveof no one命令让其成为master节点
- 向剩余的slaver节点发送命令,让他们成为新的master节点的slaver节点,复制规则和parallel-syncs有关
- 更新对原来master节点配置为slaver,并保持对其关注,当其恢复后命令他去复制新的master节点
-
选择合适的slaver节点
-
节点运维
- 主动主节点下线
sentinel failover <masterName>
- 从节点下线
临时下线还是永久下线,例如是否做一些清理工作,但是要考虑读写分离情况 - sentinel节点下线同上
节点上线
主节点:sentinel failover进行替换
从节点:slaveof即可,sentinel节点可以感知
sentinel节点:参考其它sentinel节点启动即可
- 高可用读写分离
- 从节点的作用:副本,高可用的基础
- 扩展:读能力
- redis-sentinel只会对master进行故障转移,对slave节点只会做主观下线
- 本章总结:
- redis-sentinel是redis的高可用实现方案
- 故障发现、故障自动转移、配置中心、客户端通知
- redis-sentinel从redis2.8版本开始使用,之前的版本生产不可用
- 尽可能在不同物理机上部署redis-sentinel所有节点
- redis-sentinel中的sentinel节点个数最好大于等于3,最好是奇数个
- redis-sentinel中的数据节点与普通的数据节点没有区别
- 客户端初始化时连接的是redis-sentinel节点的结合,不再是具体的redis节点,但sentinel只是配置中心,不是代理
- redis-sentinel通过三个定时任务实现了sentinel对于主节点、从节点、其余sentinel节点的监控
- redis-sentinel在对判断失败的节点分为:主观下线和客观下线的
- 看懂redis-sentinel故障转移日志对与redis-sentinel以及问题排查非常有用
- redis-sentinel实现高可用读写分离依赖:sentinel节点的消息通知,获取redis数据节点状态的变化
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)