数据库与消息队列笔记

Posted on Jan 11, 2025

面试知识

数据库

索引: 事务 隔离级别 锁 https://www.notion.so/elonnzhang/23d21f3fbf218061963dee831cdecd91?source=copy_link

消息队列

通常来说,使用消息队列主要能为我们的系统带来下面三点好处:

  1. 异步处理
  2. 削峰/限流
  3. 降低系统耦合性
  4. 分布式事务、顺序保证和数据流处理。 可能会遇到的问题
  5. 消息丢失、重复消费

Kafka

发布-订阅模型 : 1 -> N 发布订阅模型

发布订阅模型(Pub-Sub) 使用主题(Topic) 作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息通过主题传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该条消息的。

在发布 - 订阅模型中,如果只有一个订阅者,那它和队列模型就基本是一样的了。所以说,发布 - 订阅模型在功能层面上是可以兼容队列模型的。 Kafka 比较重要的几个概念:

  1. Producer(生产者) : 产生消息的一方。
  2. Consumer(消费者) : 消费消息的一方。
  3. Broker(代理) : 可以看作是一个独立的 Kafka 实例。多个 Kafka Broker 组成一个 Kafka Cluster。

同时,你一定也注意到每个 Broker 中又包含了 Topic 以及 Partition 这两个重要的概念:

  • Topic(主题) : Producer 将消息发送到特定的主题,Consumer 通过订阅特定的 Topic(主题) 来消费消息。
  • Partition(分区) : Partition 属于 Topic 的一部分。一个 Topic 可以有多个 Partition ,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上,这也就表明一个 Topic 可以横跨多个 Broker 。

分区进一步理解

  • 代理(Broker: 实例节点
  • 主题(Topic):Kafka 的消息类别,可以类比数据库的“表”。(topic可以跨 brocker,类似于分片表 shard)
  • 分区(Partition):是 Topic 的物理存储单位,每个 Topic 可以有多个分区。

Topic: order-events ├── Partition 0: msg0, msg1, msg2 … ├── Partition 1: msg3, msg4, msg5 … └── Partition 2: msg6, msg7, msg8 …

为什么要分区?

  1. 扩展性(Scalability)
    • 多个分区可以分布在不同的 Broker 上,形成集群,突破单机存储和吞吐瓶颈。
  2. 并行性(Parallelism)
    • 每个分区可以被不同的消费者实例并行消费,提升处理速度。
  3. 高可用(HA)
    • 分区可以配置副本(Replica),某个 Broker 挂了,副本仍然能提供服务。

生产者与分区的关系 生产者可以指定分区

消费者与分区的关系

  • Kafka 的消费者组(Consumer Group)是以分区为单位分配消息的:
    • 一个分区只能同时被一个消费者实例消费。
    • 消费者实例数 <= 分区数,才能最大化并行。 分区与消息顺序
  • Kafka 只保证分区内的消息顺序。
  • 不同分区之间消息是乱序的。

分区数的设计

  • 分区数越多:

    • 并行度更高,吞吐量更大
    • 但元数据更多,管理复杂度更高
  • 分区数一旦确定,后续增加可能导致数据重分布(成本高)

    经验值:

    • 根据 峰值吞吐量 / 单分区最大吞吐量 来估算分区数。
    • 分区数至少要大于消费者实例数,否则并行性浪费。

副本

Kafka 为分区(Partition)引入了多副本(Replica)机制。分区(Partition)中的多个副本之间会有一个叫做 leader ,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。

生产者和消费者只与 leader 副本交互。你可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。


Partition 0 (Leader: Broker1, Follower: Broker2, Broker3)

Kafka 的多分区(Partition)以及多副本(Replica)机制有什么好处呢?

  1. Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力(负载均衡)。
  2. Partition 可以指定对应的 Replica 数, 这也极大地提高了消息存储的安全性, 提高了容灾能力,不过也相应的增加了所需要的存储空间。

kafka中的zookeeper

ZooKeeper 主要为 Kafka 提供元数据的管理的功能。

  • Broker 注册:在 Zookeeper 上会有一个专门用来进行 Broker 服务器列表记录的节点。每个 Broker 在启动时,都会到 Zookeeper 上进行注册,即到 /brokers/ids 下创建属于自己的节点。每个 Broker 就会将自己的 IP 地址和端口等信息记录到该节点中去
  • Topic 注册:在 Kafka 中,同一个Topic 的消息会被分成多个分区并将其分布在多个 Broker 上,这些分区信息及与 Broker 的对应关系也都是由 Zookeeper 在维护。比如我创建了一个名字为 my-topic 的主题并且它有两个分区,对应到 zookeeper 中会创建这些文件夹:/brokers/topics/my-topic/Partitions/0、/brokers/topics/my-topic/Partitions/1
  • 负载均衡:上面也说过了 Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力。 对于同一个 Topic 的不同 Partition,Kafka 会尽力将这些 Partition 分布到不同的 Broker 服务器上。当生产者产生消息后也会尽量投递到不同 Broker 的 Partition 里面。当 Consumer 消费的时候,Zookeeper 可以根据当前的 Partition 数量以及 Consumer 数量来实现动态负载均衡。

Kafka 2.8 之后 引入了基于 Raft 协议的 KRaft 模式,不再依赖 Zookeeper