一站式学习Redis, 从入门到高可用分布式实践-07-08复制与哨兵sentinel保证redis的高可用

redis复制的原理与优化

  • 复制是实现高可用的基石,但复制同样是运维的痛点,我们来分析复制的原理与运维过程中可能遇到的问题
  1. 什么是主从复制
  • 单机有什么问题呢:机器故障、容量瓶颈、QPS瓶颈
    机器故障是高可用问题,容量瓶颈和QPS瓶颈是分布式问题
  • 主从复制的作用:数据副本、读写分离
  • 小结:一个master可以有多个slaver,一个slaver只能有一个master,数据流向是单向的,只能从master流向slaver
  1. 主从复制的配置
  • 两种实现方式: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的所有数据拷贝过来,保持数据一致性
  1. 全量复制和部分复制
  • 全量复制
  • 全量复制的开销
    bgsave时间、rdb文件网络传输时间、从节点清空数据、从节点加载rdb的时间,可能的AOF重写时间
  • 部分复制
  1. 故障处理
  • 主从结构故障转移:slave故障、master故障
  1. 开发运维常见问题
  • 读写分离会产生的问题
    读写分离读流量分摊到从节点,可能遇到问题,数据复制延迟,读到过期数据(redis.3.2中已经解决了这个问题),从节点故障

  • 主从配置不一致
    maxmemory不一致:丢失数据,
    数据结构优化参数:hash-max-ziplist-entried:内存不一致

  • 规避全量复制
    第一次全量复制不可避免,小主节点,低峰
    节点运行run_id不匹配,主节点重启,run_id变化, 故障转移,例如哨兵或集群
    复制积压缓冲区不足,网络中断,部分复制无法满足,增大复制缓冲区配置rel_backlog_size,网络"增强"

  • 规避复制风暴
    单主节点复制风暴
    主节点重启,多个从节点会产生复制,解决:更换复制拓扑
    单机器复制风暴,机器宕机后,会产生大量全量复制

redis sentinel

  1. 主从复制问题
  • 手动故障转移
  • 写能力和存储能力受限
  1. redis sentinel架构

  2. redis sentinel故障转移

  • 多个sentinel发现并确认redis master有问题
  • 从多个sentinel中选举出一个作为leader
  • 从多个redis slaver中选出一个作为redis master
  • 通知其余salver成为新的master的slaver
  • 通知客户端主从变化
  • 等待老的master复活成为新的master的slaver

注意:一套redis sentinel可以监控多套redis master-slaver

  1. redis-sentinel的安装与配置
  • 配置开启主从节点
  • 配置开启sentinel监控主节点,(sentinel是特殊的redis)
  • 实际应该多台机器
  • 详细配置节点
  1. sentinel主要配置

  2. 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
  1. 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

  1. 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)
  1. redis-sentinel内部有三个定时任务完成了故障转移的功能
    第一个定时任务
  • 每10秒每个sentinel会对master节点和slaver节点执行info
  • 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
    第二个定时任务

    第三个定时任务
    每1秒每个sentinel对其它sentinel和redis执行ping的操作
  1. 主观下线和客观下线

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个以上,而且最好是一个基数

  1. 领导者选举
    原因:只有一个sentinel节点来完成故障转移
    选举:通过sentinel,is-master-down-by-addr命令都希望称为领导者,

  2. 故障转移(sentinel领导者选举完成)

  • 从slaver节点中选出一个"合适"的节点作为master节点
  • 对上面的slaver节点执行slaveof no one命令让其成为master节点
  • 向剩余的slaver节点发送命令,让他们成为新的master节点的slaver节点,复制规则和parallel-syncs有关
  • 更新对原来master节点配置为slaver,并保持对其关注,当其恢复后命令他去复制新的master节点
  1. 选择合适的slaver节点

  2. 节点运维

  • 主动主节点下线
    sentinel failover <masterName>
  • 从节点下线
    临时下线还是永久下线,例如是否做一些清理工作,但是要考虑读写分离情况
  • sentinel节点下线同上

节点上线
主节点:sentinel failover进行替换
从节点:slaveof即可,sentinel节点可以感知
sentinel节点:参考其它sentinel节点启动即可

  1. 高可用读写分离
  • 从节点的作用:副本,高可用的基础
  • 扩展:读能力
  • redis-sentinel只会对master进行故障转移,对slave节点只会做主观下线
  1. 本章总结:
  • 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数据节点状态的变化
posted @ 2022-04-16 18:47  专职  阅读(60)  评论(0编辑  收藏  举报