常见场景题-接口重试策略如何设计?
接口重试策略如何设计?
常见的重试策略有两种:
- 固定间隔时间重试:实现简单、但是可能导致重试过于频繁或稀疏,从而影响系统性能。如果重试间隔太短,可能导致雪崩效应;如果太长,可能影响用户体验
- 梯度间隔重试:根据重试次数去延长重试间隔时间。例如第一次重试间隔1s,第二次2s,第三次4s。能有效提高重试的几率,也能通过梯度增加间隔时间来避免对下游系统造成更大压力。此种策略需要设置合理的上下限值,否则可能导致延长时间过长。
重试策略对分布式系统来说是自私的,客户端认为他的消息很重要,并要求服务端花费更多资源来处理,盲目的重试设计不可取。
重试策略最佳实践:
- 合理设置消费的最大超时时间和次数(尽快向客户端返回成功或失败,不要以超时或者异常抛出来代替消费失败)
- 重试会导致相同的消息进行
重复消费
,消费方应该有一个良好的幂等设计
支付系统中补单操作如何完成:https://mp.weixin.qq.com/s/9Z-N3cfWu7oMVJsTDkbb-Q
简单来讲,补单利用 RocketMQ 对操作失败进行补偿操作,但不能一直进行补偿操作,需要设置一个最大重试次数,在多次补偿失败之后,需要延缓补偿频率,这些都通过 RocketMQ 进行实现,这里还存在几个问题:
- 如果异常消息发送失败,上游没有重试机制,这笔订单就会卡住,因为系统并不知道需要去补偿
- 在补偿消息时失败
- 如果重试达到最大次数仍然没有成功,该如何处理?
针对问题1,可以将异常消息落库,存在异常消息表中,记录订单号、当前重试次数、一场分类、记录状态、消息体等字段,设置定时任务去扫描该表进行处理。对当前 MQ 的可用性,异常数据很少出现。
针对问题2,如果补偿失败,会向上抛出 error,利用 RocketMQ 的梯度重试机制,当消费次数上限后会进入死信队列。这种情况一般是网络出现问题,恢复之后,可以从死信队列拉取这些消息再统一处理。如果 MQ 和 DB 都失败了,为极端情况,人工介入即可。
针对问题3,如果达到最大次数仍然没有成功,将他放入异常表。
还可以有一些在业务低峰期的兜底任务,扫描业务表,对未完成的订单进行补偿。兜底任务可能造成信息的短暂堆积,影响线上补偿流程推进,可以使用独立的队列隔离开。