转转基于MQ的分布式重试框架设计方案

文章目录

    • 1 背景
    • 2 方案
    • 3 效果
    • 4 可选项
    • 5 注意事项
    • 6 总结

1 背景

在分布式场景下,为了保障系统的可用性和数据的最终一致性,采用基于消息队列(MQ)的重试机制是一种常见的解决方案。伪代码如下:

/*** 需要保证最终一致性的函数*/
public void doSomething(Object args) {try {// 执行事务的操作executeTransaction();// 提交事务commitTransaction();} catch (Exception e) {// 回滚事务rollbackTransaction();// 记录日志log.error(e);// 序列化参数byte[] body = serialize(args);// 构建消息, 指定Topic、BodyMessage msg = new Message("doSomethingTopic", body);// 发送失败重试消息mq.send(msg);}
}/*** 消费者,用于失败重试处理*/
@Consumer(topic = "doSomethingTopic")
public void consume(Message msg) {// 反序列化Object args = msg.deserialize();// 重试doSomething(args);
}

在上述示例中,我们需要编写一系列与业务无关的代码来实现业务逻辑的重试机制。为了减轻开发人员的负担并让其专注于核心业务,我们可以对这些无关代码进行抽象和优化,以提高开发效率和代码质量。

2 方案

通过如下步骤,我们对重试逻辑进行了封装,开发人员只需要在需要保证最终一致性的函数上标注一个重试注解,便拥有基于MQ的分布式重试能力。

1. 使用注解与AOP: 通过使用注解与面向切面编程(AOP)的技术,将重试逻辑模块与业务代码解耦。开发人员可以在需要保证最终一致性的业务方法上添加注解,通过AOP将重试逻辑应用到目标方法中,从而自动触发重试机制。

2. 提供配置化选项:为重试逻辑提供可配置化的选项,例如设置最大重试次数、重试间隔时间等。这样,开发人员可以根据具体业务需求进行调整,而无需修改代码。

3. 异常处理和日志记录:在重试逻辑中合理地处理异常,并在必要时记录相关日志。这样可以帮助开发人员及时发现问题并进行排查。

4. 提供可视化监控工具:开发一个可视化的监控工具,用于实时跟踪重试操作和相关指标。这样可以帮助开发人员更好地理解重试的执行情况,并进行故障排查和性能优化。

3 效果

我们引入了@MQRetry注解用于标记业务逻辑函数,一旦该函数发生异常,该注解会将服务名、类的完整名称、方法名称以及实际参数列表发送到消息队列(MQ)中。同时系统会注册一个MQ消费者来消费这些消息,并进行重试处理。

举个例子,假设我们有一个名为doSomething的函数,它包含了需要保证最终一致性执行的业务逻辑。仅需在该函数上添加@MQRetry注解,当函数出现异常时,框架会自动发送一条MQ重试消息。这条消息可以被当前服务的任意一台服务器消费,并重新执行doSomething函数。

@Service
class Service {@MQRetrypublic void doSomething(String params1, String params2, List<String> params3) {//throw new RuntimeException(); 抛异常将重试//RetryContext.markRetryLater(); 标记为需要下次重试//int retryCount = RetryContext.getRetryCount(); 获取重试次数}}@Controller
class Controller {@Autowiredprivate Service service;service.doSomething("1", "2", Arrays.asList("3", "4"));
}

4 可选项

除此之外,我们还为开发人员提供了一些可选项,提供一些可配置的能力。

/*** 基于MQ的分布式重试组件*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MQRetry {/*** 最大重试次数,默认与上限为16次*/int maxAttempts() default 16;/*** 忽略的异常类列表,默认所有异常都重试*/Class<? extends Throwable>[] exclude() default {};/*** 需要重试的异常类列表,默认所有异常都重试*/Class<? extends Throwable>[] include() default {};/*** 出现异常时的处理函数, 格式: Bean名.方法名. 如: smsService.onError* 也可以只设置函数名, 不设置Bean名将执行本类的函数. 如: onError* 要求函数参数必须与重试函数的参数完全一致*/String errorHandler() default "";/*** true: 第一次调用时, 同步执行@MQRetry函数, 如果失败再使用MQ* false: 调用@MQRetry函数时, 只会发送MQ*/boolean firstSyncCall() default true;/*** 消费线程数,默认为20个*/int consumeThread() default 20;}

5 注意事项

  1. 适用于异步场景,重试函数不要设置返回值,函数的返回值将不会有任何的实际意义。

  2. At lease Once保证,重试函数需要
    保证幂等。

  3. 使用了AOP代理实现,因此,@Transactional的注意事项同样适用于@MQRetry,如
    this调用、private函数、final函数会导致重试失效。

  4. 如果重试函数需要增加参数,请在函数参数最后位置添加。历史消息消费时对应参数将填充为null。

6 总结

在计算机领域中,重试机制的重要性不言而喻。它通常分为两种模式:客户端模式服务端模式。客户端模式简单易用,但可靠性较低;而服务端模式虽然相对复杂,但能够提供更高的可靠性。

无论是客户端模式还是服务端模式,重试机制都是保障系统正常运行的重要一环。选择适合您业务需求的模式,并通过合理的配置项进行优化,将为您的系统带来更好的表现和用户体验。


关于作者

苑冲,转转架构部存储服务负责人,负责MQ、监控系统、KV存储、时序数据库、Redis、KMS秘钥管理等基础组件。喜欢深入思考问题,对探索新领域和解决问题充满热情。

转转研发中心及业界小伙伴们的技术学习交流平台,定期分享一线的实战经验及业界前沿的技术话题。
关注公众号「转转技术」(综合性)、「大转转FE」(专注于FE)、「转转QA」(专注于QA),更多干货实践,欢迎交流分享~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/659836.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

phpstudy安装并运行redis

对于一个菜鸟来说&#xff0c;任何一个小步骤都可能研究半天&#xff0c;比如“phpstudy安装并运行redis”这一问题&#xff0c;解决好后第一时间记录下来&#xff0c;方便日后查看&#xff0c;也为遇到同样困难的小伙伴提供个参考&#xff01; 一、phpstudy安装redis 1.打开…

打车代驾APP小程序开发功能有哪些?

随着移动互联网的快速发展&#xff0c;越来越多的人开始使用网约车服务。开发一个网约车、打车、叫车系统已经成为了市场的热门需求。 随着城市化进程的加速和人们出行方式的多样化&#xff0c;传统的公共交通方式已经无法满足人们的出行需求。同时&#xff0c;私家车拥有成本也…

【计算机视觉】万字长文详解:卷积神经网络

以下部分文字资料整合于网络&#xff0c;本文仅供自己学习用&#xff01; 一、计算机视觉概述 如果输入层和隐藏层和之前一样都是采用全连接网络&#xff0c;参数过多会导致过拟合问题&#xff0c;其次这么多的参数存储下来对计算机的内存要求也是很高的 解决这一问题&#x…

PostgreSql和Oracle的事务机制区别以及对程序的影响

前言 几年前IT信息产业的一些核心技术包括架构、产品以及生态都是国外制定&#xff0c;然而自从“遥遥领先”公司被制裁后&#xff0c;国家开始大力支持信息产业“新基建”&#xff0c;自2020年开始市场上涌现出了大量的国产化软件&#xff0c;就国产化数据库而言我所在的公司…

辽宁链家新房数据采集与可视化实现

摘 要 网络爬虫也叫做网络机器人&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取网络信息&#xff0c;进行数据信息的采集与整理的程序或者脚本。随着海量数据的出现&#xff0c;如何快速有效的获取到我们想要的数据成为难题。以房源信息为例&#xff0c;该文使用Pyt…

做虾皮Shopee想高效发货?EasyBoss ERP的这个功能你不能错过!

随着业务的发展&#xff0c;许多Shopee、Lazada卖家的店铺订单量逐渐增大、仓库商品的SKU也越来越多。在这种情况下&#xff0c;一些卖家会选择采用人海战术来提高拣货、发货的效率。效率提高的同时&#xff0c;也意味着企业的用人成本的增加&#xff01; 那么&#xff0c;如何…

Java进阶:集合进阶统计次数(双列集合HashMap 单列集合Set):实现景点被选择的次数统计

~ 景点次数统计 * 某个班级80名学生&#xff0c;现在需要组成秋游活动&#xff0c;* 班长提供了四个景点依次是&#xff08;A,B, C, D&#xff09;&#xff0c;* 每个学生只能选择一个景点&#xff0c;请统计出最终那个景点想去的人数最多*/代码示例&#xff1a; public static…

在windows和Linux中的安装 boost 以及 安装 muduo

二、安装boost boost官网&#xff1a;boost官网 我下载的boost版本&#xff1a; windows:boost_1_84_0.ziplinux:boost_1_84_0.tar.gz 2.1 在windows中安装boost和测试 &#xff08;1&#xff09;在windows中&#xff0c;解压这个压缩包boost_1_84_0.zip&#xff0c;路径为…

TP5手动集成GatewayWorker

重点&#xff1a;//由于是手动添加&#xff0c;因此需要注册命名空间&#xff0c;方便自动加载&#xff0c;具体代码路径以实际情况为准 \think\Loader::addNamespace([ Workerman > EXTEND_PATH . Workerman/workerman, GatewayWorker >EXTEND_PATH . Workerman/gate…

Compose | UI组件(六) | 选择框

文章目录 前言Checkbox 复选框的含义Checkbox 复选框的使用Switch 单选框的含义Switch 单选框的使用Slider 滑竿组件的含义Slider 滑竿组件的使用 总结 前言 随着移动端的技术不断更新迭代&#xff0c;Compose也运用的越来越广泛&#xff0c;很多人都开始学习Compose 本文主要…

python利用stomp连接activemq,已验证可以连接成功

安装使用到的库 输入如下命令安装stomp pip install stomp.py 发送请求 # -*-coding:utf-8-*-import stomp import time# 队列名(接收方可以根据管道名来选择接受那个队列数据) location_queue "123456" # 服务器ip,端口固定用这个 conn stomp.Connection([(127…

SQL中limit的用法

在SQL中&#xff0c;LIMIT是一个用于限制返回结果行数的关键词。它可用于在查询结果中指定返回的行数&#xff0c;从而可以用于分页查询或限制结果集大小。 LIMIT关键词有两种常用的语法格式&#xff1a; LIMIT offset, count&#xff1a;该语法用于指定返回结果的起始位置和…

【力扣经典面试题】189. 轮转数组

题目描述&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 …

免费的ppt网站分享

前言 相信大学生们深有体会&#xff0c;对于学校而言&#xff0c;好像是任何活动都需要我们做ppt&#xff0c;当你拿着自己辛苦做的ppt去展示现场的时候&#xff0c;你看到别人的ppt比你的还好&#xff0c;此时心情就是毙&#xff0c;当你知道人家不过是仅仅的1个小时不到就完成…

Java编程练习之类的封装

1.把一个Student类封装起来&#xff0c;模拟一个转校生转入新学校后为其制作学生信息的过程。运行结果如下&#xff1a; package zhtestdemo; import java.util.Scanner; import java.text.DecimalFormat; public class demo { //创建类&#xff0c;类名叫demo; private Stud…

使用阿里云的IDaaS实现知行之桥EDI系统的单点登录

&#xff0c;在开始测试之前&#xff0c;需要确定用哪个信息作为“登陆用户的ID字段”。 这个字段用来在完成SSO登陆之后&#xff0c;用哪个信息将阿里云IDaaS的用户和知行之桥EDI系统的用户做对应。这里我们使用了 phonenumber 这个自定义属性。需要在阿里云做如下配置&#x…

c++阶梯之引用与内联函数

1. 引用 1.1 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 语法 类型& 引用变量名(对象名) 引用实体; 示例 很显然&#xff0c;在下面这…

stm32--simulink开发之--timer的学习,硬件输入中断,触发事件

总体的参考链接是&#xff1a; https://ww2.mathworks.cn/help/ecoder/stmicroelectronicsstm32f4discovery/ref/timer.html 输入&#xff1a; 1&#xff0c;配置项&#xff1a;Enable frequency input 缩写&#xff1a;freq conunt 说明&#xff1a;“freq count — Frequency…

2024热门游泳耳机排行榜,精选四款游泳耳机品牌

在追求健康生活的今天&#xff0c;游泳成为了许多人健身的首选活动之一。而为了让游泳体验更加愉悦&#xff0c;选择一款适合的游泳耳机显得尤为重要。这不仅能够为游泳者提供动感的音乐&#xff0c;缓解游泳过程中的疲劳感&#xff0c;同时还有助于提高游泳效率。在市场上琳琅…

新手程序员的困境

我是一名使用 PHP 和 JS 进行编码的全栈开发人员。我已经工作一年了&#xff0c;在这之前我参加了一个新兵训练营。 我感觉自己遇到了瓶颈。在工作中学习 "的宽限期已经一去不复返了&#xff0c;现在我必须完成任务。但我不觉得自己是个优秀的程序员。我读过的大部分代码…