前言
Redisson 在历史多个版本都出现了failover期间报错的问题并且目前没有一个版本可以完全解决这个问题,所以在当前使用版本3.18.0基础上做了二次开发,达到降低业务由于redis遇到问题导致不可用。
背景
Redisson 作为业务线使用的Redis 客户端,在处理 Redis 高可用架构中的故障转移(failover)时面临着特定的挑战。
特别是当 Redis 新的 slave 节点启动并加载数据集到内存中时,客户端可能会遇到 LOADING
错误,从而导致读取操作失败。
这种情况通常出现在 Redis 服务器启动或数据重新加载时,服务器在加载数据集期间,会返回 LOADING
错误,表示暂时无法处理命令。
Redisson 在接收到这一错误后,会抛出 RedisLoadingException
异常,表明 Redis 服务器目前不可用。
优化方案
为了优化 Redisson 在 failover 过程中的行为,以提高读取操作的成功率和系统的整体稳定性,我们提出以下优化策略:
-
故障转移时间记录与主节点读取路由:
- 目标:确保在故障转移窗口期间,所有的读取操作都被路由到主节点,以避免由于 slave 节点数据未完全同步而引发的读取错误。
- 实施策略:
- 在 Redisson 客户端中,增加一个机制来记录每个分片的最后一次故障转移的时间(
updateLastFailoverTime
)。 - 当检测到故障转移事件时,更新该时间戳,并在接下来的一段时间内(例如,故障转移窗口期),将所有读取请求强制路由到主节点。
- 在 Redisson 客户端中,增加一个机制来记录每个分片的最后一次故障转移的时间(
-
新 Slave 节点加入时间记录与读取路由控制:
- 目标:避免在新 slave 节点数据未完全加载完成时,将读取请求路由到该节点,减少因数据不一致或加载状态导致的读取失败。
- 实施策略:
- 在 Redisson 客户端中,对于每个 Redis 分片的 slave 节点,记录其加入集群的时间(
addSlaveJoinTime
)。 - 当有新的 slave 节点加入时,更新该节点的加入时间。在节点数据加载期间,避免将读取请求路由到该新 slave 节点。
- 在 Redisson 客户端中,对于每个 Redis 分片的 slave 节点,记录其加入集群的时间(
实现细节
- 对于 Redisson 客户端的修改,需要在其内部维护故障转移时间和新 slave 节点加入时间的状态信息。这涉及到对 Redisson 的连接管理器(Cluster
ConnectionManager
)进行扩展,以便它能够处理额外的逻辑判断。 - 对于读取操作的路由逻辑,可以在执行命令之前进行检查,根据当前时间与记录的故障转移时间或新 slave 节点的加入时间进行比较,决定是否将请求路由到主节点或现有的 slave 节点。
代码变更:
redisson配置:更短的超时时间增加检测敏感度
spring:
redis:
redisson:
config: |
clusterServersConfig:
masterConnectionMinimumIdleSize: 8
slaveConnectionMinimumIdleSize: 8
idleConnectionTimeout: 10000
connectTimeout: 3000
timeout: 1000
retryAttempts: 3
retryInterval: 500
failedSlaveReconnectionInterval: 30000
failedSlaveCheckInterval: 60000