这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天
消息队列原理 | 青训营笔记
1. 消息队列
消息队列(MQ),指保存消息的一个容器,本质是个队列。但这个队列需要支持高吞吐,高并发,并且高可用。
1.1 常用消息队列
- Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
- RocketMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
- Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群
2. Kafka
-
使用流程:创建集群——新增Topic——编写生产者逻辑——编写消费者逻辑
-
基本概念:
- Topic:逻辑队列,不同Topic可以建立不同的Topic
- Cluster:物理集群,每个集群中可以建立多个不同的Topic
- Producer:生产者,负责将业务消息发送到Topic中
- Consumer:消费者,负责消费Topic中的消息
- ConsumerGroup:消费者组,不同组Consumer消费进度互不干涉
- Offset:消息在partition内的相对位置信息,可以理解为唯一ID,在partition内部严格递增
- Replica:每个分片有多个Replica,Leader Replica将会从ISR(In-Sync Replicas)中选出
- ZooKeeper:负责存储集群元信息,包括分区分配信息等
-
Kafka消息流程:Producer——Broker——Consumer
- Producer
- 批量发送,减少IO次数,从而加强发送能力
- 数据压缩,减少消息大小,目前支持Snappy、Gzip、LZ4、ZSTD压缩算法
- Broker
- 磁盘结构:移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此顺序写可以减少寻道的时间成本
- 顺序写,提高写入效率
- 消息抓取:Consumer通过发送FetchRequest请求消息数据,Broker会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer
- Consumer
- Partition在Consumer Group中的分配方案
- 手动分配(Low Level):通过手动进行分配,哪一个Consumer消费哪一个Partition完全由业务决定。缺点是不能自动容灾、会导致机器启停问题。优点是比较快。
- 自动分配(High Level):使用Coordinator自动分配。优点是不会存在机器启停问题,分配稳定。
- Partition在Consumer Group中的分配方案
- Producer
-
Kafka缺点
- 运维成本高
- 对于负载不均衡的场景,解决方案复杂
- 没有自己的缓存,完全依赖Page Cache
- Controller和Coordinator和Broker在同一进程中,大量IO会造成其性能下降
3. BMQ
BMQ兼容Kafka协议,存算分离,支持云原生消息队列。
BMQ与Kafka的运维操作对比:
| 具体操作 | Kafka | BMQ |
|---|---|---|
| 重启 | 需要数据复制,分钟级重启 | 重启后可直接对外服务,秒级完成 |
| 替换 | 需要数据复制,分钟级替换,甚至天级别 | 替换后可直接对外服务,秒级完成 |
| 扩容 | 需要数据复制,分钟级扩容,甚至天级别 | 扩容后可直接对外服务,秒级完成 |
| 缩容 | 需要数据复制,分钟级缩容,甚至天级别 | 缩容后可直接对外服务,秒级完成 |
4. RocketMQ
RocketMQ的高级特性:事务消息、重试和死信队列,延迟队列