Redian新闻
>
大厂都是怎么做Redis重试的?

大厂都是怎么做Redis重试的?

公众号新闻
受网络和运行环境影响,应用程序可能遇到暂时性故障,如瞬时网络抖动、服务暂时不可用、服务繁忙导致超时等。
自动重试机制可大幅避免此类故障,保障操作成功执行。

1 引发暂时性故障的原因

1.1 故障触发了高可用机制

云 Redis 支持节点健康状态监测,当监测到实例中的主节点不可用时,会自动触发主备切换,例如将主节点和从节点进行互换,保障实例的高可用性。此时,客户端可能会遇到下列暂时性故障:秒级的连接闪断。30 秒内的只读状态(用于避免主备切换引起潜在的数据丢失风险和双写)。
更多参见:主备切换(https://help.aliyun.com/zh/redis/user-guide/master-replica-switchovers#concept-2025502

1.2 慢查询引起了请求堵塞

执行时间复杂度为 O (N) 的操作,引发慢查询和请求的堵塞,此时,客户端发起的其他请求可能出现暂时性失败。

1.3 复杂的网络环境

由于客户端与 Redis 服务器之间复杂网络环境引起,可能出现偶发的网络抖动、数据重传等问题,此时,客户端发起的请求可能会出现暂时性失败。

2 推荐的重试准则

2.1 仅重试幂等的操作

由于超时可能发生在下述任一阶段:该命令由客户端发送成功,但尚未到达 Redis。命令到达 Redis,但执行超时。命令在 Redis 中执行结束,但结果返回给客户端时发生超时。如果执行重试可能导致某个操作在 Redis 中被重复执行,因此不是所有操作均适合设计重试机制。通常推荐仅重试幂等的操作,例如 SET 操作,即多次执行 SET a b 命令,那么 a 的值只可能是 b 或执行失败;如果执行 LPUSH mylist a 则不是幂等的,可能导致 mylist 中包含多个 a 元素。

2.2 适当的重试次数与间隔

根据业务需求和实际场景调整适当的重试次数与间隔,否则可能引发下述问题:如果重试次数不足或间隔太长,应用程序可能无法完成操作而导致失败。如果重试次数过大或间隔过短,应用程序可能会占用过多的系统资源,且可能因请求过多而堵塞在服务器上无法恢复。常见的重试间隔方式包括立即重试、固定时间重试、指数增加时间重试、随机时间重试等。

2.3 避免重试嵌套

避免重试嵌套,否则可能会导致重复的重试且无法停止。

2.4 记录重试异常并打印失败报告

在重试过程中,建议在 WARN 级别上打印重试错误日志,同时,仅在重试失败时打印异常信息。

3 Jedis

建议使用 Jedis 4.0.0 及以上版本,推荐使用最新的 Jedis 版本,以下代码为 Jedis 5.0.0 的重试示例。

3.1 添加 Jedis 的 Pom 依赖

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.0.0</version>
</dependency>

3.2 重试实战

① 标准架构实例或集群架构代理(Proxy)模式

使用 JedisPool 模式。
该示例会将 SET 命令自动重试 5 次,且总重试时间不超过 10s,每次重试之间等待类指数间隔的时间,如果最终不成功,则抛出异常。
PooledConnectionProvider provider = new PooledConnectionProvider(HostAndPort.from("127.0.0.1:6379"));
int maxAttempts = 5; // 最大重试次数
Duration maxTotalRetriesDuration = Duration.ofSeconds(10); // 最大的重试时间
UnifiedJedis jedis = new UnifiedJedis(provider, maxAttempts, maxTotalRetriesDuration);
try {
System.out.println("set key: " + jedis.set("key", "value"));
} catch (Exception e) {
// 表示尝试maxAttempts次或到达了最大查询时间maxTotalRetriesDuration仍旧没有访问成功。
e.printStackTrace();
}

② 集群架构直连模式

使用 JedisCluster 模式。
可以通过配置 maxAttempts 参数来定义失败情况下的重试次数,默认值为 5,如果最终不成功,则抛出异常。
HostAndPort hostAndPort = HostAndPort.from("127.0.0.1:30001");
int connectionTimeout = 5000;
int soTimeout = 2000;
int maxAttempts = 5;
ConnectionPoolConfig config = new ConnectionPoolConfig();
JedisCluster jedisCluster = new JedisCluster(hostAndPort, connectionTimeout, soTimeout, maxAttempts, config);
try {
System.out.println("set key: " + jedisCluster.set("key", "value"));
} catch (Exception e) {
// 表示尝试maxAttempts之后仍旧没有访问成功。
e.printStackTrace();
}

4 Redisson

Redisson 客户端提供了两个参数来控制重试逻辑:
  • retryAttempts:重试次数,默认为 3。

  • retryInterval:重试间隔,默认为 1,500 毫秒。

重试示例如下:
Config config = new Config();
config.useSingleServer()
.setTimeout(1000)
.setRetryAttempts(3)
.setRetryInterval(1500) //ms
.setAddress("redis://127.0.0.1:6379");
RedissonClient connect = Redisson.create(config);

5 StackExchange.Redis

StackExchang.Redis 客户端目前仅支持重试时连接,重试示例如下:
var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,connectRetry=3");
说明
如需实现 API 级别的重试策略,请参见 Polly。

6 Lettuce

Lettuce 客户端未提供在命令超时后重试的参数,但是您可以通过下述参数来实现命令重试策略:
  • at-most-once execution:命令最多执行 1 次,即 0 次或 1 次,如果连接断开并重新连接,命令可能会丢失。

  • at-least-once execution(默认):最少成功执行 1 次,即可能会在执行时进行多次尝试,保障最少成功执行 1 次。使用此策略时,如果 Tair 实例发生了主备切换,此时客户端可能累积了较多的重试命令,主备切换完成后可能会引发 Tair 实例的 CPU 使用率激增。

说明
更多信息,请参见 Client-Options(https://github.com/lettuce-io/lettuce-core/wiki/Client-Options) 和 Command execution reliability(https://github.com/lettuce-io/lettuce-core/wiki/Command-execution-reliability)。
重试示例:
clientOptions.isAutoReconnect() ? Reliability.AT_LEAST_ONCE : Reliability.AT_MOST_ONCE;
参考:
  • https://help.aliyun.com/zh/redis/use-cases/retry-mechanisms-for-redis-clients
  • 通过客户端程序连接 Redis
  • 客户端程序 TLS(SSL)加密连接 Redis

END



Siri将成为杀手级AI应用



这里有最新开源资讯、软件更新、技术干货等内容
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦~

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
大厂都在砸钱的“即时零售”,只是外卖套了个新壳?视频|真假难辨?这台电视是怎么做到出神入「画」的?从小透明,到如今移民界的知名流量,马耳他是怎么做到的?“超级MDT”是怎么做的?冬雷脑科告诉你3娃单亲妈妈从交不起电费到成为年薪6500万的社长,她是怎么做到的?美国解决不了的社会鸿沟,中国是怎么做的?从长江下游的一个县城崛起成为国际性通商巨埠,上海是怎么做到的?大厂都要求的“数据分析闭环”,该如何实现?那些高颜值的图纸,都是怎么做出来的?纽约华男骗取公司至少310万美元工资!他是怎么做到的?Nature reviews重磅!知名医疗中心发表综述:错误也是有记录的!!!部分旧版Chase Freedom用户被强制“暖心升级”成Chase Freedom Unlimited美国存够500万美元退休的富人,都是怎么做到的?历时七年,首部长片入围釜山平遥,他是怎么做到的?如何在SpringBoot中优雅地重试调用第三方API?彡字源考过来人告诉你,好看的轻法式是怎么做到的?【装修干货】在中国内地直接考取美国B超师,这么简单?无基础,仅用6个月考过2个执照,他是怎么做到的?吸引70%化学专业申请人参加,UKCHO是怎么做到的?不靠中介,超半数娃DIY进入世界名校,这所国际学校是怎么做到的?大厂都在卷次世代,心动却花4年时间打磨一款像素战棋手游?太真实了!研发人员都是怎么被搞没的?美国总统拜登父子姓名考靠战略新品冲上双11榜单,徕芬、薇姿、波司登是怎么做到的?她是怎么做到跟10年前一个样的?!!直到看到她在用这个我终于懂了!!艳遇揭秘拼多多:市值超越阿里,它是怎么做到的?社会分工---邪恶与错误的放大器三次输错密码后,系统是怎么做到不让我继续尝试的?Redis实战 | 使用Redis 的有序集合(Sorted Set)实现排行榜功能,和Spring Boot集成没开玩笑!GPA不理想,标化成绩不达标也能上哈佛,他们是怎么做到的?豆瓣8.6,原著粉赞不绝口!这部暗黑国风动画是怎么做到的?拆解 | 卖得越贵销量越高,Brompton是怎么做到的?冰岛雷克雅未克(Reykjavík),地标景点法官都是怎么忍住不笑的?
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。