Kafka 0.8 副本同步机制理解
Kafka的普及在很大程度上归功于它的设计和操作简单,如何自动调优Kafka副本的工作,挑战之一:如何避免follower进入和退出同步副本列表(即ISR)。如果某些topic的部分partition长期处于“under replicated”状态,会增加数据丢失的概率。Kafka通过“多副本机制”实现高可用,当Kafka集群中一个Broker失效情况下仍然保证服务可用。
Kafka日志复制算法保证,如果leader发生故障或挂掉,一个新leader被选举并且客户端的消息成功写入。Kafka确保从同步副本列表中选举一个副本为leader。
0.副本知识
每个Partition有一个预写式日志文件,每个Partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到Partition中,Partition中的每个消息都有一个连续的序列号叫做offset, 确定它在分区日志中唯一的位置。
- leader处理对这个partition的所有读写请求。
- follower会去复制leader上的数据。
1. in sync 条件
Leader负责跟踪同步副本列表中所有follower滞后状态。
同步中的(in sync),Kafka判断一个节点是否活着有两个条件:
- 节点必须可以维护和ZooKeeper的连接,Zookeeper通过心跳机制检查每个节点的连接。——由参数
request.required.acks
决定,如果是这个参数生效而移除一个follower,说明这个follower 失效或者死亡。 - 如果节点是个follower,他必须能及时的同步leader的写操作,延时不能太久。—— 由参数
replica.lag.max.messages
决定的,如果是这个参数生效而移除一个follower,说明这个follow是一个“慢副本”。
- 一条消息只有被“in sync” list里的所有follower都从leader复制过去才会被认为已提交。这样就避免了部分数据被写进了leader,还没来得及被任何follower复制就宕机了,而造成数据丢失。
- 而对于producer而言,它可以选择是否等待消息commit,这可以通过request.required.acks来设置。
- 对于Consumer而言,只能看见被commit的消息。
1.1问题:
- 被移除后的under replica的follower 会继续拉取leader的数据,等追赶上之后,会被重新加入到“同步副本”。
- 一个消息什么时候被认为是提交的?(意味着可以被consumer消费)
- 直到follower Broker 从同步副本列表中移除
- 或者追赶上leader log end offset,最新的消息才会认为提交。
- 是什么原因导致分区的副本与leader不同步
- 慢副本:在一定周期时间内follower不能追赶上leader。最常见的原因之一是I / O瓶颈导致follower追加复制消息速度慢于从leader拉取速度。
- 卡住副本:在一定周期时间内follower停止从leader拉取请求。follower replica卡住了是由于GC暂停或follower失效或死亡。
- 新启动副本:当用户给主题增加副本因子时,新的follower不在同步副本列表中,直到他们完全赶上了leader日志。
- kafka-0.8 相关集群参数配置
replica.lag.time.max.ms=10000 // 根据队列流量大小和集群负载情况做出判断并设置一个合适值
replica.lag.max.messages=4000
2. Leader 选举
当leader宕机了,怎样在follower中选举出新的leader?
- 实际上,leader election算法非常多,比如Zookeper的Zab, Raft和Viewstamped Replication。而Kafka所使用的leader election算法更像微软的PacificA算法。
一种非常常用的选举leader的方式是“majority vote”(“少数服从多数”),但Kafka并未采用这种方式。这种模式下,如果我们有2f+1个replica(包含leader和follower),那在commit之前必须保证有f+1个replica复制完消息,为了保证正确选出新的leader,fail的replica不能超过f个。---(类似pasox算法)
- 缺点:需要的replica的数量太多,造成性能瓶颈。
leader 选举算法
Kafka在Zookeeper中动态维护了一个ISR(in-sync replicas) set,这个set里的所有replica都跟上了leader,只有ISR里的成员才有被选为leader的可能。在这种模式下,对于f+1个replica,一个Kafka topic能在保证不丢失已经ommit的消息的前提下容忍f个replica的失败。在大多数使用场景中,这种模式是非常有利的。
在ISR中至少有一个follower时,Kafka可以确保已经commit的数据不丢失,但如果某一个partition的所有replica都挂了,就无法保证数据不丢失了。这种情况下有两种可行的方案:
- 等待ISR中的任一个replica“活”过来,并且选它作为leader
- 选择第一个“活”过来的replica(不一定是ISR中的)作为leader
这就需要在可用性和一致性当中作出一个简单的平衡。(Kafka0.8.*使用了第二种方式。)
3.平衡partition
- 默认情况下,kafka以RoundRobin方式写各个partition,让各个partition的消息量均衡。
- 平衡partition的leader在所有的broker上。
优化leadership election的过程也是很重要的,毕竟这段时间相应的partition处于不可用状态。
一种简单的实现是暂停宕机的broker上的所有partition,并为之选举leader。实际上,Kafka选举一个broker作为controller,这个controller通过watch Zookeeper检测所有的broker failure,并负责为所有受影响的parition选举leader,再将相应的leader调整命令发送至受影响的broker,过程如下图所示。
4.Controller
负责leader 选举,每个broker都可成为Controller。
它可以批量的通知leadership的变化,从而使得选举过程成本更低。如果controller失败了,所有broker都会尝试在Zookeeper中创建/controller->{this broker id},如果创建成功(只可能有一个创建成功),则该broker会成为controller。
Controller对Broker failure的处理过程
- Controller在Zookeeper的/brokers/ids节点上注册Watch。一旦有Broker宕机(本文用宕机代表任何让Kafka认为其Broker die的情景,包括但不限于机器断电,网络不可用,GC导致的Stop The World,进程crash等),其在Zookeeper对应的Znode会自动被删除,Zookeeper会fire Controller注册的Watch,Controller即可获取最新的幸存的Broker列表。
- Controller决定set_p,该集合包含了宕机的所有Broker上的所有Partition。
- 对set_p中的每一个Partition:
3.1 从/brokers/topics/[topic]/partitions/[partition]/state读取该Partition当前的ISR。
3.2 决定该Partition的新Leader。如果当前ISR中有至少一个Replica还幸存,则选择其中一个作为新Leader,新的ISR则包含当前ISR中所有幸存的Replica。否则选择该Partition中任意一个幸存的Replica作为新的Leader以及ISR(该场景下可能会有潜在的数据丢失)。如果该Partition的所有Replica都宕机了,则将新的Leader设置为-1。
3.3 将新的Leader,ISR和新的leader_epoch及controller_epoch写入/brokers/topics/[topic]/partitions/[partition]/state。注意,该操作只有Controller版本在3.1至3.3的过程中无变化时才会执行,否则跳转到3.1。
- 直接通过RPC向set_p相关的Broker发送LeaderAndISRRequest命令。Controller可以在一个RPC操作中发送多个命令从而提高效率.
Broker failover顺序图如下所示。
5. 消息保障
kafka能够保障以下两点:
- At most once 消息可能会丢,但绝不会重复传输
- At least once 消息绝不会丢,但可能会重复传输
对于Producer
- 发送不管,at most once
- 发送管ack,at least once
对于Consumer
- 记录Offset,at least once。
Kafka 0.8 副本同步机制理解的更多相关文章
- Kafka副本同步机制
引用自:http://blog.csdn.net/lizhitao/article/details/51718185 Kafka副本 Kafka中主题的每个Partition有一个预写式日志文件,每个 ...
- Kafka 0.8 NIO通信机制
一.Kafka通信机制的整体结构 同时,这也是SEDA多线程模型. 对于broker来说,客户端连接数量有限,不会频繁新建大量连接.因此一个Acceptor thread线程处理新建连接绰绰有余. K ...
- Kafka 0.8 Controller设计机制和状态变化
在kafka集群中,其中一个broker server作为中央控制器Control,负责管理分区和副本状态并执行管理着这些分区的重新分配. 下面说明如何通过中央控制器操作分区和副本的状态. 名词解释 ...
- Kafka 系列(五)—— 深入理解 Kafka 副本机制
一.Kafka集群 Kafka 使用 Zookeeper 来维护集群成员 (brokers) 的信息.每个 broker 都有一个唯一标识 broker.id,用于标识自己在集群中的身份,可以在配置文 ...
- kafka 日常使用和数据副本模型的理解
kafka 日常使用和数据副本模型的理解 在使用Kafka过程中,有时经常需要查看一些消费者的情况.Kafka健康状况.临时查看.同步一些数据,又由于Kafka只是用来做流式存储,又没有像Mysql或 ...
- 图文了解 Kafka 的副本复制机制
让分布式系统的操作变得简单,在某种程度上是一种艺术,通常这种实现都是从大量的实践中总结得到的.Apache Kafka 的受欢迎程度在很大程度上归功于其设计和操作简单性.随着社区添加更多功能,开发者们 ...
- Kafka 0.8: 多日志文件夹机制
kafka 0.7.2 中对log.dir的定义如下: log.dir none Specifies the root directory in which all log data is kept. ...
- Apache Kafka 0.9消费者客户端
当Kafka最初创建时,它与Scala生产者和消费者客户端一起运送.随着时间的推移,我们开始意识到这些API的许多限制.例如,我们有一个“高级”消费者API,它支持消费者组并处理故障转移,但不支持许多 ...
- Linux内核同步机制--转发自蜗窝科技
Linux内核同步机制之(一):原子操作 http://www.wowotech.net/linux_kenrel/atomic.html 一.源由 我们的程序逻辑经常遇到这样的操作序列: 1.读一个 ...
随机推荐
- JDBC详解系列(一)之流程
---[来自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- JDBC概述 使用JDBC也挺长 ...
- effective c++ 笔记 (41-44)
//---------------------------15/04/25---------------------------- //#41 了解隐式接口和编译期多态 { // 1:面向对象编 ...
- Meteor入门介绍
Meteor是什么 基于nodejs的实时web APP开发框架. Meteor能带来什么 简单的说,你可以用js搞定客户端.服务端的开发.另外,客户端.服务端的界限被极大的模糊.客户端的界面跟服务端 ...
- Js_数组操作
用 js有很久了,但都没有深究过js的数组形式.偶尔用用也就是简单的string.split(char).这段时间做的一个项目,用到数组的地方很多,自以为js高手的自己居然无从下手,一下狠心,我学!呵 ...
- 修炼内功_day01
测试六段: 测试第一段: - 能根据测试用例的描述步骤来执行用例 - 能对照用例的预期结果发现产品的问题 - 能够清晰准确的将问题记录下来后反馈给开发, ...
- Unity3D Shader 学习笔记(一):初识Shader
第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...
- 图-图的表示、搜索算法及其Java实现
1.图的表示方法 图:G=(V,E),V代表节点,E代表边. 图有两种表示方法:邻接链表和邻接矩阵 邻接链表因为在表示稀疏图(边的条数|E|远远小于|V|²的图)时非常紧凑而成为通常的选择. 如果需要 ...
- Linux 第三周 学习笔记和实验
姬梦馨 原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 常用调试参数 r(run) 开始运行程 ...
- Python Pandas read_csv报错
为实现文本去重(将前面采集的数据进行两两对比删除重复),写了以下代码. #-*- coding: utf-8 -*-import pandas as pd inputfile = 'e:/data/H ...
- 实训五(Cocos2dx-3.x 打包apk再理解)
问题说明:Unable to resolve target 'android-10' SDK版本与Cocos项目默认的版本不相符 如果只是执行 cocos compile -p android 只是执 ...