这是我参与「第三届青训营 -后端场」笔记创作活动的第7篇笔记
什么是消息队列
保存消息的容器,本质是一个队列,需要支持高并发,高吞吐,高可用
kafka
基本概念
- topic,逻辑队列,可以认为每个不同的业务场景就是一个不同的topic,服务可以订阅topic。
- partition,分片,每个topic拥有多个分片,用以提高单个topic的吞吐
- consumerGroup,消费者组,不同组的消费进度互不干涉。
- offset,消息在partition中的相对位置,在partition内严格递增。
- replica,每个分片都有多个副本,而这些副本分布在不同的机器上。leader replica从isr中选出,follower和leader的数据差距比较大时会被提出isr
- broker,集群的一个节点
数据复制
写数据只能leader写数据,folower从leader同步数据。
集群架构
数据发送
- 批量发送,压缩
消息存储
文件名是日志中第一条消息的offset,消息按顺序写入
如何找到消息
consumser发送获取消息的请求后,broker将会指定offset处的消息,那么他如何寻找到消息呢?
- 二分查找找到小等于目标offset的最大文件。
- 在索引文件内,二分查找小于等于目标offset的最大索引位置。也可以通过时间戳在时间戳索引文件内查询offset,然后在通过offset查找,多了一步。
读数据
将磁盘数据读到内核缓冲区后,不进入用户空间,直接转到socket buffer发送。
partition在消费组内的分配问题
- 手动分配(low-level),制定哪个消费者消费哪个partition,缺点是,如果某个消费者挂了,就没有人消费对应的partition了。如果,加入了新的消费者,有需要停掉集群修改配置。
- 自动分配(high-level),对于不同的消费组,都会选取一个broker当作coordinator,而它的作用就是帮助这个消费组进行分片的分配,当消费组内有消费者宕机或者新的消费者加入时,会重新进行分配来达到稳定的消费状态
重启
- 选择一个重启的borker关闭
- 如果某个分片的副本是leader,从该分片isr中其余的follower中选取一个leader
- 刚刚重启的broker,从leader同步数据
- 回切leader,避免集群在长期运行后,leader集中在少数节点上,导致数据不均衡 问题:重启需要同步数据,花费时间较长。而且不能并发重启,因为部分topic的某一分片的副本所在的机器刚好都重启了就出大问题了。
替换,扩容,缩容
替换:需要同步许多数据的重启 扩容:分片分配到新的机器上以后也是需要从0同步数据 所容:同上。 都需要花费大量时间
负载不均衡问题
partition上的数据明显比其他多,为了减少broker的压力,可能需要吧partition3的内容移到其他机器上,但是此时就增加了broker的压力,为了解决问题而导致问题更严重了。