1 kafka consumer消费位移为什么从zookeeper改到kafka内部主题__consumer_offsets中?
kafka 0.9版本之前使用zookeeper保存offset,之后版本使用内部主题,网上有一个答案是kafka offset维护方式
主要的点是zookeeper引入了多余的网络通讯,broker需要多余的连接来访问offset,存储在broker端,可以减少该部分的IO损耗,简化设计
2 kafka是如何使用isr的?
kafka通过isr机制来维持数据的一致性,isr即in-sync replica,跟isr相关的参数有acks、min.insync.replicas、replica.lag.time.max.ms、replica.lag.max.messages(已移除)
isr由leader动态维护,当副本节点落后leader太多或者超时未请求同步时,将副本剔除isr集合,待副本同步后,会重新加入isr集合
acks:由客户端配置,表示多少个副本收到消息后,才认为消息写入成功,0相当于异步,all,相当于同步,生产环境中需要兼顾可用性和性能,一般配置acks=1
min.insync.replicas:控制消息成功写入最小副本数
replica.lag.max.messages(已移除):isr集合中副本落后leader的最大值,因为生产环境中很难定义这个阈值,0.9版本后移除了该参数
replica.lag.time.max.ms:isr集合中副本落后leader的最大时间间隔
3 kafka如何实现exactly-once语义?
exactly-once解释,即使生产者产生重复的消息,消费者也应该只收到一次消息,这也就是所谓的幂等
配置幂等通过配置enable.idempotence=true实现
实现:producer消息是分批发送,每个分批都有一个序号(单调递增),broker追踪分区的最大序号,当出现序号相等或者小于最大序号的,不写入topic
4 kafka使用isr来选主,具体选主流程是什么样的,是另外一个raft吗?还是有其他约束?
答:
1、大数据常用的选主机制
leader的选择方法非常多,大数据领域常用的的选举方法有如下集中
(1)Zab(zookeeper使用)
a、快速leader选举(leader election)
b、发现或者版本建立(epoch establish)
c、同步(follower从leader同步数据和状态)
d、广播(leader广播数据或状态到follower)
例如有3个节点需要选举leader,编号为1,2,3. 先启动1,选择自己为leader,然后启动2,首先也选择自己为leader。由于1,2都没有过半,选择编号大的为leader,所以1,2都选择2为leader。然后3启动后发现1,2都已经协商好且数量过半,于是3也选择2为leader,此时leader选择结束。
因为zab协议需要选择过半以上才能被选举为leader,所以zab协议需要奇数个机器参与选举(1,3,5,7一般不超过7个,因为zk一般同步元数据,所以负载不是很高,zk管理的节点通信负载才比较高,5或7个一般能处理大量的集群),一般为第二个节点启动后被选择为leader。
zookeeper进行选举时,有两个典型场景
1 启动时leader选举
2 运行过程中leader选举
(2)Raft协议
相关角色说明
leader:处理所有客户端交互,日志复制等,一般只有一个leader
Follower:类似选民,完全被动
Candidate:候选人,可以为选为一个新的领导,由管理员配置
启动时在集群中指定一些机器为candidate,然后candidate开始向其他机器(尤其是follower)拉票,当某一个candidate的票数超过半数,它就成为leader(同美国总统选举)。
两种选择算法的区别联系
(1)他们都是Paxos算法的变种。
(2)与zab协议不同的是,zab的每一个节点都有被选为leader的协议,raft协议必须从候选人中选择为leader。
2、常用选主机制的缺点
最简单的方式
由于kafka集群依赖zookeeper集群,所以最简单直观的方案是:所有的follower都在zookeeper上设置一个watch,一旦leader宕机,其对应的ephemeral znode(临时节点)会自动删除,此时所有follower都尝试创建该节点,而创建成功者(zookeeper保证只有一个能创建成功)即是新的leader,其他replica即为follower。
该方式有如下缺点:
a、脑裂(split-brain)
这是由于zookeeper的特性引起的,虽然zookeeper能保证所有的watch按顺序触发,但并不能保证同一时刻所有的replica看到的状态是一样的,这就可能造成不同的replica的响应不一致;(如由于网络原因部分选择的leader已经更新,但是其他follower由于网络原因没有看到,部分又选举出一个leader,导致一个集群出现两个leader)
b、羊(惊)群效应(herd effect)
如果宕机的哪个broker上的partition比较多,会造成多个watch被触发,造成集群类大量的调整(向羊群开一枪所有羊群四处奔散,造成网路资源和负载)。
c、zookeeper负载过重:每一个replica都要为此在zookeeper上注册一个watch,当集群规模增加到几千个partition时,zookeeper负载会过重。
3、kafka分区的选主机制
kafka如何解决以上选举机制的
kafka的leader election方案解决了上述问题,它在所有的broker中选出一个controller,所有的partition的leader选举都有controller决定。controller会将leader的改变直接通过RPC的方式(比zookeeper Queue的方式更高效)通知需要为此作为响应的broker。
原因:
1、不用zk选举,使用controller(Controller会将leader的改变通过rpc方式通知给follower),没有zk负载过重问题
2、也没有注册watch不会触发任何事件-惊群效应
3、leader失败是由一个Controller进行选举并不会产生任何通信,所以不会有脑裂的情况
问题:
(1)Controller是如何选举出来的
每一个broker都会在Controller path(/controller)上注册一个watch。当前controller失败时,对应的Controller path会自动消失(临时节点)。此时该watch被触发,所有活着的broker都会去竞选成为新的Controller(创建新的controller path),但是只有一个会竞选成功。竞选成功者成为新的leader。竞选失败则重新在新的Controller path上注册watch,因为zk的watch是一次性的,被触发一次之后即失效,所以需要重新注册。
(2)如何使用Controller进行partition选举
a、从zk中读取当前分区的所有ISR(in-sync-replicas)集合
b、调用配置的分区算法选择分区的leader
kafka选择分区算法:
i、NoOpLeaderSelector–偏爱分区(SR中的第一个),并将leader发送给为此做出改变的broker,
ii、offlinePartitionLeader–也是选择偏爱分区作为leader
iii、reassignedPartitionLeader
iii、preferredReplicaPartitionLeader
iiii、ControlledShutdownLeader
上面五中算法都使用偏爱分区作为leader,区别是选择leader之后所做的操作不同。