技术大佬 :佩琪,最近看你闷闷不乐,又被虐了?
佩琪:(⊙o⊙)…,又被大佬发现了。现如今公司内部岗位竞争激烈,靠被动涨薪,已经比前几年难了不止几个数量级。怎么办?趁年底到外部去主动出击,“运气好”,成功了,也能主动涨薪。可是最近出去面试都被揉捏的像一个麻花了
技术大佬 :哦,这次又是遇到什么难题了?
佩琪: 由于和大佬讨论过消息中间件的应用画像问题: 不丢,不重复,不乱序,以及kafka高性能(见
kafka 消息“零丢失”的配方
技术大佬问我 订单消息重复消费了 怎么办?
技术大佬问我 订单消息乱序了怎么办?
技术大佬问我 kafka为什么这么快
)
所以在简历的技术栈里就夸大似的写了精通kafka消息中间件,然后就被面试官炮轰了里面的细节
佩琪: 其中面试官给我印象深刻的一个问题是:你们的kafka是如何保证数据的高可靠的了?主从之间数据又是如何同步的了?
技术大佬 :哦,那你是怎么回答的了?
佩琪:我就是个crud boy,根本不知道啥是高可靠,所以就很低下的回答到:“尊敬的面试官,不好意思,我不太理解这里面的细节“
技术大佬 :哦,真是个诚实的孩子;然后呢?
佩琪:然后面试官就让我回家等通知了,然后就没有然后了。。。。
佩琪 : 对了大佬,你能讲讲 kafka 是如何保证数据高可靠的吗?
技术大佬 :kafka 数据高可靠,主要是靠分区多副本机制来保证的。即kafka认为把数据保存在一个机器的一个分区上有丢失的风险,那么可以允许把数据复制到多个机器的多个副本分区上。核心思想,是利用数据的冗余来保证数据的高可靠的。
佩琪 : 哦哦,那你能说说 kafka 副本间 数据是如何同步的吗?
技术大佬: 要了解 kafka副本间数据同步,除了要知道它的同步流程外,还需要知道数据同步流程里有两个重要的逻辑概念,一个是HW,一个是LEO。
佩琪: 哦哦,那什么是HW呢?
技术大佬: HW(hight water)翻译为中文为“高水位”。概念有点抽象,要不看看 下图
高水位其实是一个日志位置:是“所有ISR分区”已同步leader日志的位置。 比如这里的HW 值为5:表示"所有的ISR分区" 已同步了leader分区位置为5之前的日志。
佩琪: 哦哦,大佬,这个HW这么的抽象,有什么用呢;能举几个具体的栗子不?
技术大佬: 主要有两个作用
技术大佬: 1. 控制所有的消费组,对leader分区上消息日志的可见性。比如上图中HW 为5,表示消息者应用,只能看到5之前的消息;而5到8这4个未被follower分区同步的日志,消费组是看不到的。其实这也是kafka为了保证数据一致性的底层实现方式,比如5到8还未被ISR同步的日志,如果被消费者消费了,但是还没提交消费确认 就宕机了,然后集群选出其它ISR分区成为了新leader;然后消费者 再从拉消息进行消费,这时会导致消费者看不到上一次拉取到的某些消息;你不觉得很奇怪吗?
技术大佬: 2. 帮助kafka完成副本同步,就是上面说的 分区数据同步时会用到。
佩琪: 哦哦,那这个LEO又是什么了?
技术大佬: 这个LEO 英文全称是Log end offset,即日志末端偏移量,它标识 当前leader 写入下一条日志的位置。上图里的LEO 是6,HW为5,然后leader此时写入了一条新消息在位置5上,只是还没被ISR里分区进行同步。
佩琪: (小声嘀咕 概念终于啰嗦完了 ),大佬 是不是该讲讲 follower同步leader的消息数据过程是怎样的了?
技术大佬: follower同步leader消息数据 大概有5步。
技术大佬: 第一步:假设有一个topic,有1个分区,2个副本的;生产端发送3条批量消息到 leader分区上;leader HW为0,leader LEO 为3;
follower HW 为0,follower LEO为0;
如下图
技术大佬: 第二步:follower分区会定时不停的往leader分区拉取数据。请求参数带上自身LEO=0和HW=0;定时间隔和拉取的数据量可配置(默认为500毫秒,replica.fetch.wait.max.ms);如下图
技术大佬: 第三步: follower 分区拉取后,返回的数据里包含消息数据和leader的HW;接着消息写入本地文件系统,然后更新自身的LEO值为3,更新自身的HW为0;如下图
技术大佬: 第四步:follower分区再次拉取数据。请求参数带上LEO=3,HW=0;leader分区,看到follower分区LEO为3;然后和自己的HW比较,发现大于自己的HW,立刻把自己的HW也更新为3;如下图
技术大佬: 第五步:follower 分区拉取后,返回的数据里包含leader的HW=3;follower在拿到leader的HW,和自身进行比较,发现leader比自身大,则更新自身的hw为3;如下图
佩琪: 大佬我知道了,让我来简化下上面的同步过程吧。 follower的LEO,在第一次同步消息时,进行更新;而leader 的HW, follower的HW,是在第二次同步时才会进行更新的。
佩琪: leader的HW,依赖follower的LEO;follower的HW,依赖leader的HW更新;并且这些值的更新是在两次请求中完成的。
技术大佬: 佩琪进步很快嘛,给你点赞。
佩琪: 对了,大佬,这个follower 的LEO和HW,需要两次请求,即两阶段,才能完成;直觉告诉我,这里面有问题。另外 follower同步leader的这个过程,有什么问题没了?
技术大佬: (汗,被问到了)这个,额,11点半了,到饭点了,要不先吃饭,下午再聊?
总结
1、kafka 主从同步,主要是靠follower分区,定时拉取来完成的;并且这个定时时间,拉取消息数量大小的上限和下限可配置
2、kafka 主从同步时,follower 除了拉取消息数据外,还会更新HW消息位置,和LEO的消息位置
3、leader HW,follower LEO和follower HW的更新,是通过两阶段完成的。
原创不易,请 点赞,留言,关注,收藏 4暴击^^
参考资料:
kafka.apache.org/20/document…
cwiki.apache.org/confluence/…