RocketMQ的事务消息

1. 事务消息整体流程

事务消息是 RocketMQ 提供的分布式事务解决方案,用于保证生产者本地事务与消息发送的最终一致性。核心流程如下:

  1. 发送半消息:生产者先发送一条 "预备消息" 到 Broker,此时消息对消费者不可见。
  1. 执行本地事务:Broker 确认收到半消息后,生产者执行本地业务逻辑(如数据库操作)。
  1. 提交或回滚:根据本地事务的执行结果(成功 / 失败),生产者向 Broker 发送提交或回滚指令。
  1. 状态回查(关键机制):若生产者未及时返回状态(如服务宕机),Broker 会定时回查事务状态。

2. 核心方法解析

executeLocalTransaction方法

java

typescript 复制代码
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
    try {
        // 1. 解析消息获取业务参数
        String projectId = parseProjectId(msg);
        String enterpriseId = parseEnterpriseId(msg);
        
        // 2. 执行本地数据库操作(带事务)
        // 例如:更新投标状态为"处理中"
        boolean success = bidService.updateBidStatus(projectId, enterpriseId, "PROCESSING");
        
        // 3. 根据本地事务结果返回状态
        return success ? LocalTransactionState.COMMIT_MESSAGE 
                       : LocalTransactionState.ROLLBACK_MESSAGE;
    } catch (Exception e) {
        // 异常时返回 UNKNOW,触发后续回查
        return LocalTransactionState.UNKNOW;
    }
}

Java

  • 作用:在发送半消息成功后,执行本地事务并返回状态。
  • 返回值:
  • COMMIT_MESSAGE:提交事务,消息对消费者可见。
  • ROLLBACK_MESSAGE:回滚事务,消息被丢弃。
  • UNKNOW:状态未知,触发 Broker 的回查机制。

checkLocalTransaction方法

java

typescript 复制代码
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
    // 查询数据库确认投标状态
    boolean isCommitted = getBidStatusFromDB(msg);
    return isCommitted ? LocalTransactionState.COMMIT_MESSAGE 
                       : LocalTransactionState.ROLLBACK_MESSAGE;
}


// 示例:从数据库查询投标状态
private boolean getBidStatusFromDB(MessageExt msg) {
    String projectId = parseProjectId(msg);
    String enterpriseId = parseEnterpriseId(msg);
    // 查询数据库,例如:
    // Bid bid = bidRepository.findByProjectIdAndEnterpriseId(projectId, enterpriseId);
    // return bid.getStatus().equals("SUCCESS");
    // 实际实现需根据业务表结构调整
}

Java

  • 作用:处理 Broker 的状态回查请求,通过查询数据库确认本地事务的最终状态。
  • 触发条件:当 Broker 长时间未收到生产者的提交 / 回滚指令(如生产者服务宕机),会按配置的间隔(默认 60s)调用此方法。

3. 事务回查机制的关键点

  1. 服务宕机场景:
  • 若生产者在执行本地事务后、返回状态前宕机,Broker 无法感知事务结果。
  • 此时 Broker 会定时回查,通过checkLocalTransaction读取数据库真实状态。
  1. 幂等性保障:
  • 回查可能被多次调用(如网络波动),因此checkLocalTransaction必须是幂等的。
  • 通常通过数据库唯一索引或状态字段(如status)保证重复查询结果一致。
  1. 数据库一致性:
  • 本地事务需保证数据库操作的原子性(如使用数据库事务)。
  • 示例中,若更新投标状态失败,应返回ROLLBACK_MESSAGE,避免消息被消费。

4. 实际应用建议

  1. 状态设计:
  • 在业务表中增加状态字段(如bid_status),记录事务处理阶段(如INIT、PROCESSING、SUCCESS、FAILED)。
  1. 日志记录:
  • 在关键步骤添加日志(如事务执行前后),便于问题排查。
  1. 回查配置优化:
  • 通过TransactionMQProducer.setCheckThreadPool调整回查线程池大小。
  • 通过TransactionMQProducer.setCheckRequestHoldMax调整回查请求的最大等待时间。

总结

事务回查机制是 RocketMQ 事务消息的核心保障,通过定时检查数据库状态,解决了服务故障导致的状态丢失问题,确保分布式事务的最终一致性。

相关推荐
大鸡腿同学7 小时前
手心向上,手心向下
后端
CCblandy8 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
凤山老林9 小时前
Spring Boot 集成 Sa-Token 实现高可用权限认证:登录鉴权、动态路由权限与接口防重放实战
spring boot·后端·sa-token·bootstrap
Bazingga10 小时前
一次推理的完整旅程:ReAct推理深度解析
后端
姜鱼问生11 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构
颜酱11 小时前
一栋商业大厦,讲清 InnoDB 的表空间、段、区和页
后端·mysql
码事漫谈11 小时前
1956 亿行数据该怎么存:金仓时序数据库的三个实测
后端
Wx-bishekaifayuan11 小时前
springboot桂味美食分享系统40540-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
彭亚川Allen11 小时前
从零手搓 RAG 之检索全流程,给大模型接上自己的知识库
前端·后端·ai编程
IT_陈寒11 小时前
别让Java字符串拼接偷偷吃掉你的内存
前端·人工智能·后端