消息队列基础
消息队列本质是将同步处理转成异步处理
消息队列的基本要求
不丢消息
高可用
高性能
消息队列名称 |
RabbitMQ |
RocketMQ |
Kafka |
优点 |
轻量级 |
低延迟和高稳定性 |
1. 与周边生态系统的兼容性最好 2. 基于异步批量设计的异步收发性能最好 |
缺点 |
1. 消息大量堆积时性能大幅下降 2. 使用的Erlang语言比较冷门 |
与周边生态系统的兼容性没有Kafka好 |
异步批量设计带来同步收发消息的响应时延高 |
适用场景 |
不对功能和性能有高要求,开箱即用 |
在线业务,例如交易系统 |
处理海量消息
|
主题和订阅
实现每个消费者都能收到全量消息
RocketMQ消费模型
每个主题包含多个队列,通过多个队列来实现多实例并行生产和消费。RocketMQ只在队列上保证消息的有序性,主题上无法保证消息顺序。同一个消费组内的消费者是竞争关系,不同消费组都会消费全量消息。消费者组数量和队列数没有关系。
Kafka也是如此。
利用事务消息来实现分布式事务
事务消息适用的场景是异步更新数据,对数据实时性要求不高。
如果在第4步提交事务消息到MQ时失败了怎么办?
Kafka的解决方案是直接抛出异常,在业务代码中反复重试提交,直到提交成功,或者删除之前创建的订单来补偿。
支撑这个RocketMQ事务反查机制,业务代码提供反查本地事务状态的接口,告知RocketMQ本地事务是否成功。
先开启本地事务,然后创建订单,订单创建成功后再发消息,根据发消息是否成功来决定
提交还是回滚本地事务。
如果本地事务提交失败,那么已经发出去的消息是无法撤回的,会导致数据不一致。
检测消息丢失的简单方法
利用消息队列的有序性来验证是否有消息丢失。
Producer端给每个发出的消息附加一个连续递增的序号,Consumer端检查这个序号的连续性。如果没有消息丢失,Consumer收到消息的序号必然是连续递增的,或者说收到的消息,其中的序号必然是上一条消息的序号 +1。如果检测到序号不连续,那就是丢消息了。还可以通过缺失的序号来确定丢失的是哪条消息,方便进一步排查原因。
参考资料