消息队列中的几个基本概念
消息队列通常有生产者(Producer)、消费者(Consumer)和Broken三部分组成。其中生产者负责发送消息到Broken,Broken接收到消息后,投递给Consumer进行消费。
Consumer
consumer在消费消息时,通常有两种模式:推模式和拉模式。推模式指的是由Broken向Consumer推送消息,拉模式指的是由Consumer定时向Broken定时获取消息。在实际生产中,更多使用的是推这种模式。
Broken
Broken用来接收并存储消息,然后对消息进行投递。
消息队列特性
消息过滤
消息支持根据设置的属性进行过滤,这样可以有效减少Broken投递的消息数量和网络带宽。
事务消息
事务消息是类似XA的两阶段提交消息。实现原理如下:
1. ⽣产者先发送⼀条半事务消息到MQ
2. MQ收到消息后返回ack确认
3. ⽣产者开始执⾏本地事务
4. 如果事务执⾏成功发送commit到MQ,失败发送rollback
5. 如果MQ⻓时间未收到⽣产者的⼆次确认commit或者rollback,MQ对⽣产者发起消息回查
6. ⽣产者查询事务执⾏最终状态,如果本地事务执行成功,返回true,否则返回false;
7. 根据查询事务状态再次提交⼆次确认
消息可靠性
RocketMQ支持消息的高可靠,影响消息可靠性的几种情况:
- Broker非正常关闭
- Broker异常Crash
- OS Crash
- 机器掉电,但是能立即恢复供电情况
- 机器无法开机(可能是cpu、主板、内存等关键设备损坏)
- 磁盘设备损坏
1)、2)、3)、4)这4种属于硬件资源可立即恢复的情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。
5)、6)属于单点故障,且无法恢复,一旦发生,在此单点上的消息全部丢失。RocketMQ在这两种情况下,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合。
一般情况下,考虑到性能,生产上会选择异步刷盘,主从异步复制的方式。如果出现消息没有投递,可以通过核对的方式发现并重新同步消息。
流量控制
消息实践
消息重复投递的问题
- Broken无法保证消息不重复投递,需要由消费端做幂等处理;
RocketMQ为什么速度快
- 顺序写入;
- 异步刷盘;
- Page Cache;
消息堆积的问题
如果是因为消息量级太大而导致Consumer处理消息处理不过来,可以考虑以下几个办法:
- 订阅消息时,对消息进行过滤;
- 系统扩容,通过增加机器的容量或者DB的容量,增加系统的吞吐量;
- 通过多线程提升TPS;
- 消息异步化处理;
如果是因为Consumer出现问题导致消息积压,可以有以下几种处理方式:
- 消息异步化处理;
- 暂时取消订阅关系,待问题修复后或者系统恢复正常后重新订阅。在这个过程中产生的脏数据,人工补齐;
https://github.com/apache/rocketmq/blob/master/docs/cn/concept.md