7

我们的设置

  • 每个 AWS 悉尼 AZ 上的 3 个 redis 哨兵
  • 2 到 500 个 redis 节点,具有一个主节点和多个从节点,使用 AWS 自动扩展组策略自动水平扩展
  • 1x 写入 ELB,将流量推送到主服务器
  • 1x 读取 ELB,将流量推送到从站
  • 1x Sentinel ELB,将流量推送到哨兵
  • 1x 辅导员(更多内容见下文)

这个设置被复制到两个集群中,我们称之为metadatacache。我们想部署更多的集群。

促进者

是我们构建的一个 python 守护进程,它订阅 sentinels pub/sub 并监听+switch-master消息。以下是辅导员采取的行动:

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

问题

因为奴隶每天可以根据流量来来去去多次,所以我们最终会遇到一些奴隶属于两个集群中的哨兵争夺同一个奴隶。发生这种情况是因为 IP 池在集群之间共享,并且据我们所知,从属 ID 是它们的 IP。

以下是如何复制:

  1. 集群缓存有一个 IP为 172.24.249.152的 master
  2. 集群缓存有一个主故障转移,将 IP为172.24.246.142的从属设备升级为主设备。IP 为 172.24.249.152 的节点现已关闭
  3. 集群元数据向上扩展,DHCP 分配 IP 172.24.249.152(集群缓存上的前一个主节点)
  4. 集群缓存将看到它以前的主服务器现在已启动,并将尝试将其重新配置为 172.24.246.142 的从服务器(缓存集群上的新主服务器)
  5. 集群元数据将在 172.24.246.142 上触发 +sdown在一段时间后 -sdown 后跟 +slave-reconf-sent 发送给它以尝试将其重新配置为元数据集群的从属
  6. 集群缓存将尝试执行与集群元数据在第 5 点所做的相同的操作。

哨兵被困在这个无休止的循环中,永远为该资源而战。即使我们只有一个哨兵组管理具有不同主名称的两个 redis 集群,也会发生这种情况。这使我们相信,哨兵并不知道不同集群之间的资源,而是它们只是分别为每个集群做合乎逻辑的事情。

我们尝试过的解决方案

  1. 在 +sdown 事件之后触发一个SENTINEL reset mymaster,试图让哨兵忘记那个节点。这样做的问题是,如果该集群正在执行主故障转移,它可能会产生竞争条件。我们成功地复制了这个假设并且留下了不同步的哨兵,其中一个指向一个主节点,另外两个指向另一个。
  2. 将网络隔离为每个集群一个 IP 池。这是可行的,因为 IP 永远不会被重用,而且当我们需要一个新的集群时,它也会让事情变得不那么灵活和复杂。这是我们最终寻求的解决方案,但如果可能,我们希望避免它。

理想的解决方案

  1. Redis sentinel 提供了一个SENTINEL removeslave 172.24.246.142 mymaster我们可以在每次从站上发生 +sdown 事件时运行的。这将使该集群忘记从属曾经存在过,而不会产生 a 所具有的副作用SENTINEL reset mymaster

  2. 停止仅通过 IP 识别从属设备的唯一性。也许添加一个 redis 服务器启动时间戳或任何其他标记,以防止关闭的从属服务器和使用相同 IP 恢复的新服务器被视为同一个节点。

问题

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

4

0 回答 0