kafka ISR设计及水印与leader epoch副本同步机制深入剖析-kafka 商业环境实战

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。版权声明:禁止转载,欢迎学习。QQ邮箱地址:[email protected],如有任何商业交流,可随时联系。

1 帽子理论(Gilbert 和 Lynch )

  • 一致性

      any read operation that begins after a write operation completes must 
      return that value, or the result of a later write operation
    
      通过某个节点的写操作结果对后面通过其它节点的读操作可见
      
      强一致性:
      如果更新数据后,并发访问情况下后续读操作可立即感知该更新,称为强一致性。
      
      弱一致性:
      如果允许之后部分或者全部感知不到该更新,称为弱一致性。
      
      最终一致性:
      若在之后的一段时间(通常该时间不固定)后,一定可以感知到该更新,称为最终一致性。
    复制代码
  • 可用性(Availability)

      every request received by a non-failing node in the system must result in a response
    
      任何一个没有发生故障的节点必须在有限的时间内返回合理的结果。
    复制代码
  • 分区容忍性(Partition Tolerance)

      the network will be allowed to lose arbitrarily many messages sent from one node to another
    
      部分节点宕机或者无法与其它节点通信时,各分区间还可保持分布式系统的功能。
    复制代码
  • 悖论总结:

    可用性限定在无论是否集群节点宕机,只要有活着的节点,就会立即返回请求结果。若要限制返回结果必须是最近一次写的结果,就比较悲剧,若允许分区容忍性 => 分布式系统分区之间就存在数据同步机制,那么就有可能因为分区心跳切断,导致数据不一致。

2 partition本质就是为了日志备份(对外最小的存储单元)

Kafka中topic的每个partition有一个预写式的日志文件,虽然partition可以继续细分为若干个segment文件,但是对于上层应用来说可以将partition看成最小的存储单元(一个有多个segment文件拼接的“巨型”文件),每个partition都由一些列有序的、不可变的消息组成,这些消息被连续的追加到partition中。

  • partition本质就是为了日志备份,利用多份日志文件的副本(replica)备份来共同提供冗余机制来保持系统的高可用性。
  • kafka会把副本均匀的分配到所有的Broker上。在其中所有的副本中,会挑选一个Leader副本来对外提供服务,其他的副本统称为follower副本,只能被动的向leader副本请求数据。

3 Partitioner 三分天下

下图展示了3个Partition把一个Topic主题数据流分成三份,通过Partioner路由依次追加到分区的末尾中。如果partition规则设置的合理,所有消息可以均匀分布到不同的partition里,这样就实现了水平扩展。

扫描二维码关注公众号,回复: 4200526 查看本文章
config/server.properties可以设置num.partitions参数,实现主题数据分流。

3 Leader副本竞选上岗(in-sync replicas)

  • 每一个分区都存在一个in-sync replicas。
  • in-sync replicas集合中的每一个副本都与leader保持同步状态,不在里面的保持不了同步状态。
  • 只有ISR中的副本才有资格被选为leader。
  • Producer写入的消息只有被ISR中的副本都接收到,才被视为"已提交"。

4 水印HW与末端位移LEO => Leader副本

  • 这里着重强调一下,Leader副本水印HW才真正决定了对外可看到的消息数量。
  • 所有的副本都有LEO和HW。
  • Leader副本水印HW的更新发生在所有的副本都更新了最新的LEO后,Leader副本最终才认为可以更新Leader副本水印。

5 ISR设计优化(replica.lag.max.messages废弃)

  • 解决了producer突然发起一大波消息,从而产生瞬时高峰流量。若设置replica.lag.max.messages=4,则follower副本会被瞬时的拉开距离,从而导致follower副本瞬间被踢出ISR。不过一段时间follower副本同步后,会再次进入ISR。
  • 同步不同步,同步不同步反复出现,是多大的性能浪费。
  • 0.9.0.0开始采用 replica. lag. time. max. ms,默认是10s,可谓是明智之举。

6 HW同步机制(Leader与follower的爱恨缠绵)

6.1 指哪打哪(HW指向哪里?)

  • 这里重点强调,都是无论HW还是LEO都是指向下一条消息
  • 举例如下:如果一个普通topic的某个分区副本的LEO是10,那么该副本当前保存了10条消息,位移值范围是[0, 9]。此时若有一个producer向该副本插入一条消息,则该条消息的位移值是10,而副本LEO值则更新成11。

6.2 Leader与follower的HW爱恨缠绵(两阶段请求定终身)

  • follower 副本会不断地向leader副本发送Fetch请求
(1)follower 副本对象何时更新LEO?
follower 副本专属线程不断地向leader副本所在broker发送FETCH请求。

leader 副本发送 FETCH response 给follower副本。

Follower 拿到response之后取出位移数据写入到本地底层日志中,在该过程中其LEO值会被更新。
复制代码
(2)leader 端非自己副本对象何时更新LEO?
leader 端非自己副本对象 LEO值是在leader端broker处理FETCH请求过程中被更新的。
复制代码
(3) follower 副本对象何时更新HW?
Follower 副本对象更新HW是在其更新本地LEO之后。

一旦follower向本地日志写完数据后它就会尝试更新其HW值。
算法为取本地LEO与FETCH response中HW值的较小值
复制代码
(4)leader 副本对象何时更新HW?
Leader 副本对象处理 Follower FETCH请求时在更新完leader 端非自己副本对象的LEO后将尝试更新其自己HW值

producer 端写入消息会更新leader Replica的LEO

副本被踢出ISR时

某分区变更为leader副本后
复制代码
(5)两阶段请求定终身:

第一次fetch请求仅获得了当前的数据,fetchOffset < Leader LEO, 因为leader 端的非自己的副本leo 是根据fetch请求确定的,因此,只有第二次请求时,fetchOffset才会和Leader LEO相等,进而更新 leader HW ,进而响应为 leader HW,进而更新 Folloer HW。

6.3 HW更新延迟带来的刀山火海

  • 因为 fetchOffset是实实在在的需要位移。所以只有第二轮请求时,Follower才会在其现有位移的基础上,加1进行请求,从而连锁更新 会更新Leader非自己remoteLEO 和 Leader HW 和 Follower HW。
  • 刀山火海就在一轮请求和第二轮请求之间发生了。

7 刀山火海敬请期待

本文实在麻烦,大牛的技术博客看起来总总有些词不达意,我顺便就直接口语化,希望带来不同的效果。技术就是一层窗户纸,看我把kafka和spark剖析的体无完肤。香港美景,一览众山小,技术道路上毅然前行!!

秦凯新 于深圳 201811230124

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。版权声明:禁止转载,欢迎学习。QQ邮箱地址:[email protected],如有任何商业交流,可随时联系。

猜你喜欢

转载自juejin.im/post/5bf6b0acf265da612d18e931