深入了解kafka(四)

一.学习kafka的副本机制(replic)

1.为什么我们需要副本机制

我们知道kafka的每一个topic下面都可以多个partition,各个partition会均匀的分布在broker上面,但是我们每一个partition都只有一个,如果某一个broker挂掉了之后,那么这个broker上面的消息就没有办法被消费了,所以kafka为了提高partition的可靠性而提出了副本的概念,通过副本机制来实现冗余备份。

2.kafka副本机制的实现

(1)每一个partition都会存在多个副本,每一个partition的副本都会存在一个leader副本,在kafka中所有消息的写入和读取都是在leader副本中进行,然后follower会不断去同步leader副本的消息数据。一般情况下,同一个分区的多个副本会被均匀分配到集群中的不同broker上,当leader副本所在的broker出现故障后,可以重新选举新的leader副本继续对外提供服务。通过这样的副本机制来提高kafka集群的可用性。

(2)副本分配算法 (i个副本,n个broker)
第i个partition会分配到(i余n)的broker上面。
第i个Partition的第j个副本会分配到第((i + j) mod n)个broker上.
举例:创建一个三个副本的,两个分区的topic,
sh kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 2 --topic mictopictest
那么他的分布情况会如下:
在这里插入图片描述

(3)有多个副本的分区的时候,我们如何知道他的leader是副本是哪一个?
在zookeeper,bin目录,./zkCli.sh
接着get /brokers/topics/topic名字/partitions/分区数/state {“controller_epoch”:12,“leader”:0,“version”:1,“leader_epoch”:0,“isr”:[0,1]}
leader:分区的leader是那个broker-id。
isr:可以副本的的broker

(4)kafka的数据复制算法保证了当一个leader挂掉了以后,新选举出来的leader可以读写数据。kafka从副本列表选举一个称谓leader,leader负责读写数据,跟踪和维护ISR(副本同步队列)队列中所有follower的滞后情况。当生产者发送一条消息到broker后,消息写入到leader,同步到各个follower。消息提交之后才被成功复制到所有的同步副本。

3.kafka副本机制中的几个概念

(1)leader:负责读写消息,同时跟踪和维护ISR(副本同步队列)队列中所有follower的滞后情况

(2)follower:只是负责备份leader中休息

(3)ISR:包含了所有的leader和保持和leader同步的follower(当某一个follower不能保持和leader同步时,他会从ISR中踢出去)。

(4)LEO:log end offset,他记录副本日志的下一条记录的offset值

(5)HW:Hgiht Water,水位值,HW永远不大于LEO的值,只有offset小于HW值的消息才能被消费掉。每个replica都有HW,leader和follower各自维护更新自己的HW的状态

4.副本协同机制

(1)leader读写数据,follower只同步备份数据,但是会有一定的延迟,所有有一个阈值,当延迟大于这个阈值的时候,该follower会被剔除
在这里插入图片描述
ISR集合中的副本必须满足两个条件
1.副本所在节点必须维持着与zookeeper的连接
2. 副本最后一条消息的offset与leader副本的最后一条消息的offset之间的差值不能超过指定的阈值(replica.lag.time.max.ms) replica.lag.time.max.ms:如果该follower在此时间间隔内一直没有追上过leader的所有消息,则该follower就会被剔除isr列表

(2)一条消息只有被ISR里的所有Follower都从Leader复制过去才会被认为已提交。这样就避免了部分数据被写进了Leader,还没来得及被任何Follower复制就宕机了,而造成数据丢失(Consumer无法消费这些数据)。而对于Producer而言,它可以选择是否等待消息commit,这可以通过acks来设置。这种机制确保了只要ISR有一个或以上的Follower,一条被commit的消息就不会丢失。

(3)leader与follower数据的同步的过程
1.初始状态,follower会主动的发送fetch请求到leader,如果一段时间内没有任何leader没有任何消息进入,会阻塞。replica.fetch.wait.max.ms设置阻塞时间
在这里插入图片描述
2.producer生产第一条数据
(1)数据写入到leader的log,然后leader的LEO值会变成1
(2)leader会尝试去更新他的HW值,但是由于follower还没有发送fetch请求,所以他的remote LEO值还是0,由于HW是取LEO和remote LEO中的较小值,所以HW还是0
(3)这是follower发送fetch请求到leader,带上他的LEO的值即(offset=0),这是leader会收到follower的这个请求值,同时更新他的remote LEO值,依然是0,比较更新HW
(4)收到fetch请求后,leader会response,消息会同步到follower的log,然后HW(这时等于0)也会返回给follower
(5)follower收到返回后同步数据log,同时会更新的他的LEO的值为1
follower第一次fetch请求结束,这是还是不能消费数据,应为HW还是等于0
在这里插入图片描述
3.follower第二次fetch请求
(1)第二次fetch请求,follower会带上他的LEO(offset=1),然后leader收到请求后会将他的remote LEO值更新为1,HW通过比较LEO和remote LEO的值取较小的值,(这是LEO ,remote LEO都为1),所以HW更新为1,
(2)leader会将HW(值为1)返回给follower,如果有log消息带上log消息,follower收到后会更新HW
在这里插入图片描述
follower发起两次请求之后HW=1,才可以消费第一条消息。

4.处理过程基本上和前面说的一直 leader将消息写入本地日志,更新Leader的LEO ,唤醒follower的fetch请求 ,更新HW

5.由于两次fetch,可能会导致在极端情况下的数据丢失的情况
(1)一次同步时结束的时候,leader需要将新的HW值和(假设有)有新的数据一同返回给follower,follower需要更新HW值,保存新的消息log.
(2)如果这个时候follower挂掉了,那么他讲不能保存新的消息log和跟新HW,
(3)然后这个follower又恢复了,他的LEO值会变成之前HW值,他会想leader再次发送fetch请求,带上他的LEO(offset)(做了一次分断)
(4)这时leader挂了,本来他是要取到来自follower的LEO,更新remote LEO,更新HW,没更新到
(5)这时leader又恢复了,做了一次分断,导致了数据丢失。

在这里插入图片描述

6.解决方法
在kafka0.11.0.0版本以后,提供了一个新的解决方案,使用leader epoch来解决这个问题,leader epoch实际上是一对之(epoch,offset), epoch表示leader的版本号,从0开始,当leader变更过1次时epoch就会+1,而offset则对应于该epoch版本的leader写入第一条消息的位移。
leader broker中会保存这样的一个缓存,并定期地写入到一个checkpoint文件中。 当leader写log时它会尝试更新整个缓存——如果这个leader首次写消息,则会在缓存中增加一个条目;否则就不做更新。而每次副本重新成为leader时会查询这部分缓存,获取出对应leader版本的offset

5.如何处理所有的Replica不工作的情况

如果某个Partition的所有Replica都宕机了,就无法保证数据不丢失了
处理方案:
1.等待ISR中的任一个Replica“活”过来,并且选它作为Leader (可能等很久)
2. 选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader (可能数据由缺失)

6.ISR原理

如果是全部同步的话,一个follower导致挂掉,就会导致无法提交。
如果是全部异步的话,leader commit了就认为消息commit了,但是follower有时会和leader存在延迟,如果leader 所在的broker挂掉了,新选举的leader可能会数据缺失
采用ISR集合,巧妙解决了两种方案的缺陷:当follower副本延迟过高,leader副本则会把该follower副本踢出ISR集合,消息依然可以快速提交。当leader副本所在的broker突然宕机,会优先将ISR集合中follower副本选举为leader,新leader副本包含了HW之前的全部消息,这样就避免了消息的丢失。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值