重试模块介绍
# 视频教程
从0到1快速了解分布式重试组件EasyRetry (opens new window)
# 🌈重试模块简介
在当前广泛流行的分布式系统中,确保系统数据的一致性和正确性是一项重大挑战。为了解决分布式事务问题,涌现了许多理论和业务实践,其中BASE理论 (opens new window)是目前业界广泛接受的分布式一致性理论。
基于BASE理论,采用柔性事务并优先保障系统的可用性和数据的最终一致性已逐渐成为技术共识。
为了确保分布式服务的可用性和数据一致性,并防止由于网络抖动、连接超时等问题导致短时不可用的情况,根据"墨菲定律",在核心流程中增加重试和数据核对校验的动作成为提高系统鲁棒性常用的技术方案。
在此背景下EasyRetry应运而生。EasyRetry是一款基于BASE思想实现的分布式服务重试组件,旨在通过重试机制确保数据的最终一致性。它提供了控制台任务观测、可配置的重试策略、重试后执行回调以及丰富地告警配置等功能。通过这些手段,可以对异常数据进行全面监测和回放,从而在确保系统高可用性的同时,大大提升数据的一致性。
# 🌈Easy Retry为解决什么样的问题而生?
# Easy Retry和现有方案的对比
EasyRetry上线至今,遇到最多的问题就是:这款框架和SpringRetry
或者GuavaRetry
有什么区别呢?
SpringRetry
和GuavaRetry
是由Spring和Google开发的重试框架,用于解决短期系统异常或网络抖动引起的问题。这两个框架均采用基于内存的重试策略。
相比之下,EasyRetry
是一种面向分布式系统数据一致性问题的解决方案,它以重试为核心,提供了一系列功能来处理异常数据和确保最终一致性。
SpringRetry和GuavaRetry确实无法提供数据最终一致性的保障。它们主要用于处理短期系统异常或网络抖动,尝试重新执行操作,但是在重试N次后异常仍为解决,可能会导致数据丢失。对于核心业务场景,数据丢失可能带来严重的问题。
# Easy Retry的数据一致性解决方案
为确保数据的完整性和一致性,当前场景比较好的解决方案是在系统中使用本地消息表来添加异步确认机制,这种解决方案的核心是将分布式事务转化为本地事务 我们用一个余额扣减案例来说明这种方案,假设在一套商品服务中,用户下单完成后需要执行扣减余额、扣减积分、扣减优惠券的动作,假如采用本地消息表的方式来实现 大致的实现过程是这样子的:
在这种方案中,消息生产方会将消息发送到消息表中,并记录消息的发送状态。这个消息表通常与业务数据在同一个事务中提交,即它们在同一个数据库中。随后,消息会通过消息队列(MQ)发送到消息的消费方。 如果消息发送失败,会进行重试发送,直到消息成功发送为止。消息的消费方需要处理这些消息,并完成自身的业务逻辑。如果本地事务处理成功,表示消息已经成功处理;如果处理失败,会进行重试执行,直到成功为止。 如果在业务处理中发生了失败情况,可以向消息生产方发送一个业务补偿消息,通知其执行回滚等操作,以确保数据的一致性。 生产方和消费方会定期扫描本地,重新发送那些尚未处理完成或处理失败的消息,以保证消息的可靠性。 为了防止意外情况的发生,通常还会设置一个自动对账的逻辑,用于核对业务数据和消息数据,以确保数据的准确性和一致性。
经过以上操作后,系统可以较好地保证数据一致性,然而这种方案的缺点也是比较明显的, 首先它在数据库中增加了额外的表,这就使得我们所需要处理的业务必须拥有所需处理的数据库和表权限,如果此时我们的调用链中存在第三方服务,就会带来极大地不便。 其次系统中对于消息的发送、接收以及对账程序的编写,无疑会增加我们的工作量和系统复杂度。
如果采用EasyRetry来实现数据一致性方案,交互流程是这样子:
在这种方案中,我们使用 EasyRetry 来捕获和处理异常数据,将不同系统产生的异常数据集中到 EasyRetry 的控制台进行配置和管理。 通过 EasyRetry,我们可以自定义重试策略和触发时间。当重试任务执行成功或达到系统配置的最大执行次数时,服务端会向客户端发送回调请求。在接收到回调请求后,客户端可以指定后续动作。 举例来说,当服务端发起重试达到最大请求次数但仍然失败时,客户端可以执行回滚操作,确保事务的完整性。通过灵活配置回调请求的处理方式,我们可以根据具体业务需求进行相应的处理操作。
EasyRetry框架通过简单的接入方式,可以捕获分布式系统中的核心场景异常,并进行数据补偿。它能够统一管理不同系统间的异常数据,并大大降低开发成本。框架提供了易于上手的控制台,用户可以通过管理后台进行数据回放、异常分析和重试限制。 尽管通过重试来处理接口异常是成本最低的做法,但由于重试可能引发多次请求的问题,这也是一个常见的系统安全隐患。EasyRetry针对重试风暴风险设计了多种防治手段,包括单机流量管控、跨集群链路管控和可视化数据管控,有效地避免了多次重试带来的风险。 此外,EasyRetry框架提供了丰富的SPI接口,用户可以根据场景需求进行幂等ID的自定义、重试方法的自定义以及回调结果的自定义。针对不同的业务场景,框架提供了多种解决方案。通过灵活的配置和定制,可以满足各种业务需求。
# 🌈一致性方案对比
# 🌈Easy Retry框架的核心优势?
# 数据持久化
对于系统中核心场景的数据安全是非常重要的保障手段, 基于内存重试策略(目前业界比较比较出名的SpringRetry
或者GuavaRetry
都是基于内存重试实现的)数据的持久性得不到保障,
EasyRetry提供了本地重试、服务端重试、本地重试和服务端重试相结合三种重试模式。
EasyRetry的本地重试方案依然保留了内存重试的策略,应对短暂不可用场景下的快速补偿。服务端重试则实现了数据的持久化,支持多种数据库配置。用户可以通过控制台管理异常数据,自定义多种配置,便捷地完成数据补偿操作。
# 避免重试风暴
重试操作可以更加轻量化低成本的保障数据一致性,但是带来的风险也不容忽视,那就是重试风暴。
EasyRetry
支持多种方式防止重试风暴的产生比如单机流量管控、跨集群链接管控和可视化数据管控等
- 什么是单机流量管控? 在重试过程中,如果重试控制不当,容易造成单机多注解循环引用问题。EasyRetry对于重试流量做出了标识,单机的重试请求不会引发再次重试。
- 什么是跨集群链接管控? 在跨集群的多级链路场景中,EasyRetry会标识重试流量,限制每层都发生重试。理想情况下,多级链路请求场景中只有最下一层发生重试。
- 什么是可视化数据管控? EasyRetry控制台给出了重试请求和回调请求的信息,包括触发时间、重试次数、错误日志等,用户可以通过控制台对每个重试请求做到实时查看和监控。
# 接入简单
EasyRetry
和SpringRetry
一样的都是基于注解实现,只需要添加一个@Retryable即完成接入,具体的接入方式可参考接入指北
# 配置多样化
EasyRetry控制台提供了多样化的参数配置,包括路由策略、Id生成模式、分区指定、退避策略、最大重试次数、告警通知等。满足用户在不同场景下的配置需求。
# 可扩展性
EasyRetry预留了大量自定义场景,如重试结果处理器、自定义方法执行器、幂等ID生成器等模块,为用户预留了可扩展空间,可根据系统需求满足不同场景下的使用需要。