消息队列中的一些基本概念
1. 分布式事务
- 订单系统在消息队列上开启一个事务
- 然后订单系统给消息服务器发送一个 半消息
- 这个半消息不是说消息内容不完整,它包含的内容就是完整的消息内容,半消息和普通 消息的唯一区别是,在事务提交之前,对于消费者来说,这个消息是不可见的
- 半消息发送成功后,订单系统就可以执行本地事务
如果 半消息 提交失败,不同队列会有不同处理方式
- Kafka 的解决方案比较简单粗暴,直接抛出异常,让用户自行处理。我们可以在业务代 码中反复重试提交,直到提交成功,或者删除之前创建的订单进行补偿
RocketMQ 中的事务实现中,增加了事务反查的机制来解决事务消息提交失败的问题
为了支撑这个事务反查机制,我们的业务代码需要实现一个反查本地事务状态的接口, 告知 RocketMQ 本地事务是成功还是失败
2. 重复消费
在 MQTT 协议中,给出了三种传递消息时能够提供的服务质量标准,这三种服务质量从低到 高依次是:
- At most once: 至多一次。消息在传递时,最多会被送达一次。换一个说法就是,没什 么消息可靠性保证,允许丢消息。一般都是一些对消息可靠性要求不太高的监控场景使 用,比如每分钟上报一次机房温度数据,可以接受数据少量丢失。
- At least once: 至少一次。消息在传递时,至少会被送达一次。也就是说,不允许丢消 息,但是允许有少量重复消息出现。
- Exactly once:恰好一次。消息在传递时,只会被送达一次,不允许丢失也不允许重复, 这个是最高的等级。
用幂等性解决重复消息问题
- 利用数据库的唯一约束实现幂等
- 为更新的数据设置前置条件
- 记录并检查操作
3. 消息积压
- 优化消息收发性能,预防消息积压的方法有两种,
- 增加批量或者是增加并发,在发送端这两种方法都可以使用
- 在消费端需要注意的是,增加并发需要同步扩容分区数量,否则是起不到效果的
- 对于系统发生消息积压的情况,需要先解决积压,再分析原因
- 快速解决积压的方法就是通过水平扩容增加 Consumer 的实例数量