Redis 集群之主备架构(哨兵机制)原理及安装部署

前言

之前的文章介绍(Redis 集群之主从架构原理及安装部署)主从架构会有这样一个问题,如果 master node 因为某些原因宕机了,那么整个 redis 集群就无法进行写操作了。需要运维人员手动进行切换,然后所有程序需要修改配置然后重新上线,想想就很恐怖,开发和运维要时刻待命,想睡个安心觉都很难。

所以说的话,我们需要发一个高可用的架构,当集群的 master node 宕机后,能够自动检测到,并自动进行切换。Redis 提供了一种方案 —— Redis Sentinel(哨兵)。

原理

哨兵本身也是一个分布式高可用架构,与 Redis 集群相互协作配合。哨兵集群类似于 Zookeeper 集群,是一个高可用的架构,即使一个节点挂掉了,集群也可以正常工作。其架构如下图:

哨兵集群会不断监控主从节点的健康状态,如果有主节点出现故障后,后自动选择一个最优的从节点切换成主节点。客户端连接集群时,会首先连接 Sentinel 集群,通过 Sentinel 来查询主节点的地址,然后再与主节点进行数据交互。当主节点出现故障后,客户端会重新向 Sentinel 集群要主节点地址, Sentinel 会将最新的主节点地址告诉客户端。如果应用无须重启即可以完成节点的自动切换。等原先的主节点恢复后,会变成从节点,然后从新的主节点那里建立复制关系。

当发生了 master 切换后,磁盘中的 redis 配置文件也会进行相应的修改。

sdown 和 odown 转换机制

sdown 和 odown 是二种失败状态。 sdown 表示主观宕机,就是指一个哨兵自己觉得 master 宕机了,那么就是主观宕机。odown 表示客观宕机,如果 quorum 数据的哨兵认为 master 宕机了,那就是客观宕机。后面搭建集群中的配置 sentinel monitor mymaster worker-01 6379 2,其中的 2 就是 quorum 数量。也就是说在这个集群中,有二个哨兵认为 master 宕机了,就表示是客户宕机。这时候会进行主备切换。

哨兵集群的自动发现机制

如果我们配置过 sentinel.conf 文件的话,发现我们不需要 配置 slave 的地址,也不需要配置其它的哨兵节点的地址。那么哨兵间是如何通信的呢?是如果去发现其它的哨兵节点的呢。

哨兵之前的相互发现,是通过 redis 的 pub / sub 系统实现的。每个哨兵都会往sentinel:hello这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在。

同时,哨兵会通过 轮询 master 来得到 slave 的地址,从而监控 slave 节点。

每个 sentinel 也维护了最新的 master 配置,如果某个 sentinel 发现自己的配置低于接收到的配置版本,会用新的配置更新自己的 master 信息。

slave -> master 的选举算法

当 master 因某种原因宕机了,需要把某一个 slave 节点切换成 master 节点,那么 redis 是如果从多个 slave 节点中选择其中一个 slave 节点作为 master 节点的呢?

sentinel 选举一个 slave 作为 master 节点时,会考虑 slave 的以下信息:

  • 跟 master 断开的时长
  • slave 优先级
  • 复制 offset
  • run id

如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master,即 (down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state。

接下会对 slave 进行排序

  • 按照 slave 的优先级进行排序,slave priority 越小,优先级越高。
  • 如果 slave priority 相同,看 replica offset,哪个 slave 复制了越多的数据,offset 越靠后,优先级越高。
  • 如果上面二个条件相同,那么选择一个 run id 比较小的那个 slave。

quorum 和 majority

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

如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换.

但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换.

数据丢失

异步复制导致的数据丢失

由于 master 到 slave 的数据是异步复制的,如果在复制数据的过程中,master 节点宕机,此时这部分数据就丢失了。

脑裂导致的数据丢失

脑裂是由于某些原因,导致 master 脱离了正常的网络环境,跟其它 slave 机器不能正常连接,但实际上 master 还活着。此时,哨兵可能会认为 master 已经宕机,会选举出新的 master 节点,然而客户端还是连接到旧的 master 节点上,还没有切换到新的 master 节点上,还继续往旧的 master 的节点写入数据,这部分数据也会丢失。因为旧 master 节点恢复后,会被当作一个新的 slave 挂载到 master 上去,其原先的数据会被清空,重新从新的 master 上进行数据复制。

安装部署 Sentinel 集群

首先需要部署一套主从的 redis 集群,可以参考 Redis 集群之主从架构原理及安装部署

这里已经搭好一主二从的 redis 集群,其中 IP 关系为:


192.168.56.101 worker-01        worker-01.joyxj.com
192.168.56.102 worker-02        worker-02.joyxj.com
192.168.56.103 worker-03        worker-03.joyxj.com

其中 worker-01 是 master 节点,worker-02 和 worker-03 是 slave 节点。

下面开始配置 sentinel 的配置

创建数据目录和配置文件目录

# 创建配置文件目录
mkdir /etc/sentinel
# 创建数据目录, sentinel 的相关数据会在这里面
mkdir -p /var/sentinel/26379
# 拷贝配置文件
cp /opt/tools/redis-5.0.5/sentinel.conf /etc/sentinel/

配置

主要是配置以下几下:

# 端口
port 26379
# 后台运行
daemonize yes
# pid
pidfile /var/run/redis-sentinel.pid
# 数据目录
dir /var/sentinal/26379

# 给需要监控的 master 起一个名字,这里起的名字是 mymaster, 且至少需要 2 个哨兵同意才进行切换
sentinel monitor mymaster worker-01 6379 2
# 超过 30s 就认为一个 redis 实例故障
sentinel down-after-milliseconds mymaster 30000
# 执行故障转移的timeout超时时长
sentinel failover-timeout mymaster 180000
# 1 表示一个接一个把slave 挂载到新的 master 上面
sentinel parallel-syncs mymaster 1

上面的配置在三台服务器上都需要配置。

启动

三台服务器执行脚本 redis-sentinel /ect/sentinel/sentinel.conf 即可启动哨兵集群。

可以通过以下的一些命令查询 sentinel 的信息。

# 连接到某个哨兵节点,worker-01 为 IP , 26379 为端口
redis-cli -h worker-01 -p 26379
# 查看集群的 master 节点信息
>>> sentinel master mymaster
# 查看集群的 slave 节点信息
>>> sentinel slaves mymaster
# 查看 sentinel 节点信息
>>> sentinel sentinels mymaster

   转载规则


《Redis 集群之主备架构(哨兵机制)原理及安装部署》 孤独如梦 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Redis 集群之 Redis Cluster 原理及安装部署 Redis 集群之 Redis Cluster 原理及安装部署
主从架构和哨兵架构的缺点我们知道 Redis 主从架构和哨兵架构可以通过扩容从节点增加 QPS,但是如果需要缓存的数据有上百个 G 的话,在主从架构和哨兵架构下因为是读写分离,主节点写入数据,从节点从主节点复制数据,此时单机是无法存储这个么
2019-07-30
下一篇 
【dubbo系列】 12-Dubbo 服务导出 【dubbo系列】 12-Dubbo 服务导出
前言Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 收到事件后,会立即执行导出逻辑。整个逻辑大概可以分成三个部分:每一部分是前置工作,主要用于检查参数和组装URL。第二部分是导出服务,包含导出到本地(JVM),和导
2019-07-17
  目录