【方案】业务中MQ的使用方案分析

[方案系列文章说明]: 该类型的文章是我在使用和学习中认为不错的解决办法,当然会有更好的方案,也一定会有, 所以文章具有一定的局限性, 请结合自己的思考辩证的看.

业务中使用MQ遇到的常见问题,进行分析并给出一个合理的解决方案.

常见使用方式及问题

场景一

1
2
3
4
S1: open Transaction
S2: 处理业务
S3: 发送MQ消息
S4: commit Transaction

问题
1, 当S3失败,大量阻塞业务,可能造成整个业务线雪崩
2, 当S4失败,造成业务数据回滚, MQ消息发送成功,产生异常数据

场景二

1
2
3
4
S1: open Transaction
S2: 处理业务
S3: commit Transaction
S4: 发送MQ消息

问题
1,当S4失败, 造成MQ未正常发送,产生消费业务线产生异常数据

针对上面两种场景进行优化

场景三

1
2
3
4
5
6
S1: open Transaction
S2: 处理业务
S3: 记录MQ消息(待发送)
S4: commit Transaction
S5: 触发MQ发送
S6: 定时检测MQ发送

解决了不在一个事务中产生的不一致问题
问题
1, MQ消息落库与业务需要事务原子操作(通常考虑同一个库),不适合分布式场景

针对分布式场景继续优化

场景四

1
2
3
4
5
6
S1: 调用MQ消息落库服务(返回ID)
S2: open Transaction
S3: 处理业务
S4: commit Transaction
S5: 调用MQ消息发送服务(根据ID)
S6: 定时任务处理异常消息状态(业务提供检查逻辑)+发送

解决了
1,将MQ落库拆分成分布式服务,解决高可用性,避免每个业务库建立MQ表
2,定时任务+业务检查逻辑, 解决了MQ记录与业务逻辑不一致的情景
3,以服务间调用的形式发送MQ,提高了MQ服务的扩展性
问题
1, 增加了业务处理的复杂度
2, 增加了MQ使用上的复杂度

补充

以上没有分析消费者如何保证消息的处理,这里直接给出最终方案

1
2
3
4
5
6
S1: 接收MQ消息,调用MQ消息落库服务,更新发送消息接收状态
S2: open Transaction
S3: 处理业务
S4: commit Transaction
S5: 调用MQ接收消息状态更新服务
S6: 定时任务检测消费失败的消息

说明
S1: 消费者接收消息后落库,保证数据持久性
S3: 异常, 由S6定时任务检测并处理,需要消费逻辑支持幂等
S5: 异常, 由S6定时任务检测并处理,需要消费逻辑支持幂等

实践

  • 对业务一致性,时效性要求不是特别高,可结合人工介入,采用场景三的方案降低开发复杂度
  • MQ定制化开发高的公司,可以结合MQ的特性配合业务,支撑数据的持久化,和重发机制