本地事务表+普通mq实现最终一致性

本文详细描述了一套业务处理流程,涉及本地数据事务、消息队列通信、幂等性保障及错误重试机制。特别强调了在处理异常情况时,如何确保消息一致性,尤其是在消息消费和确认阶段的挑战与解决方案。

主要流程步骤

  1. 1,本地业务数据处理
  2. 2.1本地消息数据处理(1+2.1需要在同一个事务),要么成功,要么失败
  3. 2.2 发送消息给mq
  4. 3,消息投递到Consumer消费端
  5. 4,消费端服务处理业务数据
  6. 5,业务端业务数据消费成功,反馈给comsumer
  7. 6,comsumer返回ack非消息中间件MQ
  8. 7,发送ack消息,更新本地消息表,表示已经完成或者消费成功,修改消息状态
  9. 8,恢复系统定时轮询消息表,找出没有消费成功ack的消息
  10. 9,重新发送没有消费成功的消息

bad case

  1. 如果1,2.1出错,本地事务回滚,业务数据,消息都没有变化,啥都没做
  2. 如果2.2 发送失败,定时任务系统会查询消息表,依据状态重新发送
  3. 3-7步骤出错,也没法ack本地消息表,都会重新发送消息
  4. 既然会重新发送消息,那消费端就要考虑重复消息的问题,也就是幂等,尤其是在7.1/7.2确认过程中失败了,一旦重复发送,如果不幂等,业务逻辑就会重复执行,如果是减库存或者支付场景,就会出现多加或者多减数据,出现不一致

<think>好的,我需要回答用户关于MQ务消息的机制和实现方式的问题。首先,我需要回忆之前提供的引用内容,看看有哪些相关信息可以整合。 用户提到了RocketMQ务消息流程,所以我要重点参考引用中的内容。根据引用[1],务消息的流程分为几个步骤,包括发送半消息、执行本地务、根据结果提交或回滚。引用[4]详细说明了三步流程,这可以作为结构的基础。 然后,机制方面需要解释如何保证务的一致性。这里引用[2]提到分布式务中MQ的作用,将大务分解为小务,结合两阶段提交(2PC)可能相关。不过RocketMQ务消息实现可能不是标准的2PC,而是类似但优化的机制。需要确认这一点,根据引用[3]和[4],RocketMQ使用了半消息和务状态回查的机制,确保本地务和消息发送的一致性实现方式方面,引用[3]指出需要注册TransactionListener,并实现执行本地务和回查的逻辑。Producer发送半消息后自动触发本地务执行,Broker在未收到确认时会发起回查。这部分需要详细说明。 可能还需要比较其他MQ务消息实现,但用户可能主要关注RocketMQ,所以重点放在它上面。此外,要确保使用正确的LaTeX格式,如独立公式用$$,行内用$,比如在提到务状态时可能有数学模型,但如果没有具体公式,可能不需要数学表达,但要注意用户的指令。 最后,生成相关问题时要涵盖机制、实现细节、与其他技术的对比、性能优化和实际应用等。需要检查引用是否覆盖了这些方面,并确保问题相关且合理。</think>### MQ务消息机制与实现原理解析 #### 一、务消息核心机制 MQ务消息通过**两阶段提交思想**实现分布式一致性,核心目标是保证**本地务执行与消息投递的原子性**。以RocketMQ为例,其机制包含以下关键步骤: 1. **半消息(Half Message)阶段** 生产者向Broker发送半消息(标记为`TRANSACTION_PREPARED`状态),此时消息对消费者不可见[^4]。半消息用于记录务执行前的消息状态,类似数据库务的预提交。 2. **本地务执行** 生产者执行本地务(如数据库操作),并根据结果向Broker发送**提交(COMMIT)**或**回滚(ROLLBACK)**指令。 若未收到明确指令,Broker会触发**务状态回查(Transaction Check)**机制[^3]。 3. **务状态确认** - 若本地务成功,Broker将半消息转为普通消息(状态`COMMIT_MESSAGE`),消费者可消费 - 若本地务失败或超时未确认,Broker删除半消息(状态`ROLLBACK_MESSAGE`)[^4] $$状态转换公式:TRANSACTION\_PREPARED \xrightarrow{COMMIT} COMMIT\_MESSAGE \quad \xrightarrow{ROLLBACK} \varnothing$$ #### 二、实现方式与关键技术 1. **务监听器(TransactionListener)** 开发者需实现两个核心方法: - `executeLocalTransaction`:执行本地务并返回执行状态 - `checkLocalTransaction`:处理Broker的务回查请求[^3] ```java // RocketMQ务消息生产者示例 TransactionMQProducer producer = new TransactionMQProducer("group"); producer.setTransactionListener(new TransactionListener() { @Override public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { return doBusiness() ? LocalTransactionState.COMMIT_MESSAGE : LocalTransactionState.ROLLBACK_MESSAGE; } @Override public LocalTransactionState checkLocalTransaction(MessageExt msg) { return checkTransactionStatus(msg.getTransactionId()); } }); ``` 2. **务回查机制** Broker通过定时任务扫描未完成务,若超时未确认(默认60秒),则回调生产者的`checkLocalTransaction`方法[^4]。该机制解决了网络分区或生产者宕机导致的状态不一致问题。 3. **消息存储优化** - 半消息存储于特殊Topic(`RMQ_SYS_TRANS_HALF_TOPIC`) - 提交后转移至目标Topic,通过写时复制(Copy-On-Write)保证原子性[^1] #### 三、与其他方案的对比 | 方案 | 一致性保障 | 性能消耗 | 适用场景 | |---------------|------------|----------|----------------------| | MQ务消息 | 最终一致 | 中等 | 跨服务异步务 | | 2PC协议 | 强一致 | 高 | 同构数据库场景 | | TCC模式 | 最终一致 | 高 | 复杂业务补偿场景 | #### 四、典型应用场景 1. **订单支付场景** 用户支付成功后,异步通知库存系统扣减库存[^2] 2. **跨系统数据同步** 保证数据库操作与ES索引更新的最终一致性 3. **金融转账场景** 主账户扣款与子账户入账的异步解耦
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值