乐趣区

一文读懂Kafka副本机制

前言

副本机制就是备份机制,指的是在分布式集群机器中保存着相同的数据备份。

那么副本机制的好处的是什么呢?

  1. 提供数据冗余(主要作用)
  2. 提供高伸缩性
  3. 改善数据局部性

总之: 副本机制是 kafka 确保系统高可用和高持久的重要基石。

1. 副本

所谓副本,本质上就是一个只能追加写消息的提交日志。这些日志被相同的分散保存在不同的 Broker 上。
在实际生产上,每台 Broker 都可能保存有各个主题下不同分区的不同副本。因此单个 Broker 上存有成百上千个副本现象是非常正常的。

1.1 副本角色

既然多个 Broker 中保存分区下的多个副本,那么是如何保证副本当中的数据都是一致的呢?

针对这个问题,kafka 的解决方案就是 领导者副本机制

领导者的副本机制工作原理

  • 在 kafka 中,副本分成两类:领导者副本和追随者副本。每个分区在创建时都要选举一个副本,成为领导者副本,其余的副本自动称为追随者副本。
  • kafka 中,追随者副本是不会对外提供服务的,所有的请求都必须由领导者副本来处理。它唯一的任务就是从领导者副本异步拉去消息,并写入到自己提交日志中,从而实现与领导者副本的同步。
  • 当领导者副本挂掉了,或者说所在 Broker 宕机了,kafka 可以通过 Zookeeper 提供的监控功能能够实时感知到,并开启新一轮领导者选举,从追随者副本中选一个作为新的领导者。老 Leader 副本重启回来后,只能作为追随者副本加入到集群中。

一定注意上面第二点,追随者副本是不会对外提供服务的。这也是 kafka 没能提供读操作横向扩展的根本原因,而且它也不像 mysql 副本一样有”抗读“的作用,帮助领导者减轻压力。那么这种副本机制设计究竟有什么好处呢?

1.2 副本机制的好处

1. 方便实现“Read-your-writes”

顾名思义,就是当你使用生产者 api 向 kafka 成功写入消息后,就马上使用消费者 api 去读取刚才的消息。
举个例子,就是你刚发完一条微博,肯定是希望立马能够看到的。这就是 Read-your-writes 场景了。如果追随者副本对外提供服务的话,由于副本同步是异步的,因此有可能发生追随者副本还没有及时从领导者副本中拉取最新消息,从而使客户端看不到最新的消息。

2. 方便实现单调读

什么是单调读。单调读就是消费者在多次读消息时候,不会看到一条消息一会儿存在一会儿不存在。
例如:如果允许追随者副本提供读服务,那么假设当前有两个追随者副本 F1,F2。生产者往领导者中发送了消息后,F1,F2 开始异步拉取消息。若 F1 拉取成功了,而 F2 还未拉取成功。此时消费者第一次消费 F1 副本获取最新消息,第二次消费的时候消费到了 F2 副本。就获取不到该条消息了。这就不是单调读一致性。所以都由 Leader 副本来处理请求的话,就能实现单调读。

1.3 In-sync Replicas(ISR)

上文提及到的追随者副本不对外提供服务,只是定期的异步拉取消息。既然是异步的,那么就存在着不可能与 Leader 实时同步的风险。所以 kafka 应该告诉我们,追随者副本到底在什么条件之下才算与 Leader 同步。

基于这个想法,kafka 引入了 ISR,副本集合。ISR 中的副本都是与 Leader 同步的副本,相反,不在 ISR 中的追随者副本被认为是与 Leader 不同步的。那么进入 ISR 到底需要满足什么条件才能进入呢。

首先需要明确一点。ISR 不只是追随者副本集合,它必然包括 Leader 副本。甚至在某些情况下,ISR 只有 Leader 这一个副本。

图中有 3 个副本:1 个领导者副本,2 个追随者副本。领导者副本写入了 10 条消息,F1 同步了 6 条,F3 同步了 3 条。那么哪个追随者副本与 Leader 不同步呢?
事实上,这两个副本都有可能与 Leader 副本不同步,但也可能同步。它实际上不是依靠与消息条数来进行判断的。而是根据 Broker 端参数 replica.lag.time.max.ms 参数值 。这个参数的含义就是 Follower 副本能够落后 Leader 副本的最长时间间隔,当前默认值是 10 秒。
这就是说,只要一个 Follower 副本落后 Leader 副本的时间不连续超过 10 秒,那么 Kafka 就认为该 Follower 副本与 Leader 是同步的,即使此时 Follower 副本中保存的消息明显少于 Leader 副本中的消息。若是同步过程的速度持续慢于 Leadr 副本的写入速度,那么在 replica.lag.time.max.ms 时间后,kafka 就会自动收缩 ISR 集合,将改副本提出集合。

值得注意的是,若改副本后面慢慢追上了 Leader 的进度。那么它是可以被重新放入 ISR 集合中的。这也表明 ISR 是一个动态调整的集合,而非静态不变的。

Unclean 领导者选举

既然 ISR 可以动态调整,那么就会出现 ISR 为空的情况。ISR 为空的情况就代表 Leader 副本也挂掉了。那么 kafka 就需要重新选举新的 Leader。
那么该怎么选举 Leader 呢?

  • kafka 把所有不在 ISR 的存活副本都成为非同步副本。
  • 通常来说,非同步副本落后 Leader 太多,因此,如果选择这些副本为新的 Leader,就可能出现数据的丢失。在 kafka,选举 Leader 这种过程被成为 Unclean。由 Broker 端参数 unclean.leader.election.enable 控制是否允许 Unclean 领导者选举。
  • 开启 Unclean 领导者选举可能会造成数据丢失,但好处是,它使得分区 Leader 副本一直存在,不至于停止对外提供服务,因此提升了高可用性。反之,禁止 Unclean 领导者选举的好处在于维护了数据的一致性,避免了消息丢失,但牺牲了高可用性。

可以根据你的实际业务场景决定是否开启 Unclean 领导者选举。不过并 不建议开启 它,毕竟我们还可以通过其他的方式来提升高可用性。如果为了这点儿高可用性的改善,牺牲了数据一致性,那就非常不值当了。

退出移动版