在具有哨兵的AWS上设置Redis HA - 不同哨兵看到的redis节点最终无限循环

mjs*_*lva 6 amazon-web-services redis autoscaling redis-sentinel devops

我们的设置

  • 每个AWS Sydney AZ上有3个redis哨兵一个
  • 具有主服务器和多个从服务器的2到500个redis节点,可使用AWS自动扩展组策略自动水平扩展
  • 1x写入将流量推送到主站的ELB
  • 1x读取将流量推送到从站的ELB
  • 1x Sentinel ELB将流量推送到哨兵
  • 1x辅导员(更多关于这个波纹管)

此设置在两个集群中复制,用于称为元数据缓存.我们想要部署更多集群.

主持人

是我们构建的python守护程序,它订阅了sentinels pub/sub并侦听+ switch-master消息.以下是协调人采取的行动:

  1. 检测并主控+ switch-master触发的故障转移
  2. 使用查询新主服务器的标记 SENTINEL get-master-addr-by-name mymaster
  3. 使用RedisClusterNodeRole = slave标记旧主服务器
  4. 使用RedisClusterNodeRole = master标记新的master
  5. 在我们的写ELB中添加新的master
  6. 从我们的阅读ELB中删除新的主人
  7. 从写ELB中删除旧主人
  8. 尝试将旧主服务器添加到我们的读取ELB中(如果服务器已关闭,这将失败,这很好)

问题

因为奴隶每天可以根据交通进出多次,所以我们最终会遇到属于同一个奴隶争夺同一奴隶的哨兵的一些奴隶.这是因为IP池在集群之间共享,并且据我们所知,从属ID是它们的IP.

这是复制的方法:

  1. 群集缓存具有IP 172.24.249.152的主服务器
  2. 群集缓存具有主故障转移提升从站,主机为IP 172.24.246.142.IP 172.24.249.152的节点现已关闭
  3. 群集元数据向上扩展,DHCP分配IP 172.24.249.152(群集缓存上的先前主服务器)
  4. 群集缓存将看到它的先前主服务器现在已启动,并将尝试将其重新配置为172.24.246.142(缓存群集上的新主服务器)的slave
  5. 簇的元数据将触发上的+ SDOWN 172.24.246.142和一段时间后接着是+从属可重新-发送给它的尝试重新配置它作为元数据群集从属一个-sdown
  6. 群集缓存将尝试执行与群集元数据在第5点上执行的操作相同的操作.

哨兵陷入无休止的循环中,永远为这种资源而战.即使我们只有一个哨兵小组管理具有不同主名称的两个redis群集,这种情况也会发生.这使我们相信哨兵不了解不同群集之间的资源,而只是分别对每个群集执行合乎逻辑的操作.

解决方案我们试过

  1. 触发a SENTINEL reset mymaster+ sdown事件后,尝试让哨兵忘记该节点.问题是,如果该集群正在执行主故障转移,它可能会生成竞争条件.我们成功地复制了这个假设,并且让哨兵不同步,其中一个指向一个主人,另外两个指向另一个.
  2. 将网络分成每个群集一个IP池.这是有效的,因为IP不会被重用,但是当我们需要一个新的集群时,它也会使事情变得更加灵活和复杂.这是我们最终要解决的问题,但我们希望尽可能避免这种情况.

理想的解决方案

  1. Redis哨兵提供SENTINEL removeslave 172.24.246.142 mymaster我们可以在每次有奴隶的+ sdown事件时运行.这将使该群集忘记那个奴隶曾经存在而不会产生副作用SENTINEL reset mymaster.

  2. 仅通过IP停止识别奴隶的唯一性.也许添加一个redis服务器启动时间戳或任何其他令牌,以防止关闭的从站和使用相同IP备份的新站点被视为同一节点.

您能想到任何其他解决方案,不涉及更改redis哨兵代码,并且不需要在群集之间隔离IP池吗?