这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天
前言
消息队列的前世今生
消息队列定义
消息队列(MQ),指保存消息的一个容器,本质是个队列。但这个队列呢,需要支持高吞吐,高并发,并且高可用。
业内对比
- Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
- RocketMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
- Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群
消息队列kafka
创建集群->新增topic->编写生产者逻辑->编写消费者逻辑
Topic:逻辑队列,不同业务创建不同Topic
Cluster:物理集群,每个集群可以建立多个不同Topic
Producer:生产者,负责将业务消息发送到Topic中
Consumer:消费者,负责消费Topic中消息
ConsumerGroup:消费者组,不同consumer消费进度互不干涉
Partition:分区,不同分区可并发处理
Offset:消息在partition内的相对位置,可以理解为唯一ID,在partition内严格递增
Replica:每个分区有多个副本。分为leader和follower,生产消费都与leader交互,follower与leader进行同步。具有选举机制
Broker:服务代理节点。对于 Kafka 而言,Broker 可以简单地看作一个独立的 Kafka 服务节点或 Kafka 服务实例。大多数情况下也可以将 Broker 看作一台 Kafka 服务器,前提是这台服务器上只部署了一个 Kafka 实例。一个或多个 Broker 组成了一个 Kafka 集群。一般而言, 我们更习惯使用首字母小写的 broker 来表示服务代理节点。
Broker
磁盘上采用顺序写提高写入效率,写之前使用批处理和数据压缩
偏移量索引文件:二分找到小于目标offset的最大索引位置
时间戳索引文件:在offset上层加一个二级索引,二分找到小于目标时间戳最大的索引位置
零拷贝:数据读到内存空间后通过sync field发送给网卡,再发送给消费者进程,避免了传统数据拷贝的三次拷贝
Consumer
使用coordinator(由broker承担)为consumer group中的consumer动态分配partition
coordinator制定consumer group中第一机器当leader来制定分配方案
使用心跳机制确认consumer是否离线
小结:哪些帮助kafka提高吞吐或者稳定性
Producer: 批量发送、数据压缩
Broker: 顺序写、消息索引、 零拷贝
Consumer: Rebalance
kafka存在的问题
数据复制问题,运维成本高
负载不均衡的场景解决方案复杂
没有自己的缓存,完全依赖Page Cache
Controller和Coordinator和Broker(意思是controller和coordinator选的同一个broker)在同一进程中,大量IO造成性能下降,一旦broker挂了,影响controller和coordinator
消息队列-BMQ
BMQ是什么
BMQ 兼容 Kafka 协议,支持存算分离,支持云原生消息队列。
- 新增 Proxy 层作为代理;
- Coordinator 和 Controller 可以独立部署;
- 底层新增 HDFS 用于存算分离。
BMQ 读写流程
在 BMQ 中,客户端写入前会选择一定数量的 DataNode,这个数量一般是副本数,然后将一个文件写入到这几个节点上,切换到下一个 segment 之后,又会重新选择节点进行写入。这样对于单个副本的所有 segment,会随机写入到集群当中。
对于写入逻辑,BMQ 还有一个状态机的机制(Broker-Partition),用来保证不会出现同一个分片在两个 Broker 上同时启动的情况,另外也能保证一个分片的正常运行。
BMQ 的具体写入过程:
- CRC 数据校验参数是否合法;
- 校验完成后,会把数据放入 Buffer 中;
- 通过一个异步的 Write 线程将数据最终写入到底层的存储系统。