基于Kafka 0.9.0版

ReplicaManager需要做什么

Replicated Logs

Kafka的partition可以看成是一个replicated log, 每个replica就是这个replicated log其中的一个log。多个replica是为了容忍机器故障,因此同一个partition的不同replica需要被分配到不同的broker上。所以,对于一个partition,broker id即可唯一代表一个replica,也被当作replica id。

为了一致性,Kafka在同一个partition的replicas中选出一个作为leader,由它接受client的所有读写请求,而其它的replica作为follower,从leader处拉取数据,leader作为唯一的"source of truth"。在有些情况下,follower会truncate自己的log(这个log和以下的log都是指"replicated log"这个概念里的log),然后重新从leader处抓取数据,以求与leader一致(下面会讲到)。

leader和follower的角色区分,也主要是ReplicaManager来实现。具体地讲

  • leader

    • leader会接受client的读取请求和写入请求。
    • leader需要接受follwer抓取message的请求,返回message给follower
    • leader需要维护ISR(in-sync replicas)列表。“保持同步”的含义有些复杂,0.9之前版本对这个概念的定义与0.9不同,详情参见KIP-16 - Automated Replica Lag Tuning。0.9版本,broker的参数replica.lag.time.max.ms用来指定ISR的定义,如果leader在这么长时间没收到follower的拉取请求,或者在这么长时间内,follower没有fetch到leader的log end offset,就会被leader从ISR中移除。ISR是个很重要的指标,controller选取partition的leader replica时会使用它,因此leader选取ISR后会把结果记到Zookeeper上。
    • leader需要维护high watermark。high watermark以下的消息就是所有ISR列表里的replica都已经读取的消息(注意,并不是所有replica都一定有这些消息,而只是ISR里的那些才肯定会有)。因此leader会根据follower拉取数据时提供的offset和ISR列表,决定HW,并且在返回给follower的请求中附带最新的HW。
  • follower
    • follower需要不停地去leader处拉取最新的log
    • follower需要根据leader在fetch reponse中提供的HW,更新自己本地保存的leader的HW信息。在它过行leader或follower转变时,会用到这个HW。

HW与LEO

HW、ISR以及leader对于partition这个多副本系统算是一种元数据。ISR和leader确要在controller和所有replica之间保持一致,HW需要在leader和follower之间保持一致,因为在leader转换的时候,HW是安全线。

下面明确一下high watermark和log end offset在源码里的意义

HW  high watermark  offset的数据小于被认为是commit的,注意,offset为high watermark的message并不是commit的。

LEO log end offset 这个replica的log里最后一条消息的下一条消息的offset

这些数据根据实际需求,以不同的方式在Kafka中传递:

  • HW。随着follower的拉取进度的即时变化,HW是随时在变化的。follower总是向leader请求自己已有messages的下一个offset开始的数据,因此当follower发出了一个fetch request,要求offset为A以上的数据,leader就知道了这个follower的log end offset至少为A。此时就可以统计下ISR里的所有replica的LEO是否已经大于了HW,如果是的话,就提高HW。同时,leader在fetch本地消息给follower时,也会在返回给follower的reponse里附带自己的HW。这样follower也就知道了leader处的HW(但是在实现中,follower获取的只是读leader本地log时的HW,并不能保证是最新的HW)。但是leader和follower的HW是不同步的,follower处记的HW可能会落后于leader。
  • ISR以及leader。 在需要选举leader的场景下,leader和ISR是由controller决定的。在选出leader以后,ISR是leader决定。如果谁是leader和ISR只存在于ZK上,那么每个broker都需要在Zookeeper上监听它host的每个partition的leader和ISR的变化,这样效率比较低。如果不放在Zookeeper上,那么当controller fail以后,需要从所有broker上重新获得这些信息,考虑到这个过程中可能出现的问题,也不靠谱。所以leader和ISR的信息存在于Zookeeper上,但是在变更leader时,controller会先在Zookeeper上做出变更,然后再发送LeaderAndIsrRequest给相关的broker。这样可以在一个LeaderAndIsrRequest里包括这个broker上有变动的所有partition,即batch一批变更新信息给broker,更有效率。另外,在leader变更ISR时,会先在Zookeeper上做出变更,然后再修改本地内存中的ISR。

Hight Watermark Checkpoint

以外,由于HW是随时变化的,如果即时更新到Zookeeper,会带来效率的问题。而HW是如此重要,因此需要持久化,ReplicaManager就启动了单独的线程定期把所有的partition的HW的值记到文件中,即做highwatermark-checkpoint。

Epoch

除了leader,ISR之外,在replica系统中还有其它三个对于一致性有重要作用的参数:controller epoch、leader epoch和zookeeper version。

  • controller epoch: 当新的controller开始工作后,旧的controller可能还在工作,这时就会有两个自认为是的controller,那么broker该听哪个的呢?cpmtroller epoch是一个整数,记在Zookeeper的/controller_epoch path的数据中,当新的controller当选后,它更新Zookeeper中的这个数据,把这个整数的值+1,并且以每个命令中都附带上controller epoch。这样broker收到一个controller的命令后,就与自己内存中保存的controller epoch比较,如果命令中的值小于内存中的值,就代表是旧的controller的命令,如果大于内存中的值,就更新内存中的controller epoch为新值,并且执行命令。
  • leader epoch: 对于同一个controller,也存在它的LeaderAndIsrRequest以错误的顺序到达broker的可能,这样broker就可以在检查controller的epoch之后,再检查leader epoch,以确认该执行哪个命令。
  • zkVersion 对于在zookeeper path中存储的controller epoch, leaderAndIsr信息进行更新时,始终都得进行条件更新,以避免产生竞态。比如,在controller读取Zookeeper上的leaderAndIsr信息后,更新leaderAndIsr信息前,如果leader更改了ISR的信息,而controller以更改前的ISR进行leader选举的话,就可能会产生异常状态;或者在controller更新完leaderAndIsr之后,旧的leader又去更新zk上的这个数据,也会使集群不一致。所以,就需要zkVersion来进行条件变更。controller和replica在内存中存储上一次状态更新时读取到的zkVersion,当它依据此状态做出决定时,需要带上这个zkVersion做条件更新,以保证根据旧状态做出的更新不会生效。这种条件更新是使用的kafka.utils.ZkUtils的conditionalUpdatePersistentPath方法。

由这三个版本号共同作用,Kafka基本都保证对于leader, ISR, controller的认知在各个broker间不会出现大问题(但是还会有bug和潜在的问题导致认知不一致)。

update MetadataCache

此外,当broker收到UpdateMetadataRequest时,它会把这个request交给ReplicaManager处理,而ReplicaManager在确定UpdateMetadataRequest的controller epoch有效之后,就会交由MetadataCache来处理。之所以不直接收MetadataCache处理,可能是ReplicaManager处会保存controller epoch, 不过MetadataCache内部也可能获取controller epoch,只是没有做为单独的一个field保存起来。这样做显得有些混乱,不知道是什么原因。

Kafka之ReplicaManager(1)的更多相关文章

  1. Kafka单节点及集群配置安装

    一.单节点 1.上传Kafka安装包到Linux系统[当前为Centos7]. 2.解压,配置conf/server.property. 2.1配置broker.id 2.2配置log.dirs 2. ...

  2. Kafka运维填坑(转)

    前提: 只针对Kafka 0.9.0.1版本; 说是运维,其实偏重于问题解决; 大部分解决方案都是google而来, 我只是作了次搬运工; 有些问题的解决方案未必一定是通用的, 若应用到线上请慎重; ...

  3. Linux Kafka源码环境搭建

    本文主要讲述的是如何搭建Kafka的源码环境,主要针对的Linux操作系统下IntelliJ IDEA编译器,其余操作系统或者IDE可以类推. 1.安装和配置JDK确认JDK版本至少为1.7,最好是1 ...

  4. Kafka 0.8 Controller设计机制和状态变化

    在kafka集群中,其中一个broker server作为中央控制器Control,负责管理分区和副本状态并执行管理着这些分区的重新分配. 下面说明如何通过中央控制器操作分区和副本的状态. 名词解释 ...

  5. 5 Kafka 应用问题经验积累

    16.Kafka 配置文件同步 为了给kafka的进程添加GC日志信息,方便在以后重启的时候,加入GC日志: 修改bin/kafka-server-start.sh: export KAFKA_OPT ...

  6. kafka的安装及基本使用

    1.安装zookeeper # 解压缩 [root@localhost zookeeper]# .tar.gz [root@localhost zookeeper]# zk_simple # 复制zo ...

  7. kafka报错:Invalid message size: 0

    现象 1.kafka topic 部分分区积压 2.问题kafka 节点上一直报错:java.lang.IllegalStateException: Invalid message size: 0 [ ...

  8. kafka的安装和初步使用

    简介 最近开发的项目中,kafka用的比较多,为了方便梳理,从今天起准备记录一些关于kafka的文章,首先,当然是如何安装kafka了. Apache Kafka是分布式发布-订阅消息系统. Apac ...

  9. Kafka压测— 搞垮kafka的方法(转)

    分布式系统故障场景梳理方法: 场景梳理逻辑关系: 单点硬件故障→单点进程故障类型→集群影响→集群故障场景 第三方依赖故障→集群依赖关系→集群影响→集群故障场景 业务场景→集群负载/错误影响→集群故障场 ...

随机推荐

  1. 20141128—JavaScript对象

    JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... String 对象的 length 属性来获得字符串的长度: var message="Hello World!& ...

  2. WCF之实例模型

    PerCall. 为每次调用创建新的服务对象. 内存使用量最小,增加整体的吞吐量. 状态不保存,服务实例及时释放. 单例的状态没有办法保存.所以应使用数据库或者文件或者全局变量来保存服务实例的状态.如 ...

  3. 20140527-ASP.NET中尖括号百分号用法

    1.<%=%> 里面放的变量名,如:<div><h1>Hello World</h1><p>Welcome to Beginning ASP ...

  4. [javascript|基本概念|Underfined]学习笔记

    Underfined类型的值:underfined(只有一个) 1/声明未初始化 e.g.:var msg;-->msg == underfined:true 2/申明并值初始化为underfi ...

  5. 跨frame操作dom元素

    今天,一群友问到跨frame操作dom元素的问题.于是写了个demo,在此发表在博客里面,供其他同道中人参考! 创建child.html内容如下: <!DOCTYPE HTML PUBLIC & ...

  6. C++ Double Ended Queues(双向队列)

    双向队列和向量很相似,但是它允许在容器头部快速插入和删除(就像在尾部一样). Constructors 创建一个新双向队列 Operators 比较和赋值双向队列 assign() 设置双向队列的值 ...

  7. C++ 11 之Lambda

    1.Lambda表达式来源于函数式编程,说白就了就是在使用的地方定义函数,有的语言叫“闭包”,如果 lambda 函数没有传回值(例如 void ),其回返类型可被完全忽略. 定义在与 lambda ...

  8. 编译内核模块出现error: negative width in bit-field 错误

    今天在写一个简单的内核测试模块的时候出现了一个挺奇怪的问题,网上查了一下也没人解决,自己试了好久终于解决了,所以分享出来供大家参考,先贴出源码: /************************** ...

  9. 躲避球游戏ios源码

    躲避球游戏源码,有限源码是一个基于cocos2d的躲避球游戏源码的,并且还引用了大家熟悉google广告的,进行推广,已经还有带game center等,游戏操作很简单,用手指按住物体,然后移动物体避 ...

  10. 【Qt】Qt Creator快捷键【转】

    简介 Qt Creator中提供了各种快捷键来加快开发进程. 如果需要查看或自定义快捷键,选择工具->选项->环境->键盘.快捷键按类别列出,可以在过滤器(Filter)处输入命令名 ...