【AKS+Redis】AKS中客户端(ioredis)遇见Azure Redis服务Failover后链接中断的可能性
问题描述
在AKS中连接Redis,当遇到Azure Redis 升级或者Failover时,NodeJS应用中使用ioredis sdk 在很长一段时间内无法恢复和 Azure Redis服务端的连接,对于这种想象的可能性推断。
问题解答
使用 Azure Cache for Redis 时,一个服务器是主节点,另一个服务器是副本。 主节点通常负责为来自客户端的写入和读取请求提供服务。 在执行写入操作时,它会向其内部内存提交一个新密钥和密钥更新,并立即回复客户端。 它以异步方式将操作转发给副本。
当发生升级或者是Failover时,Azure Redis服务会执行以下操作:
- 首先修补副本节点(Replica)。
- 修补的副本以协作方式将自身提升为主副本。 这种升级被视为计划性故障转移。
- 以前的主节点将重新启动以接受新的更改,并作为副本节点备份。
- 副本节点连接到主节点并同步数据。
- 数据同步完成后,将对剩余的节点重复修补过程。
在Redis的升级/故障转移(Failover)中,会出现之前的链接全部断开,然后重连的情况。所以非常考验Redis SDK的复原设计能力。
在公网上搜索,遇见有类似的问题: 一个关于 redis 长链接的问题 · Issue #1615
当 redis1 挂掉以后(比如直接电源关机),这个时候 node 客户端这边大约要等10 分钟左右才能成功连接成功 ....
Redis SDK中,Redis Client使用的TCP Connection依赖TCP的重连机制,如果遇到Redis的Failover,TCP连接将一直尝试重传,直到十几分钟后才会创建一个新的TCP连接, 这部分在Azure Redis的文档中(
Linux 托管客户端应用程序的 TCP 设置) 有非常详细的介绍:
某些 Linux 版本中的默认 TCP 设置可能会导致 Redis 服务器连接失败 13 分钟或更长时间。 默认设置可以防止客户端应用程序检测关闭的连接,并在连接未正常关闭的情况下防止自动还原这些关闭的连接。
如果网络连接中断或 Redis 服务器脱机进行计划外维护,重新建立连接可能会失败。
建议使用以下 TCP 设置:
设置 值 net.ipv4.tcp_retries2
5 有关此方案的详细信息,请参阅在 Linux 上运行时,长达 15 分钟无法重新建立连接。 虽然此讨论与 StackExchange.Redis 库有关,但 Linux 上运行的其他客户端库也会受到影响。 该说明仍然有用,可以通用化到其他库。
所以,继续查看 ioredis文档的重连配置,寻找可以避免出现长达十分钟以上无法连接Redis服务的问题:
Auto-reconnect 自动重新连接
默认情况下,当与 Redis 的连接丢失时,ioredis 会尝试重新连接,除非通过
redis.disconnect()
或redis.quit()
手动关闭连接。使用
retryStrategy
选项可以非常灵活地控制断开连接后等待多长时间重新连接:const redis = new Redis({ // This is the default value of `retryStrategy` retryStrategy(times) { const delay = Math.min(times * 50, 2000); return delay; }, });
retryStrategy
是一个在连接丢失时将被调用的函数。参数
times
表示这是第 n 次重新连接,返回值表示等待重新连接的时间(以毫秒为单位)。当返回值不是数字时,ioredis将停止尝试重新连接,如果用户不手动调用
redis.connect()
,连接将永远丢失。
参考资料
ioredis auto-reconnect: https://github.com/redis/ioredis?tab=readme-ov-file#auto-reconnect
Linux 托管客户端应用程序的 TCP 设置:https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-best-practices-connection#tcp-settings-for-linux-hosted-client-applications
一个关于 redis 长链接的问题 : https://github.com/redis/ioredis/issues/1615
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!