赞
踩
目录
在业务执行失败之后,重试一种常见的容错策略。保证数据最终的一致性。
第三方平台api调用(支付模块,邮件等等),第三方服务api调用(其他业务服务数据同步,步等),
面临上面失败问题,怎么去保证提高推送成功的可能性,因此想到重试,所以重试是为了提高成功的可能性。
那么我们重试要
因为一直重试可能会造成业务线程一直被重试占用,这样会导致服务的负载线程暴增直至服务宕机,因此需要限制重试次数。
那么如果是因为网络抖动,服务断线,我们一直重试,会造成重试浪费,造成资源浪费。所以怎么样去采用重试的时机。
那么既然有重试次数,如果我们重试也都失败了怎么办?不还是失败了嘛。
不也是可能会失败嘛。
所以我们知道重试只是提高成功的可能性。由此看,所有的方案都是提高成功的概率,如果重试都成功,服务挂了,全部断网,等等,一样会失败。所以我们实现都是近似值。到达一定程度,只能通过人为干预。
重试有哪些方案?怎么选择?
通过上面背景与问题分析,可以总结重试机制要素
有了这些要素,就知道了我们的目标
我们的目标是实现一个优雅的重试机制,那么先来看下怎么样才算是优雅。
所以我们猜测:
这个思路比较清晰,在需要添加重试的方法上添加一个用于重试的自定义注解,然后在切面中实现重试的逻辑,主要的配置参数则根据注解中的选项来初始化
优点:
缺点:
这个也比较容易理解,在需要重试的方法中,发送一个消息,并将业务逻辑作为回调方法传入;由一个订阅了重试消息的consumer来执行重试的业务逻辑
优点:
EventBus
框架,可以非常容易把框架搭起来缺点:
把这个单独捞出来,主要是某些时候我就一两个地方要用到重试,简单的实现下就好了,也没有必用用到上面这么重的方式;而且我希望可以针对代码快进行重试
优点:
缺点:
guava-retrying
和 spring-retry
实际上是更好的选择,设计与实现都非常优雅,实际的项目中完全可以直接使用
框架中应用
既然我们有了实现的方式,那么思考,上面的问题是不是都解决了呢?
我们可以采用死信队列DLQ。因为
重试就会导致后续的消费无法被消费,就会导致消息的堆积。所以他就把是失败的消息,给另外一个队列,然后去处理就行 了。
还有一种处理方式:
我们不希望消息,重试这么多,
那么我们会有一个消息重试记录表,
就是判断多少次,之后,我们持久化到数据库,
他会造成重复消费问题。
怎么解决呢?
第三方服务比较好解决:通过状态机幂等 或者访问标识,每一个请求携带一个请求。
第三方平台怎么解决?
当时支付请求发起成功,突然断网,发起方判断不了是否支付成功,此时如何处理?
状态判断
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。