消息队列MQ
这是我参与「第五届青训营」伴学笔记创作活动的第 13 天
消息队列(MQ):指保存消息的一个容器,本质是一个队列。但是该队列需要支持高吞吐、高并发、高可用
发展
- 业界MQ对比
Kafka
使用步骤
基本概念
- Topic:逻辑队列,不同Topic可以建立不同的Topic
- Cluster:物理集群,每个集群中可以建立多个不同Topic
- Producer:生产者,负责将业务消息发送到Topic中
- Consumer:消费者,负责消费Topic中的消息
- ConsumerGroup:消费者组,不同组Consumer消费进度互不干涉
- Partition:通常topic会有多个分片,不同分片之间消息是可以并发来处理的,这样提高单个Topic的吞吐
- Offset:消息在 partition内的相对位置信息,可以理解为唯一ID,在 partition内部严格递增。
- 每个分片有多个 Replica, Leader Replica将会从 ISR中选出。
- Replica:分片的副本,分布在不同的机器上,可用来容灾,Leader对外服务,follwer异步去拉取leader的数据进行一个同步,如果leader挂掉了,可以将follower提升成leader再对外进行服务
- lSR:意思是同步中的副本,对于Follower来说,始终和leader是有一定差距的,但当这个差距比较小的时候,我们就可以将这个follower副本加入到ISR中,不在ISR中的副本是不被允许提升为Leader
数据复制
架构
一条信息的存储过程
数据压缩
消息文件结构
磁盘结构
移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此顺序写可以减少寻道所带来的时间成本。
查找消息
二分查找
读取数据
零拷贝
- Consumer从Broker中读取数据,通过sendfile的方式,将磁盘读到os内核缓冲区后,直接转到socket buffer进行网络发送 Producer生产的数据持久化到broker,采用mmap文件映射,实现顺序的快速写入
消息接收端的消费
-
手动分配
- 如果我们的Consumer3挂掉了,我们的7,8分片是不是就停止消费了。又或者,如果我们新增了一台Consumer4,那是不是又需要停掉整个集群,重新修改配置再上线,保证Consumer4也可以消费数据,其实上面两个问题,有时候对于线上业务来说是致命的。
- 如果我们的Consumer3挂掉了,我们的7,8分片是不是就停止消费了。又或者,如果我们新增了一台Consumer4,那是不是又需要停掉整个集群,重新修改配置再上线,保证Consumer4也可以消费数据,其实上面两个问题,有时候对于线上业务来说是致命的。
-
自动分配
- 在我们的Broker集群中,对于不同的Consumer Group来讲,都会选取一台Broker当做Coordinator,而Coordinator的作用就是帮助Consumer Group进行分片的分配,也叫做分片的rebalance,使用这种方式,如果ConsumerGroup中有发生宕机,或者有新的Consumer加入,整个partition和Consumer都会重新进行分配来达到一个稳定的消费状态
Rebalance
小总结
数据复制问题
通过前面的介绍我们可以知道,对于Kafka来说,每一个Broker上都有不同topic分区的不同副本,而每一个副本,会将其数据存储到该Kafka节点上面,对于不同的节点之间,通过副本直接的数据复制,来保证数据的最终一致性,与集群的高可用。
重启操作
回切的必要:
在众多 leader 的转移过程中,就会产生 leader 不均衡现象,可能一小部分 broker 上有大量的 leader,影响了整个集群的性能,所以就需要把 leader 调整会最初的 broker 上,这就需要 preferred leader 选举。
替换、扩容、所容
本质还是数据复制问题
负载不均衡
但我们的数据复制又会引起Broker1的IO升高,所以问题就变成了,我为了去解决IO升高,但解决问题的过程又会带来更高的IO,所以就需要权衡IO设计出一个极其复杂的负载均衡策略
BMQ
- 兼容Kafka协议,存算分离,云原生消息队列
架构图
文件结构
对于Kafka分片数据的写入,是通过先在Leader上面写好文件,然后同步到Follower上,所以对于同一个副本的所有Segment都在同一台机器上面。就会存在之前我们所说到的单分片过大导致负载不均衡的问题,但在BMQ集群中,因为对于单个副本来讲,是随机分配到不同的节点上面的,因此不会存在Kafka的负载不均问题
Partition状态机
写文件流程
- Thread的具体逻辑,首先会将Buffer中的数据取出来,调用底层写入逻辑,在一定的时间周期上去flush,flush完成后开始建立Index,也就是offset和timestamp对于消息具体位置的映射关系
Index建立好以后,会save一次checkpoint,也就表示,checkpoint后的数据是可以被消费的
- 我们想一下,如果没有checkpoint的情况下会发生什么问题,如果flush完成之后宕机,index还没有建立,这个数据是不应该被消费的
Proxy
多机房部署
- 防止机房级故障带来的影响
泳道消息
Databus
Mirror
Index
如果希望通过写入的Logld、Userld 或者其他的业务字段进行消息的查询,应该怎么做?
Parquet
Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容Hadoop生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、lmpala、Drill等)。
RocketMQ
存储模型
事务消息
- 相当于二阶段提交