跳至主要內容

消息队列

HeChuangJun约 1261 字大约 4 分钟

什么是消息队列?使用原因?优缺点?协议?消费语义?

mq:消息队列是一种先进先出的数据结构.

解耦:假设A系统要发送数据到B,C,D系统,如果E系统需要数据然后,D系统不需要了,此时A系统需要维护下游系统的调用,耦合性太高,引入消息队列后可以减少A系统维护成本
异步:同步很花费并且业务时效性不大的操作,可以使用异步来提升效果,比如发送微信通知
削峰、限流:解决高并发情况

系统可用性降低、系统复杂度提高、一致性问题

AMQP、MQTT、STOMP、XMPP协议

消息至多被消费一次(At most once):消息可能会丢失,但绝不重传。
消息至少被消费一次(At least once):消息可以重传,但绝不丢失。
消息仅被消费一次(Exactly once):每一条消息只被传递一次。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

mq.png
mq.png

中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。
如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。
RabbitMQ延时最低,消息可靠性高,高可用,但扩展性较差。

如何保证消息的不被重复消费/幂等性?消息丢失/可靠性传输?顺序性?消息积压如何解决?

框架层统一封装:由 Producer 生成唯一标识。使用关系型数据库,增加一个排重表,使用消息编号作为唯一主键。需要让插入记录和业务逻辑在同一个事务
业务层实现:先查询数据库,判断数据是否已经被更新过。如果是,则直接返回消费完成,否则执行消费。

rabbitmq如何防止消息丢失?可靠性传输?

rocketmq如何防止消息丢失?可靠性传输?

rabbitmq顺序消息

rocketmq顺序消息

临时紧急扩容,具体操作步骤和思路如下:
先修复consumer的问题,确保其恢复消费速度
新建一个topic,partition是原来的10倍,临时建立好原先10倍或者20倍的queue数量
然后写一个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的10倍数量的queue
接着临时征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的数据
这种做法相当于是临时将queue资源和consumer资源扩大10倍,以正常的10倍速度来消费数据
等快速消费完积压数据之后,得恢复原先部署架构,重新用原先的consumer机器来消费消息

如何保证消息队列的高可用?

rabbitmq高可用

rocketmq高可用

为什么kafka最高吞吐量

kafka采用顺序读写磁盘,写时分文件顺序写,读时按offset顺序读
Kafka利用了操作系统本身的Page Cache而不是JVM空间内存
Kafka 的生产和消费两个过程都使用了零拷贝(zero copy):
网络数据持久化到磁盘(Producer 到 Broker使用了mmap)
磁盘文件通过网络发送(Broker 到 Consumer使用了sendfile+DMA采集)
数据压缩
Kafka使用了批量压缩,即将多个消息一起压缩而不是单个消息压缩。(如果每个消息都压缩,压缩率相对较低。)
Kafka允许使用递归的消息集合,批量的消息可通过压缩的形式传输并且在日志中也可保持压缩格式,直到被消费者解压缩
Kafka支持多种压缩协议,包括Gzip、Snappy、LZ4
批量传输
在向Kafka发送数据时,可以启用批次发送,这样可以避免在网络上频繁传输单个消息带来的延迟和带宽开销。假设网络带宽为10MB/S,一次性传输10MB的消息比传输1KB的消息10000万次显然要快得多。
并行
由于不同 Partition 可位于不同机器,因此可以充分利用集群优势,实现机器间的并行处理。
由于 Partition 在物理上对应一个文件夹,即使多个 Partition 位于同一个节点,也可通过配置让同一节点上的不同 Partition 置于不同的磁盘上,从而实现磁盘间的并行处理,充分发挥多磁盘的优势。