「训」 笔记(10):消息队列

本文最后更新于:40 分钟前

消息队列(MQ),指保存消息的一个容器,本质是个队列。但这个队列呢,需要支持高吞吐,高并发,并且高可用。

Kafka

分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色。

基本概念

  • Topic:逻辑队列,可以理解成每一个不同的业务场景就是一个不同的 Topic,对于这个业务来说,所有的数据都存储在这个 Topic 中
  • Partition:分片,通常 Topic 会有多个分片,不同分片之间消息是可以并发来处理的,这样提高单个 Topic 的吞吐量
  • Cluster:物理集群,每个集群中可以建立多个不同的 Topic
  • Producer:生产者,负责将业务消息发送到 Topic 中
  • Consumer:消费者,负责消费 Topic 中的消息
  • ConsumerGroup:消费者组,不同组 Consumer 消费进度互不干涉

  • Offset:消息在 Partition 内的相对位置信息,可以理解为唯一 ID,在 Partition 内部严格递增
  • Replica:分片的副本,分布在不同的机器上,可用来容灾,Leader 对外服务,Follower 异步拉取 Leader 的数据进行同步,如果 Leader 挂掉了,可以将 Follower 提升成 Leader 再对外进行服务
  • ISR:意思是同步中的副本,对于 Follower 来说,始终和 Leader 是有一定差距的,但当这个差距比较小的时候,我们就可以将这个 Follower 副本加入到 ISR 中,不在 ISR 中的副本是不允许提升成 Leader 的

数据复制

下图代表着 Kafka 中副本的分布图。Broker 代表每一个 Kafka 的节点,所有的 Broker 节点最终组成了一个集群。图中整个集群,包含了 4 个 Broker 机器节点,集群有两个 Topic,分别是 Topic1 和 Topic2,Topic1 有两个分片,Topic2 有 1 个分片,每个分片都是三副本的状态。这里中间有一个 Broker 同时也扮演了 Controller 的角色,Controller 是整个集群的大脑,负责对副本和 Broker 进行分配。

整体架构

在集群的基础上,还有一个模块是 ZooKeeper,这个模块其实是存储了集群的元数据信息,比如副本的分配信息等等,Controller 计算好的方案都会放到这个地方。

提高吞吐

  • Producer:批量发送,数据压缩

  • Broker:顺序写,消息索引,零拷贝
    零拷贝

  • Consumer:Rebalance

存在问题

  1. 数据复制问题

    举个例子来说,如果我们对一个机器进行重启:首先,我们会关闭一个 Broker,此时如果该 Broker 上存在副本的 Leader, 那么该副本将发生 Leader 切换。而因为数据在不断的写入,刚刚关闭重启的 Broker 和新 Leader 之间一定会存在数据的滞后,此时这个 Broker 会追赶数据,重新加入到 ISR 当中。当数据追赶完成之后,我们需要回切 Leader,这一步目的是为了避免在一个集群长期运行后,所有的 Leader 都分布在少数节点上,导致数据的不均衡。

    通过上面的分析,我们可以发现对于一个 Broker 的重启来说,需要进行数据复制,所以时间成本会比较大,比如一个节点重启需要 10 分钟,一个集群有 1000 个节点,如果该集群需要重启升级,则需要 10000 分钟,那差不多就是一个星期。如果并发多台重启,在一个两副本的集群中,重启了两台机器,对某一分片来讲,可能两个分片都在这台机器上面,则会导致该集群处于不可用的状态,这是更不能接受的。在替换、扩容、缩容的过程中也会遇到数据复制的时间成本问题。

  2. 负载不均衡

    某个 Broker 负载较高时,需要将某分片迁移到负载小的机器上,但是数据复制的过程又会加大该 Broker 的负载。所以其负载均衡非常复杂。

  3. 没有自己的缓存,完全依赖 Page Cache

  4. Controller 和 Coordinator 和 Broker 在同一进程中,大量 IO 会造成其性能下降

BMQ

存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的 Kafka 集群。

架构模型

RocketMQ

低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广。

基本概念

架构模型


「训」 笔记(10):消息队列
https://qanlyma.github.io/ByteDance-10/
作者
Qanly
发布于
2023年4月14日