相关链接

redis-GitHub-配置文件下载:https://github.com/redis/redis

redis 官网配置文件:https://redis.io/topics/config

redis哨兵原理 - 思维导图:https://kdocs.cn/l/spXDj5U6vDKF

实战演示的服务节点分布图 :https://kdocs.cn/l/sk1lDLmDbLqY

redis 主从复制搭建:https://blog.mailjob.net/posts/1586519326.html

redis广播:https://blog.mailjob.net/posts/2416487960.html

优秀文章: http://redis.cn/articles/20181020001.html

搭建步骤

# 让sentinel服务后台运行
daemonize yes 
Sentinel 的核心配置:
sentinel monitor mymaster 127.0.0.1 6379 2
监控的主节点的名字、IP 和端口,
最后一个2的意思是有几台 Sentinel 发现有问题,就会发生故障转移
例如 配置为2,代表至少有2个 Sentinel 节点认为主节点 不可达,那么这个不可达的判定才是客观的。
对于设置的越小,那么达到下线的条件越宽松,反之越严格。一般建议将其设置为 Sentinel 节点的一半加1
注意:最后的参数不得大于conut(sentinel)
sentinel down-after-millseconds mymaster 30000
这个是超时的时间(单位为毫秒)。打个比方,当你去 ping 一个机器的时候,多长时间后仍 ping 不
通,那么就认为它是有问题
sentinel parallel-syncs mymaster 1
当 Sentinel 节点集合对主节点故障判定达成一致时, Sentinel 领导者节点会做故障转移操作,选出新
的主节点,原来的从节点会向新的主节点发起复制操 作, parallel-syncs 就是用来限制在一次故障转移
之后,每次向新的主节点发起复制操作的从节点个数,指出 Sentinel 属于并发还是串行。1代表每次只
能 复制一个,可以减轻 Master 的压力

sentinel auth-pass master-name password
如果 Sentinel 监控的主节点配置了密码,sentinel auth-pass 配置通过添加主节点的密码,防止
Sentinel 节点对主节点无法监控。
sentinel failover-timeout mymaster 180000
表示故障转移的时间(单位:毫秒)

Sentinel命令

sentinel是一个特殊的redis节点,它有自己专属的api;

1. sentinel masters 显示被监控的所有master以及它们的状态.
2. sentinel master 显示指定master的信息和状态;
3. sentinel slaves 显示指定master的所有slave以及它们的状态;
4. sentinel get-master-addr-by-name 返回指定master的ip和端口, 如果正在进行failover或者
   failover已经完成,将会显示被提升 为master的slave的ip和端口。
5. sentinel failover 强制sentinel执行failover,并且不需要得到其他sentinel的同意。 但是failover
   后会将最新的配置发送给其他 sentinel。

哨兵原理

为什么要做哨兵?

Redis 主从复制有一个缺点,当主机 Master 宕机以后,我们需要人工解决切换,如使用 slaveof no one 。

实际上主从复制 并没有实现高可用。

高可用侧重备份机器, 利用集群中系统的冗余,当系统中某台机器发生损坏的时候,其他后备的机器
可以迅速的接替它来启动服务

实现逻辑

Redis Sentinel 一个分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节
点会对数据节点和其余 Sentinel 节点进行监 控,当它发现节点不可达时,会对节点做下线标识。
如果被标识的是主节点,它还会和其他 Sentinel 节点进行“协商”,当大多数 Sentinel 节点都认为主节点
不可达时,它们会选举出一个 Sentinel 节点来 完成自动故障转移的工作,同时会将这个变化实时通知
给 Redis 应用方。

可查看上文中【实战演示的服务节点分布图 】转移图

Redis Sentinel 具有以下几个功能:

监控:Sentinel 节点会定期检测 Redis 数据节点、其余 Sentinel 节点是否可达
通知:Sentinel 节点会将故障转移的结果通知给应用方 主节点故障转移: 实现从节点晋升为主节
点并维护后续正确的主从关系
配置提供者: 在 Redis Sentinel 结构中,客户端在初始化的时候连接的是 Sentinel 节点集合 ,从
中获取主节点信息。

Redis Sentinel 包含多个节点好处:

对于节点的故障判断是由多个 Sentinel 节点共同完成,这样可以有效地防止误判。
Sentinel 节点集合是由若干个 Sentinel 节点组成的,这样即使个别 Sentinel 节点不可用,整个
Sentinel 节点集合依然是健壮的。

哨兵监控原理

请查阅上文中的【redis发布订阅】

img

三个定时任务
首先要讲的是内部 Sentinel 会执行以下三个定时任务。
每10秒每个 Sentinel 对 Master 和 Slave 执行一次 Info Replication 。
每2秒每个 Sentinel 通过 Master 节点的 channel 交换信息(pub/sub)。
每1秒每个 Sentinel 对其他 Sentinel 和 Redis 执行 ping 。
第一个定时任务,指的是 Redis Sentinel 可以对 Redis 节点做失败判断和故障转移,在 Redis 内部有三
个定时任务作为基础,来 Info Replication 发现 Slave 节点,这个命令可以确定主从关系。
第两个定时任务,类似于发布订阅, Sentinel 会对主从关系进行判定,通过 sentinel:hello 频道交互。
了解主从关系可以帮助更好的自动化操作 Redis 。然后 Sentinel 会告知系统消息给其它 Sentinel 节
点,最终达到共识,同时 Sentinel 节点能够互相感知到对方。

主观下线

​ 首先解析一下什么叫主观下线,所谓主观下线,就是单个sentinel认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因)。

​ sentinel会以每秒一次的频率向所有与其建立了命令连接的实例(master,从服务,其他sentinel)发ping命令,通过判断ping回复是有效回复,还是无效回复来判断实例时候在线(对该sentinel来说是“主观在线”)。

客观下线

​ 当sentinel监视的某个服务主观下线后,sentinel会询问其它监视该服务的sentinel,看它们是否也认为该服务主观下线,接收到足够数量(这个值可以配置)的sentinel判断为主观下线,既任务该服务客观下线,并对其做故障转移操作。

​ sentinel通过发送 SENTINEL is-master-down-by-addr ip port current_epoch runid,(ip:主观下线的服务id,port:主观下线的服务端口,current_epoch:sentinel的纪元,runid:*表示检测服务下线状态,如果是sentinel 运行id,表示用来选举领头sentinel)来询问其它sentinel是否同意服务下线。

选举领头sentinel

​ 一个redis服务被判断为客观下线时,多个监视该服务的sentinel协商,选举一个领头sentinel,对该redis服务进行古战转移操作。选举领头sentinel遵循以下规则:

​ 所有的sentinel都有公平被选举成领头的资格

​ 所有的sentinel都有且只有一次将某个sentinel选举成领头的机会(在一轮选举中),一旦选举某个sentinel为领头,不能更改

​ sentinel设置领头sentinel是先到先得,一旦当前sentinel设置了领头sentinel,以后要求设置sentinel为领头请求都会被拒绝

​ 每个发现服务客观下线的sentinel,都会要求其他sentinel将自己设置成领头

​ 当一个sentinel(源sentinel)向另一个sentinel(目sentinel)发送is-master-down-by-addr ip port current_epoch runid命令的时候,runid参数不是*,而是sentinel运行id,就表示源sentinel要求目标sentinel选举其为领头

​ 源sentinel会检查目标sentinel对其要求设置成领头的回复,如果回复的leader_runid和leader_epoch为源sentinel,表示目标sentinel同意将源sentinel设置成领头

​ 如果某个sentinel被半数以上的sentinel设置成领头,那么该sentinel既为领头

​ 如果在限定时间内,没有选举出领头sentinel,暂定一段时间,再选举

各个哨兵选举master依据点:

  • 选择健康状态从节点(排除主观下线、断线),排除5秒钟没有心跳的、排除主节点失联超过10*down-after-millisecends。
  • 选择最高优先级中复制偏移量最大的从机。
  • 如果还没有选出来,则按照ID排序,获取 run id 最小的从节点。

为什么要选偏移量最大的:偏移量大,代表复制的数据更全

为什么要选 run id 最小的:runid就是节点的运行id,最小的就是最先启动的,数据可能更全

如何进行故障转移

故障转移分为三个主要步骤

a. 从下线的主服务的所有从服务里面挑选一个从服务,将其转成主服务
sentinel状态数据结构中保存了主服务的所有从服务信息,领头sentinel按照如下的规则从从服务列表中挑选出新的主服务

删除列表中处于下线状态的从服务

删除最近5秒没有回复过领头sentinel info信息的从服务

删除与已下线的主服务断开连接时间超过 down-after-milliseconds*10毫秒的从服务,这样就能保留从的数据比较新(没有过早的与主断开连接)

领头sentinel从剩下的从列表中选择优先级高的,如果优先级一样,选择偏移量最大的(偏移量大说明复制的数据比较新),如果偏移量一样,选择运行id最小的从服务
b. 已下线主服务的所有从服务改为复制新的主服务
挑选出新的主服务之后,领头sentinel 向原主服务的从服务发送 slaveof 新主服务 的命令,复制新master
c. 将已下线的主服务设置成新的主服务的从服务,当其回复正常时,复制新的主服务,变成新的主服务的从服务

常见问题

客户端如何调用redis

Master可能会因为某些情况宕机了,如果在客户端是固定一个地址去访问,肯定是不合理的,所以客户
端请求是请求哨兵,从哨兵获取主机地址的信息,或者是 从机的信息。可以实现一个例子
1、随机选择一个哨兵连接,获取主机、从机信息
2、模拟客户端定时访问,实现简单轮训效果,轮训从节点
3、连接失败重试访问

思路
sentinel节点集合具备了监控、通知、自动故障转移、配置提供着若干功能,也就是说实际上最了解主
节点的就是sentinel节点集合,而各个主节点可以通过 进行标识的,所以,无论是那种编程语言的客户
端,如果需要正确地连接redis sentinel
1. 遍历sentinel节点集合获取一个可用的sentinel节点,sentinel会共享数据,所以从任意一个
sentinel节点获取主节点信息都可以
2. 通过 sentinel get-master-addr-by-name master-name 这个api来获取对应主节点的相关信息
3. 验证当前获取的“主节点”是真正的主节点,这样做的目的是未来放置故障转移期间主节点的变化
4. 保持和sentinel节点集合的“联系”,时刻获取关于主节点的相关“信息”

搭建报错问题

1、异步复制导致数据丢失

因为master->slave的复制是异步,所以可能有部分还没来得及复制到slave就宕机了,此时这些部分数
据就丢失了。

解决方案: 在异步复制的过程当中,通过 min-slaves-max-lag 这个配置,就可以确保的说,一旦 slave 复制数据
和 ack 延迟时间太长,就认为可能 master 宕机 后损失的数据太多了,那么就拒绝写请求,这样就可以
把master宕机时由于部分数据未同步到 slave 导致的数据丢失降低到可控范围内

2、集群脑裂导致数据丢失

脑裂,也就是说,某个master所在机器突然脱离了正常的网络,跟其它slave机器不能连接,但是实际
上master还运行着。

解决方案: 原redis主节点活了以后,会自动变成从节点。不用我们自己处理

哨兵启动报错

root@85cbceb66bad:/data# redis-server /etc/sentinel.conf --sentinel
*** FATAL CONFIG FILE ERROR (Redis 6.0.10) ***
Reading the configuration file, at line 336
>>> 'SENTINEL resolve-hostnames no'
Unrecognized sentinel configuration statement.

这个是由于 docker 按照的 redis 版本和 引入数据卷使用的哨兵配置文件,版本不一致导致的