前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >画图搞懂Kafka的高可用方案-ISR机制如何保证写入数据时主从的数据同步

画图搞懂Kafka的高可用方案-ISR机制如何保证写入数据时主从的数据同步

作者头像
简熵
修改2023-03-07 09:46:47
8370
修改2023-03-07 09:46:47
举报
文章被收录于专栏:逆熵逆熵

目录

1、kafka霸道性能之揭开日志底层存储的面纱

2、HW?LEO?你俩一起搞事情?

3、ISR机制底层如何设计?

这是2020年的第一篇文章,新的开始,与君共勉。前文小白简单的去剖析了肌霸先生kafka的一些肌肉群,但是呢,只是远远地看了几眼,今天我们将深层次的从ISR机制,HW,高水位,LEO,日志存储等绕来绕去的名词去真正的靠近肌肉,大饱眼福,撕开Kafka的外衣,文明看肉,肌肉的肉。上文的链接是这个【舔一舔 · 肌霸Kafka】,也欢迎一起去回味一下。文中若有错误之处,欢迎大家留言讨论,谢谢大家。

1、kafka读写霸道性能之揭开日志底层存储的面纱

回顾上文我们知道,Kafka利用操作系统的Page Cache加上磁盘顺序写的机制,将自己的读写能力提升到了极致,高吞吐,低延迟。前文也简单的介绍了partition,日志,kafka的消息格式等,那么这里我们就来看看kafka的日志到底怎样的模样,有什么玄妙?

kafka上创建的一个topic都对应着多个partition,我们假设下topic的命名是orderPush,并且该topic有3个partition,每个partition有三个副本。

kafka有个配置参数log.dirs,所有的数据就是写入到这个目录下面,并且partition这样命名的,orderPush-0,orderPush-1,orderPush-2,分别对应着一个目录。每个目录中都很多个分段文件segment,写入文件会按照顺序写的规则去写入例如 00000000000000000000.log,默认大小为1G,就像我们平时用的logback文件一样,一旦写满,就自动滚动到下一个文件。

记住:kafka永远是顺序写入,文件结尾追加写

每一个log文件都对应俩个索引文件,一个是位移索引,后缀为.index,0.8版本之后又加入了时间戳索引,后缀为.timeindex,通过索引文件都能够快速地定位到消息。kafak为了节省索引的空间,采取了稀疏索引的策略,参数log.index.interval.bytes定义了log文件每写入多少字节,就会写入一条索引。

读取消息时,采用二分查找法定位到对应的索引,然后根据物理地址和物理位置去定位消息。

02

HW?LEO?你俩一起搞事情?

还记得之前我们讨论过的【舔一舔 · 肌霸Kafka】,kafka通过ISR机制来保证数据的高可用,不丢失,in sync replicas。我们接着讨论的是俩个看起来很酷(hui)炫(se)炸(nan)天(dong)的几个offset,这几个名词都和kafka写入日志紧紧相关,可以说我们理解了他们,才是真正的开始去理解kafka的写入,高可用机制,ISR机制如何运转。

  1. offset,这个很好理解,这个就是每次写入的消息的下标,和数组一样,第一条数据,0,1,2以此类推。
  2. LEO,log end offset,日志写完最后一个下标,这个理解起来也不难,就是说你当前写入的下标为0,那么LEO=offset+1,也就是下一个即将要写入的位置。
  3. HW offset,这是啥?high water offset ,高水位,这是一个比较重要的概念,简单来说当我们一个topic有多个partition,只有当所有follower partition的LEO和leader partition的LEO相等的时候,HW才会发生变化,他代表的是当前已经提交的数据,HW和LEO之间的数据消费者是看不到的。
  4. leader partition和follower partition都有LEO和HW。LEO的变化影响了HW,本质上LEO的一个作用就是为了更新HW。

我们需要去理解和掌握上的就是这几个offset是如何变化的。

  1. leader partition offset的更新就是每次写入数据,offset+1
  2. follower partition找leader来同步数据,leader partition每次将数据推送给follower partition
  3. leader会维护一个follower partition的LEO值的列表,包含所有Follower partition的LEO值
  4. 每次leader partition 将数据推送给出follower partition,follower partition写入数据,follower partition的LEO+1
  5. 通过每次follower partition Fetch数据带上自己的LEO,leader可以更新follower partition的LEO值列表
  6. 每次follower partition过来拉取数据的时候,leader更新完LEO值列表,就会比对一下列表中所有的follower partition的LEO值是否和自己的LEO一致,如果一致,就会推进HW+1
  7. 每次返回给follower partition的数据也会带上HW,follower partition就会更新HW值,如果Leader partition的HW大于自己的LEO,follower partition HW=自己的LEO,如果如果Leader partition的HW小于自己的LEO,follower partition HW=leader partition HW,总之,二者取其小。
  8. 由此说来,LEO的更新和同步一致才是HW变化的前提。由于是follower partition每次过来同步数据,所以,HW最少都要俩次才会发生变化。

03

ISR机制底层如何设计

ISR机制是保证数据写入不丢失高可用的核心机制,Kafka是如何为leader Partition维护ISR列表的呢?什么样的follower partition才有资格放入ISR列表中呢?

  1. 老版本的Kafka配置文件有这样一个参数,replica.lag.max.messages,这个参数的意思是,在生产者写入数据,leader Partition维护的ISR列表中所有的follower Partition同步leader数据,follower Partition的LEO落后的条数,不能超过这个参数,一旦超过,会将follower Partition踢出去
  2. 默认配置下,一般生产者写数据要所有follower都写入成功才算成功,如果某台follower Partition卡住,落后了,会导致生产者也卡住,直到follower被踢出去ISR列表,此时leader Partition和其他follower Partition的HW也会随着LEO推进。
  3. 在这个过程中,消费者是读取不到已经写入的HW到LEO之间的数据的
  4. 每次follower过来fetch数据的时候,leader会判断Leo是否落后,一旦落后,剔除
  5. 还有一个参数 min.sync.replicas,意思是必须要有多少个副本在ISR中,生产端写入可以配置ack=-1,意思是每次写入必须要写入所有ISR副本才算成功,这里也可以理解,如果ISR副本数小于配置的,生产者会卡住。

不过我们也可以思考一下,在线上环境如果配置这样的参数的话,其实也有问题的,一般高并发场景下,大数据量都是瞬间涌入,可能就会导致有些follower Partition因为机器原因或者full GC原因,会偶尔跟不上数据,如果这样的情况重复出现,就会导致某些follower Partition 频繁被踢出ISR列表。这样子其实不是很好。

所以后面版本Kakfa有引入了新的参数,replica.lag.time.max.ms,默认10s,根据时间来判断,落后超过多长时间就剔除,这样子和之前的方案比起来,只要在一定时间内follower partition追上数据同步,就不会频繁被踢出。

时间过得好快,这是2020年的第一篇文章,技术真的需要去耐心钻研,我们的面“肌”之旅还没有结束,本文主要对ISR机制的一些技术点做了剖析,若文中有误,欢迎批评指正。一起成长,一起去积累我们的技术肌肉,我们的目标是什么?大!大!大!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 逆熵架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档