MQ
MQ总览
作用
异步,削峰,解耦,大数据量分批
引入复杂度
重复消费,中间数据不一致,降低可用性,复杂度提高
防止重复消费
- 幂等
- redis分布式锁
- 分区顺序MQ
- mysql唯一键
消息积压
原因:生产速率大于消费速率
- 用户流量突然增大
- 广播消息,服务器扩容10倍以上
- 消费者服务问题
- bug
- 数据库,下游服务网络问题
解决消息积压:
增加消费能力
- 直接增加消费者数量;增加消费者服务器、多线程消费
- 单个消费改为批量消费
- 提前写消息积压时的特殊消费逻辑。
- 将Topic分发到多个临时Topic,新的多台consumer消费临时Topic
降低生产速率
- 限流
进一步对MQ削峰填谷
白天丢弃消息,晚上通过日志找到消息补发到MQ中
避免消息积压
- 监控和告警,监控消息队列的消息数量、延迟等指标
示例
- 问题:部分MQ消费速度为0,消息积压
- 原因:修改饮品菜谱后,广播清除所有服务器的JVM本地缓存,节日扩容引起了单个MQ消费速率超高,占用了所有消费限制。生产+消费一共8万。
- 解决
临时:缩容
后期:取消广播,本地缓存时间降低到2分钟,接受2分钟的数据延迟
数据一致性
定时任务比较成功消费MQ的数据是否正确
RocketMQ
功能
异步消息
同步消息
顺序消息
定时消息
事务消息
修改状态原理:
- 记录消息offset(相当于地址)
- 第一阶段提交
- 第二阶段根据offset查询到消息
- 修改状态
offset实现查询消息的问题:通过offset修改数据,会产生很多脏页
消息重放
支持指定消息,指定时间段重放
消息堆积
可堆积亿条消息
消息防丢失
消息可靠性
- broker关闭、异常、操作系统异常后恢复,可保证消息不丢失。(刷盘方式是异步时丢失极少量数据)
- 机器无法开机、磁盘损坏,通过异步复制,可保证99%的消息不丢失;同步双写可避免单点问题,但很影响性能。
- 消息消费后,才会返回ACK,不返回ACK,消息会重新投递,消费一定次数后,会被投递到死信队列。
原理
物理结构

逻辑结构

消息数据结构
消费方式
push(推,长轮询pull)
优点:实时性高,不用自己维护消费速率
缺点:消息量大的时候,消费者压力大
拉去消息步骤
消费者启动时创建一个后台线程,处理拉消息
判断有没有过多消息未消费,
有的话,间隔一定时间再去执行拉消息步骤
没有的话,直接向MQ发送拉去消息的请求。
- 有消息,立刻返回
- 没有消息,hold住请求,有消息时再放回
获取消息后,找用户自定义的消息处理逻辑,并执行;同时再次拉取消息。
消费者控制消费压力
- 基于未消费消息的数量
- 基于未消费消息内存占用
pull
优点:消费速率灵活可控
缺点:实时性差,需要主动维护消费速率
各类MQ区别
| RocketMQ | RabbitMQ | Kafaka | |
|---|---|---|---|
| 开发语言 | Java | Erlang | Java |
| 单机性能 | 10万 | 万 | 10万 |
| 延迟 | ms | us | ms |
| 可用性 | 普通集群(主从架构),镜像集群 | ||
| 功能性 | 功能完备,扩展性强 | 相比RocketMQ缺事务、顺序消息。基于Erlang开发,并发能力强,延时低,管理界面丰富 |