10

前言

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

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

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

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

1.副本

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

image.png

1.1 副本角色

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

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

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

image.png

  • 在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这一个副本。

image.png

图中有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 领导者选举。不过并不建议开启它,毕竟我们还可以通过其他的方式来提升高可用性。如果为了这点儿高可用性的改善,牺牲了数据一致性,那就非常不值当了。


十三先生
34 声望196 粉丝

信念不能崩塌