Redis Sentinel实现集群节点故障转移

时间:2024-10-13 07:52:44

1. 简介

Redis Sentinel为Redis提供了很高的可用性,在实践中,这意味着你可以部署一个可以解决非人为干预导致节点故障的Redis集群系统。Redis Sentinel还提供了其他的功能:如监控,通知和客户端配置服务的提供方。下面列出来了Redis Sentinel的功能列表:

  • 监控:Sentinel能够监控master节点或slave节点是否处于按照预期工作的状态。
  • 通知:Sentinel能够通过api通知系统管理原,其他的计算机程序,Redis实例运行过程中发生了错误。
  • 自动故障转移:如果Redis的master节点出现问题,Sentinel能够启动一个故障转移处理,该处理会将一个slave节点提升为master节点,其他的slave节点则会自动配置成新的master节点的slave节点,如果原来的master重新正常启动后,也会成为该新Master的slave节点。
  • 客户端配置提供者:Sentinel可作为客户端服务发现的一个权威来源,客户端通过连接到Sentinel来请求当前的Redis Master节点,如果Master节点发生故障,Sentinel将会提供新的master地址。
Redis Sentinel 是一个分布式系统, 你可以在架构中运行多个 Sentinel 进程,这些进程通过相互通讯来判断一个主服务器是否断线,以及是否应该执行故障转移。在配置Redis Sentinel时,至少需要有1个Master和1个Slave。当Master失效后,Redis Sentinel会报出失效警告,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器,并提供读写服务;当失效的Master恢复后,Redis Sentinel会自动识别,将Master自动转换为Slave并完成数据同步。通过Redis Sentinel可以实现Redis零手工干预并且短时间内进行M-S切换,减少业务影响时间。

虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动 Redis Sentinel。

2. 部署

2.1  部署Redis集群

先在3个机器上部署1个master, 2个slave, 具体部署过程参考上一边文章:Redis

本次部署的节点如下:

 10.7.112.52 部署Master节点
 10.7.12.52   部署Slave节点
 10.5.35.3     部署Slave节点

2.2  部署Redis Sentinel

1. 将master拷贝一份,重新命名为master-sentinel(可任意命名)。
2. 在master-sentinel的同目录下增加一个文件:,在文件中添加一下内容:

<span style="font-size:14px;">sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1</span>

第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效, 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持, 才能发起一次自动故障迁移, 并预留一个给定的配置纪元 (configuration Epoch ,一个配置纪元就是一个新主服务器配置的版本号)。换句话说, 在只有少数(minority) Sentinel 进程正常运作的情况下, Sentinel 是不能执行自动故障迁移的。

其他选项的基本格式如下:

sentinel <选项的名字> <主服务器的名字> <选项的值>

各个选项的功能如下:
  • down-after-milliseconds:指定了 Sentinel 认为服务器已经断线所需的毫秒数。如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。
  • parallel-syncs :指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长。如果从服务器被设置为允许使用过期数据集(参见对 文件中对 slave-serve-stale-data 选项的说明), 那么你可能不希望所有从服务器都在同一时间向新的主服务器发送同步请求, 因为尽管复制过程的绝大部分步骤都不会阻塞从服务器, 但从服务器在载入主服务器发来的 RDB 文件时, 仍然会造成从服务器在一段时间内不能处理命令请求: 如果全部从服务器一起对新的主服务器进行同步, 那么就可能会造成所有从服务器在短时间内全部不可用的情况出现。你可以通过将这个值设为 1 来保证每次只有一个从服务器处于不能处理命令请求的状态。
3.  添加bat文件

--sentinel

最后的文件结构:


4. 将maser-sentinel文件夹拷贝到10.7.12.52和10.5.35.3机器上各一份

5. 分别启动各自的命令来启动redis-sentinel节点

10.7.112.52上的启动信息:


10.7.12.52上的启动信息


10.5.35.3上的启动信息


启动完之后发现文件内容也自动发生了改变:

<span style="font-size:14px;">sentinel monitor mymaster 10.7.112.52 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
# Generated by CONFIG REWRITE
port 26379
dir "D:\\redis\\redis-cluster\\master-sentinel\\redis-64.2.8.17"
sentinel known-slave mymaster 10.5.35.3 6380
sentinel known-slave mymaster 10.7.12.52 6379
sentinel known-sentinel mymaster 10.7.12.52 26379 5356501f2b6b773704718527020dd88da1c43725
sentinel known-sentinel mymaster 10.5.35.3 26379 80bfae8b3c96aca804268b7f660ce1acdc80bc7d
sentinel current-epoch 0</span>

此已经将redis sentinel的3个节点启动完成了,用redis-cli连接到master节点查看下集群信息:


我们用客户端程序来测试下redis的使用。

  1. <span style="font-size:14px;">public static void main(String[] args){
  2. Set sentinels = new HashSet();
  3. (new HostAndPort("10.7.112.52", 26379).toString());
  4. (new HostAndPort("10.7.12.52", 26379).toString());
  5. (new HostAndPort("10.5.35.3", 26379).toString());
  6. JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinels);
  7. ("Current master: " + ().toString());
  8. Jedis master = ();
  9. ("name","张三");
  10. (master);
  11. Jedis master2 = ();
  12. String value = ("name");
  13. ("name: " + value);
  14. ();
  15. ();
  16. }</span>
运行结果:

<span style="font-size:14px;">六月 08, 2015 3:35:24 下午  initSentinels
信息: Trying to find master from available Sentinels...
六月 08, 2015 3:35:24 下午  initSentinels
信息: Redis master running at 10.7.112.52:6379, starting Sentinel listeners...
六月 08, 2015 3:35:24 下午  initPool
信息: Created JedisPool to master at 10.7.112.52:6379
Current master: 10.7.112.52:6379
name: 张三</span>

2.3  模拟master节点故障转移

现在来模拟master节点发生故障,看看redis sentinel对节点的故障转移,关闭10.7.112.52上的master节点,然后会发现10.7.112.52,10.7.12.52,10.5.35.3的sentinel节点上打印以下信息,实际上就是进行新Master节点的选举:


这里我们可以看到10.5.35.3上的slave节点被选举成为新的Master节点,然后10.7.12.52上的slave节点开始从这个新的master节点上同步数据:


这时查看10.7.112.52上的文件,发现已经发生改变了:

<span style="font-size:14px;">sentinel monitor mymaster 10.5.35.3 6380 2
sentinel down-after-milliseconds mymaster 60000
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
# Generated by CONFIG REWRITE
port 26379
dir "D:\\redis\\redis-cluster\\master-sentinel\\redis-64.2.8.17"
sentinel known-slave mymaster 10.7.12.52 6379
sentinel known-slave mymaster 10.7.112.52 6379
sentinel known-sentinel mymaster 10.5.35.3 26379 80bfae8b3c96aca804268b7f660ce1acdc80bc7d
sentinel known-sentinel mymaster 10.7.112.52 26379 1167bab5c8882cbc3b01a974c30ad6997e4e1d9d

sentinel current-epoch 1</span>
而10.7.12.52上的的文件也发生了改变,原来配置的是属于10.7.112.52的slave节点,现在调整成10.5.35.3的slave节点:

原来配置为:slaveof 10.7.112.52 6379

现在配置为:slaveof 10.5.35.3 6380

可见,当重新选举master节点时,各个slave节点的配置文件和各个sentinel节点的配置文件都会自动发生调整。

现在我们用redis-cli客户端连接到10.5.35.3上的master节点查看集群节点信息:

现在再把10.7.112.52上的redis节点启动起来,会发现该节点会自动加入redis集群,并且成为新maste(10.5.35.3)的slave节点:

现在我们再用redis-cli客户端连接到10.5.35.3上的master节点查看集群节点信息:


再次执行测试程序,结果如下:

<span style="font-size:14px;">六月 08, 2015 3:59:53 下午  initSentinels
信息: Trying to find master from available Sentinels...
六月 08, 2015 3:59:53 下午  initSentinels
信息: Redis master running at 10.5.35.3:6380, starting Sentinel listeners...
六月 08, 2015 3:59:53 下午  initPool
信息: Created JedisPool to master at 10.5.35.3:6380
Current master: 10.5.35.3:6380
name: 张三
</span>


从结果可发现,对客户端而言,master节点已经切换到10.5.35.3上去了,而且客户端程序也不用更新代码。