深入学习Redis高可用架构:哨兵原理及实践

作者:微信小助手

发布时间:2018-09-18T00:26:20

在上篇文章《深入学习 Redis 高可用的基石:主从复制》中曾提到,Redis 主从复制的作用有数据热备、负载均衡、故障恢复等;但主从复制存在的一个问题是故障恢复无法自动化。


本文将要介绍的哨兵,它基于 Redis 主从复制,主要作用便是解决主节点故障恢复的自动化问题,进一步提高系统的高可用性。


文章将首先介绍哨兵的作用和架构;然后讲述哨兵系统的部署方法,以及通过客户端访问哨兵系统的方法;然后简要说明哨兵实现的基本原理;最后给出关于哨兵实践的一些建议。(注:文章内容基于 Redis 3.0 版本


哨兵的作用和架构


哨兵的作用


在介绍哨兵之前,首先从宏观角度回顾一下 Redis 实现高可用相关的技术。


它们包括:持久化、复制、哨兵和集群,其主要作用和解决的问题是:

  • 持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。

  • 复制:复制是高可用 Redis 的基础,哨兵和集群都是在复制基础上实现高可用的。

    复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。

  • 哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。

  • 集群:通过集群,Redis 解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。


下面说回哨兵,Redis Sentinel,即 Redis 哨兵,在 Redis 2.8 版本开始引入。哨兵的核心功能是主节点的自动故障转移。


下面是 Redis 官方文档对于哨兵功能的描述:

  • 监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。

  • 自动故障转移(Automatic failover):当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。

  • 配置提供者(Configurationprovider):客户端在初始化时,通过连接哨兵来获得当前 Redis 服务的主节点地址。

  • 通知(Notification):哨兵可以将故障转移的结果发送给客户端。


其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则需要在与客户端的交互中才能体现。


这里对“客户端”一词在本文的用法做一个说明:在前面的文章中,只要通过 API 访问 Redis 服务器,都会称作客户端,包括 redis-cli、Java 客户端 Jedis 等。


为了便于区分说明,本文中的客户端并不包括 redis-cli,而是比 redis-cli 更加复杂。


redis-cli 使用的是 Redis 提供的底层接口,而客户端则对这些接口、功能进行了封装,以便充分利用哨兵的配置提供者和通知功能。


哨兵的架构


典型的哨兵架构图如下所示:

它由两部分组成,哨兵节点和数据节点:

  • 哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 Redis 节点,不存储数据。

  • 数据节点:主节点和从节点都是数据节点。


哨兵系统的部署方法


这一部分将部署一个简单的哨兵系统,包含 1 个主节点、2 个从节点和 3 个哨兵节点。


方便起见:所有这些节点都部署在一台机器上(局域网 IP:192.168.92.128),使用端口号区分;节点的配置尽可能简化。


部署主从节点


哨兵系统中的主从节点,与普通的主从节点配置是一样的,并不需要做任何额外配置。


下面分别是主节点(port=6379)和 2 个从节点(port=6380/6381)的配置文件,配置都比较简单,不再详述。

#redis-6379.conf
port 6379
daemonize yes
logfile "6379.log"
dbfilename "dump-6379.rdb"

#redis-6380.conf
port 6380
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
slaveof 192.168.92.128 6379

#redis-6381.conf
port 6381
daemonize yes
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 192.168.92.128 6379


配置完成后,依次启动主节点和从节点:

redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf


节点启动后,连接主节点查看主从状态是否正常,如下图所示:

部署哨兵节点


哨兵节点本质上是特殊的 Redis 节点。3 个哨兵节点的配置几乎是完全一样的,主要区别在于端口号的不同(26379/26380/26381)。


下面以 26379 节点为例,介绍节点的配置和启动方式,配置部分尽量简化,更多配置会在后面介绍。

#sentinel-26379.conf
port 26379
daemonize yes
logfile "26379.log"
sentinel monitor mymaster 192.168.92.128 6379 2


其中,sentinel monitor mymaster 192.168.92.128 6379 2 配置的含义是:该哨兵节点监控 192.168.92.128:6379 这个主节点。


该主节点的名称是 mymaster,最后的 2 的含义与主节点的故障判定有关:至少需要 2 个哨兵节点同意,才能判定主节点故障并进行故障转移。


哨兵节点的启动有两种方式,二者作用是完全相同的:

redis-sentinel sentinel-26379.conf
redis-server sentinel-26379.conf --sentinel


按照上述方式配置和启动之后,整个哨兵系统就启动完毕了,可以通过 redis-cli 连接哨兵节点进行验证。


如下图所示:可以看出 26379 哨兵节点已经在监控 mymaster 主节点(即192.168.92.128:6379),并发现了其 2 个从节点和另外 2 个哨兵节点。

此时如果查看哨兵节点的配置文件,会发现一些变化,以 26379 为例:

其中,dir 只是显式声明了数据和日志所在的目录(在哨兵语境下只有日志);known-slave 和 known-sentinel 显示哨兵已经发现了从节点和其他哨兵。


带有 epoch 的参数与配置纪元有关(配置纪元是一个从 0 开始的计数器,每进行一次领导者哨兵选举,都会 +1;领导者哨兵选举是故障转移阶段的一个操作,在后文原理部分会介绍)。