学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • Java基础

  • Java集合

  • MySQL

  • Redis

  • JVM

  • 多线程

  • 计算机网络

  • Spring

  • Kafka

    • 生产者客户端开发
    • 消费者客户端开发
    • 主题与分区管理
    • 配置管理
    • KafkaAdminClient
    • 消费管理
    • Kafka Streams
    • 日志存储
    • 可靠性研究
      • 一、副本剖析
        • 1、失效副本
        • 2、ISR的伸缩
        • 3、LEO和HW
        • 4、Leader Epoch的介入
      • 二、为什么不支持读写分离
      • 三、日志同步机制
      • 四、可靠性分析
        • 1、分区副本保证可靠
        • 2、ack机制
      • 参考
    • 深入服务端
    • 深入客户端
    • 集群参数配置
    • 生产者消息分区机制原理
    • 如何确保消息不丢失
    • 如何确保消息不重复消费
    • 消费积压如何处理
    • 生产者是如何管理TCP连接
    • 消费者重平衡问题
    • 位移提交问题
    • 消费者是如何管理TCP连接
    • 副本机制深入
    • 消费组消费进度如何监控
    • 高水位和Leader Epoch
  • Elasticsearch

  • Python

  • 面试专题

  • 知识库
  • Kafka
旭日
2023-09-08
目录

可靠性研究

# 一、副本剖析

kafka采用了多副本的机制,以此来实现水平扩展、提供容灾能力,而副本是在不同的节点上持久化同一份数据,当某一个节点上存储的数据丢失时,可以从副本上读取该数据。

# 1、失效副本

正常情况下,分区的所有副本都处于ISR集合下,即AR=ISR,在ISR集合之外,处于同步失效或功能失效的副本统称为失效副本。

如何判断为失效副本

kafka的副本管理器会启动一个副本过期检测的定时任务,而这个定时任务会定期检查当前时间与副本的lastCaughtUpTimeMs差值是否大于指定参数

为什么副本不自己更新

假设现在leader副本中消息的流入速度大于follower副本中拉取的速度时,相当于follower永远也赶不上leader副本

副本失效的情况

  • follower副本进程卡住,在一段时间内根本没有向leader副本发出同步请求
  • follower副本进程同步过慢,一段时间都无法赶上leader副本

注意:

  • 通过副本因子的方式来增加的副本在赶上leader副本之前也是失效副本。
  • 一个follower副本由于某些原因宕机下线之后在上线,在赶上leader副本之前也是失效副本。

# 2、ISR的伸缩

kafka启动的时候会开启和ISR相关的定时任务(isr-expiration和isr-change-propagation)

  • isr-expiration会周期性检测每个分区是否需要缩减ISR集合,当检测到ISR集合中存在失效副本时,就会收缩ISR集合,当ISR集合发生变更后,会将变更后的记录缓存到isrChangeSet
  • isr-change-propagation会周期性检查isrChangeSet,如果发现isrChangeSet中有ISR集合的变更记录,就会创建一个持久顺序节点。

# 3、LEO和HW

  • HW:High Watermark
  • LW:Low Watermark
  • LEO: Last End Offset

现在来分析消息同步过程上诉属性的变化,假设此时leader副本的LEO增加到5,HW为0:

follower副本开始第一次拉取

image-20230911160157428

leader副本返回给follower副本相应的信息,并且带有自身的HW,两个副本接受消息之后,更新各自的LEO为3和4,并且更新自身的HW(LEW和HW最小值)

follower副本开始第二次拉取

image-20230911160421151

这个时候会告诉leader副本各自的LEO,然后leader副本计算最新的HW(min(15,3,4) = 3)

image-20230911160545007

leader副本接受消息之后,再把最新的HW传递给follower副本,follower副本更新HW。

# 4、Leader Epoch的介入

背景1 - 消息丢失

现在假设有两个副本A和B,初始状态如下,其中B是leader副本:

image-20230911161748682

现在假设A宕机,A重启之后,由于HW是0,会把m2这条消息给丢失,此时它会找leader副本进行同步,假设同步的时候B也宕机了,那么现在的leader副本就是A了。

当B重启的时候,B就成了follower副本不能比leader副本高,所以m2这条消息也要丢失。

image-20230911162637466

解决这个办法的一种方法就是follower副本恢复之后,在收到leader副本消息之前,不要截断消息,但是这样存在消息不一致的情况。

背景2 - 消息不一致

假设A和B副本情况如下,其中副本A是leader副本,两者重启之后,B副本先恢复过来,成为leader副本:

image-20230911162949901

此时B副本新来一条消息,并且把HW修改为2:

image-20230911163201573

此时A和B副本的HW都是2,但是消息不一样。

Leader Epoch应对数据丢失

image-20230911165429307

和之前一样,A宕机重启后,不是先急着截断日志,而是先给B发送请求,B这个时候会去查询LEO,A发现LEO和副本B的LEO相同,就不需要截断日志。

Leader Epoch应对数据不一致

现在假设副本A和副本B同时宕机,其中副本A为leader副本:

image-20230911191226146

之后重启过程中,B先恢复成为了Leader副本,并且写入了新的数据m3,

image-20230911191400567

等到A恢复之后,给B发送请求,发现现在offset为1,A就截断日志并删除m2:

image-20230911191739847

# 二、为什么不支持读写分离

在kafka中,生产者写入消息、消费者读取消息的操作都是和leader副本进行交互的,并非读写分离的方式,其中读写分离存在两个问题:

  • 数据一致性问题:数据从主节点到从节点必然会有一个延时的时间窗口,这个时间窗口会导致主从节点
  • 延时问题

# 三、日志同步机制

略

# 四、可靠性分析

# 1、分区副本保证可靠

就kafka而言,越多的副本数能够保证数据的可靠性,不过副本数越多也会引起磁盘、网络带宽的浪费,同时引起性能的下降。

设置副本数为3就可以满足绝大多数场景对可靠性的要求,而对可靠性要求更高的场景下,一般设置副本数为5就行

# 2、ack机制

除了依靠副本数来支持可靠性,ack机制也可以一定程度提高消息的可靠性:

  • ack为1,相当于只有leader副本接受到消息后就告知生产者完成了,如果在还没有同步给其他副本的时候,leader副本发生宕机,那么这条消息就丢失了

  • 对于ack为1,相当于是异步方式发送消息,不需要等待确认,就告知生产者完成了,这种情况最不可靠。

  • 对于ack为-1,是当消息成功写入leader副本之后,并且在ISR集合的所有副本同步完成后才告知生产者完成,这种情况最为可靠。

kafka通过retries参数可以配置重试的次数。

下面对ack为-1进行如下分析:

由于这种机制下,要求所有ISR集合中的副本全部同步完成之后才告知生产者同步完成,如果出现leader副本的消息流入速度很快,而follower副本同步速度很慢,那么在某一个临界点所有的follower副本剔除ISR集合,那么ISR中就只有一个leader副本,这种情况相当于是ack=1的情况。

针对这种情况,要指定ISR集合中最小的副本数不能为1

# 参考

官方文档 (opens new window)

图解Kafka之实战指南 (opens new window)

#消息队列
上次更新: 2024/06/29, 15:13:44
日志存储
深入服务端

← 日志存储 深入服务端→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式