vlambda博客
学习文章列表

redis主从架构及哨兵模式

redis主从原理分析

主从出现原因
  • 高并发
    • 官方数据表示redis的读数据在11万/s左右,写速度在8万/s左右
    • redis尽量少写多读,符合缓存的适用要求
    • 通过主从架构来进行读写分离
  • HA
    • 具备有一个以上的从库就会对节点进行备份

主从同步过程中一定要开启持久化

  • 如果master出现宕机内存丢失,从库也会删除数据
  • 如果master进行功能性重启,内存数据就是,也会同步给slave节点

主从复制原理

  • 当slave第一次连接时,会触发全量同步,如果已经连接过,只会同步新增数据
  • 全量备份分为落盘和不落盘两种形式,默认是落盘
# 不落盘复制配置 yes不落盘,no落盘repl-diskless-sync no# 等待其他slave连接的一个时间周期,单位是秒repl-diskless-sync-delay 5
  • 支持断点续传
  • 如果从库过多会导致占用带宽过大,所以从库不易过多

主从结构除了一对多,还可以是树形结构,只不过树形结构用的比较少

主从设置

# 可以通过命令看一下主从信息,v5.x版本前从是用slave表示,之后换成replication# master和slave节点都可以查看info replication# 修改slave的redis.confreplicaof 192.168.1.100 6379 #master的ip,master的端口# 在slave配置上添加masterauth icoding #主机的访问密码# yes 主从复制中,从服务器可以响应客户端请求# no 主从复制中,从服务器将阻塞所有请求,有客户端请求时返回“SYNC with master in progress”;# 默认开启yes,在slave上配置replica-serve-stale-data yes# slave节点只允许read 默认就是 yes# 这个配置只对slave节点才生效,对master节点没作用# 默认开启并配置为yes,在slave上配置replica-read-only yes # slave根据指定的时间间隔向master发送ping请求# 时间间隔可以通过 repl-ping-replica-period 来设置,默认10秒# 默认没有开启,在slave的配置上打开repl-ping-replica-period 10# 复制连接超时时间。# master和slave都有超时时间的设置。# master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。# slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。# 需要注意的是repl-timeout需要设置一个比repl-ping-slave-period更大的值,不然会经常检测到超时。# 默认没有开启,在slave的配置上打开repl-timeout 60# 是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。# 默认是no,即使用tcp nodelay,允许小包的发送。对于延时敏感型,同时数据传输量比较小的应用,开启TCP_NODELAY选项无疑是一个正确的选择# 如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。# 但是这也可能带来数据的延迟。# 默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。# 默认开启并配置为no,在master上添加repl-disable-tcp-nodelay no# 复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。# 这样在slave离线的时候,不需要完全复制master的数据,如果可以执行部分同步,只需要把缓冲区的部分数据复制给slave,就能恢复正常复制状态。# 缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有slave连接的时候才分配内存。# 没有slave的一段时间,内存会被释放出来,默认1m。# 默认没有开启,在master上配置repl-backlog-size 5mb# master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。# 单位为秒。# 默认没有开启,在master上配置repl-backlog-ttl 3600# 当master不可用,Sentinel会根据slave的优先级选举一个master。# 最低的优先级的slave,当选master。# 而配置成0,永远不会被选举。# 注意:要实现Sentinel自动选举,至少需要2台slave。# 默认开启,在slave上配置replica-priority 100# redis提供了可以让master停止写入的方式,如果配置了min-slaves-to-write,健康的slave的个数小于N,mater就禁止写入。# master最少得有多少个健康的slave存活才能执行写命令。# 这个配置虽然不能保证N个slave都一定能接收到master的写操作,但是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。# 设置为0是关闭该功能,默认也是0。# 默认没有开启,在master上配置min-replicas-to-write 2# 延迟小于min-replicas-max-lag秒的slave才认为是健康的slave。# 默认没有开启,在master上配置min-replicas-max-lag 10

哨兵机制及实现原理

redis的提供的sentinel哨兵机制,是为了应对master节点挂掉之后,保证redis的可用性及实现继续写的操作,哨兵可以自动将slave升级成master节点。

什么是哨兵?

redis的sentinel机制是用于管理多个redis服务器的,sentinel会执行以下四个任务

  • 服务监控:负责监控redis   master和slave进程是否正常工作
  • 消息通知:master如果挂掉了,哨兵可以根据配置的脚本来调用发送通知
  • 故障转移:master几点挂掉,sentinel会从slave中选举一个节点为master,会让剩下的slave节点 follow到新的master节点上,并从新master节点复制数据
  • 配置中心:如果故障发生转移,sentinel可以通知客户端,新的master地址端口
哨兵配置
# redis的安装根目录下,有个sentinel.conf# 部署三个哨兵节点,同时监控一组redis服务(只有一个节点其实也可以,但风险)# bind 127.0.0.1 192.168.1.1# 测试的时候放开访问保护protected-mode noport 26379 #默认是26379daemonize yespidfile /var/run/redis-sentinel-26379.pid #pid 集群要区分开logfile /usr/local/redis-6379/sentinel/redis-sentinel.log #日志,非常重要dir /usr/local/redis-6379/sentinel #工作空间# sentinel监控的核心配置# 最后一个2,quorum,>=2个哨兵主观认为master下线了,master才会被客观下线,才会选一个slave成为mastersentinel monitor icoding-master 127.0.0.1 6379 2# master访问密码sentinel auth-pass icoding-master icoding# sentinel主观认为master挂几秒以上才会触发切换sentinel down-after-milliseconds icoding-master 3000# 所有slave同步新master的并行同步数量,如果是1就一个一个同步,在同步过程中slave节点是阻塞的,同步完了才会放开sentinel parallel-syncs icoding-master 1# 同一个master节点failover之间的时间间隔sentinel failover-timeout icoding-master 180000

启动哨兵

redis-sentinel sentinel.conf# 如果要搭建集群,只需要将刚刚配置的sentinel.conf复制到其他节点即可

哨兵部署的约定

  • 哨兵集群至少3个节点
  • 最好三个节点在不同的物理机器上
  • 一组哨兵最好只监控一组主从
查看哨兵信息
redis-cli -p 26379 #通过哨兵的端口进入sentinel master cqp-mastersentinel slaves cqp-mastersentinel sentinels cqp-master #查看哨兵信息
主观宕机和客观宕机
  • S_DOWN(subjectively down)主观宕机

    • 一个哨兵根据配置的主观宕机秒数,认为一个master宕机了就是主观宕机
    • sentinel down-after-milliseconds icoding-master 3000 就是这个配置
    • 哨兵ping主机,然后返回超过上面设置的时间就会认为是主观宕机
  • O_DOWN(objectively down)客观宕机

    • 如果quorum数量的哨兵认为一个master宕机了,就是客观宕机
哨兵集群是如何自动发现

创建哨兵集群的时候并没有手动设置之间的关联

通过pub/sub机制来实现的,每个哨兵都会pub一个__sentinel__:hello并通过sub来获取和感知有多少个同组redis监控的哨兵并且信息里会携带host ip runid,并让其他哨兵感知到
选举算法

会考虑的slave选举的信息

  • 和master断开的时长
  • slave的优先级:replica-priority 100
  • 复制的offset位移程度
  • run_id

如果slave和master连接断开超过:down-after-milliseconds icoding-master这个配置的10倍以上绝对不考虑

slave的选举排序顺序

1、按照slave优先级进行排序,replica priority越低,优先级越高

2、如果replica priority级别相同,看offset越靠后(复制的内容多少),优先级越高

3、如果上面两个条件都一样,这个时候看run_id ,run_id字符排序越靠前越优先

先选一个执行主从的sentinel,这个sentinel在根据主从选举算法进行选举

quorum和majority

每次哨兵要做主从切换,首先需要quorum数据的哨兵认为O_DOWN,然后选举一个哨兵来做主从切换,这个哨兵要得到majority数量哨兵的授权,才能正式切换

如果quorum<majority,如果5个哨兵,maj就是3个,qu就是2个

如果quorum>=majority,必须quorum数量的哨兵都授权

configuration epoch

监控的版本号,这个时候所有的哨兵都会记录一套当前的主从关系,这个关系的变更,切换版本号

一个执行哨兵完成了主从切换后,就会通过pub/sub机制来传播给其他哨兵

哨兵故障转移实现

关闭master节点服务

实现方式:依赖于config命令,我们会改成imconfig

# 可以通过这个命令来修改成无redis修改后的config命令# SENTINEL rename-command mymaster CONFIG IMCONFIG

实现切换机制

1. 通过config命令修改redis.conf的主从关系 修改自己的sentinel.conf的主机监控命令2. 在sentinel.conf配置的最下端写入当前主从的版本,供所有哨兵进行使用sentinel leader-epoch icoding-master 1sentinel known-replica icoding-master 127.0.0.1 7002sentinel known-replica icoding-master 127.0.0.1 6379sentinel known-sentinel icoding-master 127.0.0.1 26379 ce3608694909e996b280e8672750b2bd5522945fsentinel known-sentinel icoding-master 127.0.0.1 26382 a2f203e003ce891a08580104dc2b49a4f6ae187esentinel current-epoch 1
哨兵故障通知机制
# sentinel notification-script <master-name> <script-path># 当我们master出现sdown和odown都会触发sentinel notification-script icoding-master /usr/local/redis/nofity.sh

# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh# 会带有一些参数:主从切换新旧地址的参数# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>sentinel client-reconfig-script icoding-master /usr/local/redis/configer.sh
哨兵转移中问题
  • 异步复制的时候,master的数据还没有复制给slave,这个时候哨兵切换slave成为master后就会丢失这些数据(新master会把他的数据同步到其他slave:清空其他slave进行同步)

  • 脑裂:哨兵的网络和master断开了,但我们master还在运行,这个时候客户端写入旧master的时候就会丢失

    old-master<-->client 是连接的,这个时候old-master就没有slave,可以通过以下两个配置来缓解

    new-master---slave1/slave2

    • min-replicas-to-write 2
    • min-replicas-max-lag 10
程序如何确保访问有效

需要我们在springboot配置中连接哨兵port

spring: redis: host: 127.0.0.1 password: icoding sentinel: master: icoding-master nodes: 39.99.199.5:26379,39.99.199.5:26381,39.99.199.5:26382