从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)

r660926
发布于 2022-6-30 16:54
浏览
0收藏

四、搭建哨兵集群


4.1 哨兵集群拓扑图


三台机器上分别部署三个哨兵服务。部署拓扑图如下所示:从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区4.2 哨兵服务是怎么启动的


其实哨兵服务也是用 Redis 容器启动的,只是用的不同命令的启动的。

 

我们可以在 redis 容器中执行如下命令启动哨兵服务。

redis-sentinel /usr/local/etc/redis/sentinel.conf

因为我们是通过 docker 启动的,所以在启动 docker 容器时,带上这个命令参数就可以启动哨兵服务了,就不用到容器里面执行这个命令了。

 

4.3 哨兵配置


首先创建两个映射文件:sentinel.conf 和 sentinel-26379.log,第一个是配置哨兵参数的,第二个文件是哨兵的日志文件,这两个文件都会在启动 redis 容器时,映射到容器中,方便我们修改配置以及查看日志。

 

sentinel.conf 这个配置文件可以从官方的 redis 安装包中拷贝,也可以自己创建一个配置文件,修改几个参数就可以了。可以直接拷贝我的配置。

mkdir /home/redis
vim /home/redis/sentinel.conf

配置内容如下:

# sentile 端口
port 26379
# 是否在后台启动,默认为 no,注意这里需要设置为 no,否则容器启动不起来。
daemonize no
pidfile /var/run/redis-sentinel.pid
# 日志文件
logfile /var/log/sentinel-26379.log
# 工作目录
dir /tmp
# 监控 redis 的 IP 和端口,这里监控的 redis 的主节点
sentinel monitor mymaster 10.2.1.61 6379 2
# down-after-milliseconds:每个 Sentinel节点都要通过定期发送 ping 命令来判断Redis数据节点和其 余Sentinel节点是否可达,如果超过了down-after-milliseconds配置的时间且没 有有效的回复,则判定节点不可达,<times>(单位为毫秒)就是超时时 间。这个配置是对节点失败判定的重要依据。对 Sentinel节点、主节点、从节点的失败判定同时有效。
sentinel down-after-milliseconds mymaster 30000
# parallel-syncs 就是用来限制在一次故障转移之后,每次向新的主节 点发起复制操作的从节点个数。
sentinel parallel-syncs mymaster 1
# 故障转移超时时间
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
# 当 redis 主从复制配置了密码的话,则需要在这里配置密码
sentinel auth-pass mymaster WHredis2020!

 • daemonize是否在后台启动,默认为 no,注意这里需要设置为 no,否则容器启动不起来。


 • logfile日志文件,哨兵监控和故障转移的日志都会存到这个日志里面。


 • sentinel monitor mymaster监控 redis 的 IP 和端口,这里监控的 redis 的主节点。


 • down-after-milliseconds:每个 Sentinel节点都要通过定期发送 ping 命令来判断Redis数据节点和其 余Sentinel节点是否可达,如果超过了down-after-milliseconds配置的时间且没 有有效的回复,则判定节点不可达,(单位为毫秒)就是超时时间。这个配置是对节点失败判定的重要依据。对 Sentinel节点、主节点、从节点的失败判定同时有效。

 

 • parallel-syncs:就是用来限制在一次故障转移之后,每次向新的主节 点发起复制操作的从节点个数。

 

 • failover-timeout:故障转移超时时间。


 • auth-pass:当 redis 主从复制配置了密码的话,则需要在这里配置密码。


首先在本地创建日志文件用来存放哨兵日志。

mkdir /home/redis/sentinel
vim /home/redis/sentinel/sentinel-26379.log

4.4 启动哨兵容器


4.4.1 启动一个 sentinel 容器

docker run --name mysentinel1 --restart=always -p 26379:26379 \
-v /home/redis/sentinel.conf:/usr/local/etc/redis/sentinel.conf \
-v /home/redis/sentinel/sentinel-26379.log:/var/log/sentinel-26379.log \
-d 9a2f \
redis-sentinel /usr/local/etc/redis/sentinel.conf

 • --name mysentinel1,指定哨兵容器的名称为 mysentinel1。
 • --restart=always,重启机器后,自动重启容器。
 • -v,挂载哨兵配置文件和日志文件。

 

这里的 -d 9a2f 是 本地的 redis 容器 id,因为本机没有网络,所以这个镜像是从其他有网络的机器加载进来的。如果你们的机器有网络,完全可以用 -d redis 参数替换,也就是使用最新的 redis 镜像来启动 sentinel。

 

查看启动的容器,第一个是哨兵容器,名字是 mysentinel1, 第二个是 redis 容器,名字是 redis。如下图所示:从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区当在三台服务器上分别启动 Redis 哨兵后,查看哨兵日志文件 sentinel-26379.log。从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区打印出了 Redis 的当前版本(5.0.14),运行模式(哨兵模式),端口号 26379,哨兵 id,监控的 Redis 中的主节点,两个 Redis 从节点和一个主节点的 IP 和 端口。

 

而且当我们去查看 Sentinel 配置文件时,发现配置文件中的内容发生了变化,在文件末尾追加了以下内容,含义就是 Sentinel 自动发现了其他 Redis 从节点 

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区

4.4.2 启动第二个容器


执行以下命令启动第二个容器:

docker run --name mysentinel2 --restart=always -p 26379:26379 \
-v /home/redis/sentinel.conf:/usr/local/etc/redis/sentinel.conf \
-v /home/redis/sentinel/sentinel-26379.log:/var/log/sentinel-26379.log \
-d 9a2f \
redis-sentinel /usr/local/etc/redis/sentinel.conf

 从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区4.4.3 启动第三个容器


执行以下命令启动第三个容器:

docker run --name mysentinel3 --restart=always -p 26379:26379 \
-v /home/redis/sentinel.conf:/usr/local/etc/redis/sentinel.conf \
-v /home/redis/sentinel/sentinel-26379.log:/var/log/sentinel-26379.log \
-d 9a2f \
redis-sentinel /usr/local/etc/redis/sentinel.conf

4.4.4 验证 Redis 主从切换


停掉主节点的 redis 容器后,进入到第二个哨兵容器中,执行以下命令查看哨兵的状态:

redis-cli -h 127.0.0.1 -p 26379 info Sentinel 

发现主节点的 IP 已经从 10.2.1.61 切换为从节点的 IP(10.2.1.63)了。从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区进入到第二个 redis 容器中,查看同步状态。主节点的 IP 也是 10.2.1.63 

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区

查看第三个哨兵的日志,可以看到哨兵通过以下步骤进行了主从切换。 

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区

重要的步骤说明如下:

 

 • 主观宕机+sdown 表示当前哨兵认为这个 Redis 节点(10.2.1.61)宕机了。
 • 客观宕机+odown 表示有几个哨兵认为这个 Redis 节点(10.2.1.61)宕机了。看到的 quorun 4/2,表示有 4 个哨兵认为 Redis 节点宕机了,大于设置的 2,所以这个 Redis 节点是真的宕机了。(这里为什么是 4,而不是哨兵数 3,笔者也没有弄清楚,欢迎留言讨论。)
 • 投票选举新的哨兵 Leader,三个哨兵都将票投给了 id = 2abxxx 的哨兵,也就是第三个哨兵节点,将由这个哨兵进行主从切换。
 • ④ 开始故障转移,failover-state-select-slave 表示要转移哪个故障节点。这里就是切换主节点。
 • ⑤ 选出主节点为第三个 Redis 节点(10.2.1.63)。
 • ⑥ 切换主节点为第三个 Redis 节点(10.2.1.63)。


说明哨兵集群模式下对 Redis 的状态监控和主从切换成功。

 

五、客户端自动感知故障


如何实现自动感知故障


我们项目中,都是用 Redis 客户端去读写 Redis,在单机情况下,单节点 Redis 宕机后,客户端肯定会报错,我们可以尝试恢复这个服务器上的 Redis 就好了。

 

但是我们现在是有多个 Redis 节点的,应用程序该如何配置呢?

 

可能的思路是这样:应用程序配置主节点的 IP 地址和端口。缺点:主节点切换后,需要改配置并重启应用。

 

那有没有一种方案是自动感知到 Redis 宕机后,连接到新的主节点的呢?

 

有的,我们加下 Redis 的哨兵配置就可以了。配置内容如下所示:

spring:
  redis:
    database: 0
    password: abc123   # 密码(默认为空)
    timeout: 10000  # 连接超时时长(毫秒)
    sentinel: #哨兵模式
      master: mymaster #主服务器所在集群名称
      nodes: 10.2.1.63:26379,10.2.1.62:26379,10.2.1.61:26379

配置好了后,重启应用程序,然后停掉 Redis 主节点的容器。测试往 redis 写入数据,程序会报错。

 

写入数据的代码:

stringRedisTemplate.opsForValue()
  .setIfAbsent(key, toJson(value), 
     millisecond, TimeUnit.MILLISECONDS);

报错信息如下:

nested exception is redis.clients
  .jedis.exceptions.JedisConnectionException: 
     Unexpected end of stream.

因为故障转移是需要一定时间的,过几秒后后发现控制台窗口打印出 Redis 的主节点为 10.2.1.63:6379,说明故障转移成功了。

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区

[MasterListener-mymaster-[10.2.1.61:26379]] 
  INFO  redis.clients.jedis.JedisSentinelPool 
    -Created JedisPool to master at 
      10.2.1.63:6379

再次测试读写 Redis,都是正常的,且往第三个节点写入数据后,第二个节点也进行了主从复制。

 

客户端自动感知的原理


我们项目中用的 Jedis 客户端,它有一个连接池 JedisPool,当访问 Redis 时,会从连接池里面获取一个连接。我们看下这个连接池里面的信息。如下图所示:

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路(二)-鸿蒙开发者社区 • masterListeners 代表对三个 Redis 节点的监听器。里面指定了 Redis 节点的 IP 和 Port。


 • currentHostMaster 代表当前连接的主节点。目前为第三个节点。


当我们停掉 Redis 主节点后,哨兵会切换主节点,这个连接池里面的 currentHostMaster 也会被更新为新的主节点。当我们再次访问 Redis 时,会和新的主节点建立连接。

 

六、遇到的问题


6.1 提示不能写只读的 redis 节点

READONLY You can't write against a read only replica.;

解决方案:每个哨兵都需要配置成监控主节点 node1 的 IP。

 

6.2 提示连接 Redis 失败

ERR Client sent AUTH, but no password is set

解决方案:主从节点都需要配置 requirepass  和 masterauth。

 

七、总结


本篇讲解了在真实的多台服务器上如何部署 Redis 主从架构、哨兵集群,以及验证主从复制和故障转移。

 

然后对项目中使用 Redis 的地方,加入了哨兵配置,使其可以自动感知主从切换后的 IP 变化,从而和新的 Redis 主节点进行连接。

 

Redis Cluster 集群模式并没有涉及到,大家有没有兴趣呢~~

标签
已于2022-6-30 16:54:25修改
收藏
回复
举报
回复
    相关推荐