1. 错误思路
- 问题描述: 发送MQ超时导致事务回滚,但下游可能错误地感知到订单更新成功,而数据库状态未更新,造成数据不一致。
2. 基于 RocketMQ 的分布式事务
- 事务消息: RocketMQ提供的高级消息类型,支持分布式场景下消息生产与本地事务的一致性。
- 交互流程:
- 生产者发送消息至RocketMQ服务端。
- 服务端持久化消息后返回Ack,消息标记为"暂不能投递"(半事务消息)。
- 生产者执行本地事务逻辑。
- 根据本地事务结果,生产者提交二次确认(Commit或Rollback)。
- 服务端根据确认结果处理消息。
- 特殊情况处理:
- 网络问题或生产者重启,服务端发起消息回查。
- 生产者检查本地事务状态,再次提交确认。
- 交互流程:
3. 基于本地事务的一致性处理
- Spring框架: 实现MQ最终一致性的过程。
- 业务数据更新: 在事务保护下更新数据库。
- 创建本地消息记录: 创建包含将来发送至MQ的消息的记录。
- 业务事务提交: 确保数据更新和消息记录的原子性和一致性。
- 异步发送消息: 消息服务轮询未发送消息,发送至MQ并更新状态。
- 处理发送失败: 记录失败事件,根据配置重试。
- 消息消费者处理: 消费者处理消息,失败则重试或达到上限。
- 消息状态回查: 对失败或状态模糊的消息进行回查。
4. 基于 binlog 变动实现消息一致性
- Change Data Capture (CDC): 监听数据库binlog,实现跨数据库和服务的数据同步。
- 监听binlog: 使用工具如Debezium或Maxwell监听数据库变更。
- 变更事件捕获: 捕获数据库变更并生成事件。
- 变更事件发布: 发布事件到MQ系统。
- 处理MQ中的事件: 消费者读取并处理事件,实现数据一致性。
- 幂等性和错误处理: 消费者服务应具备处理重复消息和错误处理的能力。
注意事项
- 避免大量未决事务导致超时。
- 正确处理"进行中"的事务,保持Unknown状态。
- 设置合理的事务回查时间,避免事务提交延迟。
- 程序应能正确识别正在进行中的事务。
总结
提供了三种确保RocketMQ消息与数据库更新一致性的最佳实践,包括分布式事务、基于本地事务的一致性处理以及基于binlog变动的一致性实现。每种方法都有其适用场景和注意事项,以确保在分布式系统中实现数据的最终一致性。