滴滴二面:Kafka是如何读写副本消息的?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 无论是读取副本还是写入副本,都是通过底层的Partition对象完成的,而这些分区对象全部保存在上节课所学的allPartitions字段中。可以说,理解这些字段的用途,是后续我们探索副本管理器类功能的重要前提。

无论是读取副本还是写入副本,都是通过底层的Partition对象完成的,而这些分区对象全部保存在上节课所学的allPartitions字段中。可以说,理解这些字段的用途,是后续我们探索副本管理器类功能的重要前提。


现在,我们就来学习下副本读写功能。整个Kafka的同步机制,本质上就是副本读取+副本写入,搞懂了这两个功能,你就知道了Follower副本是如何同步Leader副本数据的。


appendRecords-副本写入


向副本底层日志写入消息的逻辑就实现在ReplicaManager#appendRecords。


Kafka需副本写入的场景:


生产者向Leader副本写入消息


Follower副本拉取消息后写入副本


仅该场景调用Partition对象的方法,其余3个都是调用appendRecords完成


消费者组写入组信息


事务管理器写入事务信息(包括事务标记、事务元数据等)


appendRecords方法将给定的一组分区的消息写入对应Leader副本,并根据PRODUCE请求中acks的设置,有选择地等待其他副本写入完成。然后,调用指定回调逻辑。


1.png


appendRecords向副本日志写入消息的过程:

2.png




执行流程

可见,appendRecords:


实现消息写入的方法是appendToLocalLog

判断是否需要等待其他副本写入的方法delayedProduceRequestRequired

appendToLocalLog写入副本本地日志

3.png

利用Partition#appendRecordsToLeader写入消息集合,就是利用appendAsLeader方法写入本地日志的。


delayedProduceRequestRequired


判断消息集合被写入到日志之后,是否需要等待其它副本也写入成功:


private def delayedProduceRequestRequired(

 requiredAcks: Short,

 entriesPerPartition: Map[TopicPartition, MemoryRecords],

 localProduceResults: Map[TopicPartition, LogAppendResult]): Boolean = {

 requiredAcks == -1 && entriesPerPartition.nonEmpty &&

   localProduceResults.values.count(_.exception.isDefined) < entriesPerPartition.size

}


若等待其他副本的写入,须同时满足:


requiredAcks==-1

依然有数据尚未写完

至少有一个分区的消息,已成功被写入本地日志

2和3可结合来看。若所有分区的数据写入都不成功,则可能出现严重错误,此时应不再等待,而是直接返回错误给发送方。


而有部分分区成功写入,部分分区写入失败,则可能偶发的瞬时错误导致。此时,不妨将本次写入请求放入Purgatory,给个重试机会。


副本读取:fetchMessages


ReplicaManager#fetchMessages负责读取副本数据。无论:


Java消费者API

Follower副本

拉取消息的主途径都是向Broker发FETCH请求,Broker端接收到该请求后,调用fetchMessages从底层的Leader副本取出消息。


fetchMessages也可能会延时处理FETCH请求,因Broker端必须要累积足够多数据后,才会返回Response给请求发送方。

4.png5.png





整个方法分为:


读取本地日志


6.png

首先判断,读取消息的请求方,就能确定可读取的范围了。


fetchIsolation,读取隔离级别:


对Follower副本,它能读取到Leader副本LEO值以下的所有消息

普通Consumer,只能“看到”Leader副本高水位值以下的消息

确定可读取范围后,调用readFromLog读取本地日志上的消息数据,并将结果赋给logReadResults变量。readFromLog调用readFromLocalLog,在待读取分区上依次调用其日志对象的read方法执行实际的消息读取。


根据读取结果确定Response


根据上一步读取结果创建对应Response:

7.png



根据上一步得到的读取结果,统计可读取的总字节数,然后判断此时是否能够立即返回Reponse。


副本管理器读写副本的两个方法appendRecords和fetchMessages本质上在底层分别调用Log的append和read方法,以实现本地日志的读写操作。完成读写操作后,这两个方法还定义了延时处理的条件。一旦满足延时处理条件,就交给对应Purgatory处理。


从这俩方法可见单个组件融合一起的趋势。虽然我们学习单个源码文件的顺序是自上而下,但串联Kafka主要组件功能的路径却是自下而上。


如副本写入操作,日志对象append方法被上一层的Partition对象中的方法调用,而后者又进一步被副本管理器中的方法调用。我们按自上而下阅读了副本管理器、日志对象等单个组件的代码,了解了各自的独立功能。


现在开始慢慢地把它们融合一起,构建Kafka操作分区副本日志对象的完整调用路径。同时采用这两种方式来阅读源码,就能更高效弄懂Kafka原理。


总结


Kafka副本状态机类ReplicaManager读写副本的核心方法:


appendRecords:向副本写入消息,利用Log#append方法和Purgatory机制实现Follower副本向Leader副本获取消息后的数据同步操作

fetchMessages:从副本读取消息,为普通Consumer和Follower副本所使用。当它们向Broker发送FETCH请求时,Broker上的副本管理器调用该方法从本地日志中获取指定消息

8.png

目录
相关文章
|
4月前
|
消息中间件 SQL 分布式计算
大数据-74 Kafka 高级特性 稳定性 - 控制器、可靠性 副本复制、失效副本、副本滞后 多图一篇详解
大数据-74 Kafka 高级特性 稳定性 - 控制器、可靠性 副本复制、失效副本、副本滞后 多图一篇详解
44 2
|
4月前
|
消息中间件 JSON 大数据
大数据-65 Kafka 高级特性 分区 Broker自动再平衡 ISR 副本 宕机恢复再重平衡 实测
大数据-65 Kafka 高级特性 分区 Broker自动再平衡 ISR 副本 宕机恢复再重平衡 实测
116 4
|
7月前
|
消息中间件 存储 监控
深入理解Kafka核心设计及原理(六):Controller选举机制,分区副本leader选举机制,再均衡机制
深入理解Kafka核心设计及原理(六):Controller选举机制,分区副本leader选举机制,再均衡机制
130 1
|
7月前
|
消息中间件 算法 NoSQL
面试题Kafka问题之Kafka保证系统的可用性如何解决
面试题Kafka问题之Kafka保证系统的可用性如何解决
60 0
|
7月前
|
消息中间件 算法 Kafka
面试题Kafka问题之Kafka的副本消息同步如何解决
面试题Kafka问题之Kafka的副本消息同步如何解决
115 4
|
7月前
|
消息中间件 Kafka 数据库
面试题Kafka问题之Kafka中的消息(Message)定义如何解决
面试题Kafka问题之Kafka中的消息(Message)定义如何解决
52 1
|
7月前
|
消息中间件 人工智能 Kafka
微服务数据问题之MetaQ和Kafka在选择读写技术时考虑因素如何解决
微服务数据问题之MetaQ和Kafka在选择读写技术时考虑因素如何解决
|
7月前
|
消息中间件 存储 Kafka
微服务分布问题之Kafka分区的副本和分布如何解决
微服务分布问题之Kafka分区的副本和分布如何解决
|
7月前
|
消息中间件 Kafka 程序员
Kafka内幕:详解Leader选举与副本同步的那些事儿
大家好,我是小米,今天给大家带来一篇关于 Kafka 核心机制的深度解析文章。本文将详细讲解 Kafka 的 Leader 选举、副本消息同步以及相关概念 LEO 和 HW,帮助大家更好地理解和应用 Kafka,提升处理分布式系统的能力。快来一起学习吧!
692 0
|
8月前
|
消息中间件 Kafka 程序员
Kafka面试必备:深度解析Replica副本的作用与机制
**Kafka的Replica副本是保证数据可靠性的关键机制。每个Partition有Leader和Follower副本,Leader处理读写请求及管理同步,Follower被动同步并准备成为新Leader。从Kafka 2.4开始,Follower在完全同步时也可提供读服务,提升性能。数据一致性通过高水位机制和Leader Epoch机制保证,后者更精确地判断和恢复数据一致性,增强系统容错能力。**
309 1