首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式专题|最近一直死磕kafka设计原理,都肝吐了

分布式专题|最近一直死磕kafka设计原理,都肝吐了

作者头像
AI码师
发布2020-12-11 14:29:25
5390
发布2020-12-11 14:29:25
举报

点击上方蓝字关注我们 文末有惊喜

kafka架构图

在这里插入图片描述

kafka核心控制器

定义

在kafka集群中,会选举出一个broker作为控制器(controller),负责管理集群中所有的分区和副本的状态;

职责

  1. 监听broker变化,通过监听Zookeeper中的/brokers/ids/ 节点方式来实现
  2. 监听topic变化,通过监听Zookeeper中的/brokers/topics节点方式来实现,实时监听topic变化
  3. 管理topic、partition、broker相关的信息
  4. 更新数据的元数据信息,同步到其他的broker节点

选举过程

broker控制器选举的原理是借助于zookeeper的临时节点实现:kafka集群启动时,每个broker都会尝试争当控制器,都会往zookeeper的controller节点注册自己,但是由于zookeerper的特性,如果节点已经创建过,再创建就会失败,所以只会有一个broker创建成功,那么创建成功的broker就会成为控制器;此外其他broker都会监听这个controller节点

在这里插入图片描述

由于controller是临时节点,当控制器broker挂机之后,就会断开与zookeeper的会话连接,临时节点也会消失,其它节点监听到controller节点消失后,就会重新争取controller节点。

Partition副本选择机制

当controller感知到副本leader所在的broker宕机之后,会在当前副本所在的副本列表中选出第一个副本所在的broker作为副本leader,并且要保证这个broker一定要在副本的ISR(存活的副本broker)集合中,如果第一个不存在,则继续尝试第二个第三个,直到满足;不知道为啥kafka作者为什么不直接在ISR集合里面挑,非得多一步操作

消费者消费的offset如何记录?

每个消费者消费所在分区的offset都会记录在kafka的内部topic中(__consumer_offsets),kafka默认会为这个topic创建50个分区,用来抵抗高并发;提交到这个topic的时候,key是当前消费者所处的消费组ID+topic+分区号,value就是当前offset的值,那么kafka会把这个消息发送到哪个分区呢,是由以下公式决定的:hash(consumer group id) % __consumer_offsets主题的分区数(默认50),consumer每次消费前都会从这里获取offset值;

什么是消费者rebalance?

定义

当某个消费组中的消费者挂掉或退出之后,此时就会自动把分配给它的分区分配给其它消费者(没有被指定消费分区的消费者),不仅如此,当有新的消费者加入后也会触发rebalance操作。

Rebalance过程

  1. 选择组协调器(GroupCoordinato) 因为每个消费组的消费offset提交到的分区是确定的,即通过公式hash(consumer group id) % __consumer_offsets主题的分区数计算而来,所以kafka就直接把这个提交的分区所在的副本leader当作组协调器。
  2. 加入消费组 JOIN GROUP 在选好组协调器之后,接下来就是加入消费组阶段,在此阶段的消费者会向 GroupCoordinator 发送 JoinGroupRequest 请求,并处理响应,然后GroupCoordinator 从一个consumer group中选择第一个加入group的consumer作为leader(消费组协调器),把consumer group情况发送给这个leader,接着这个leader会负责制定分区方案。
  3. SYNC GROUP consumer leader通过给GroupCoordinator发送SyncGroupRequest,接着GroupCoordinator就把分区方案下发给各个consumer,他们会根据指定分区的leader broker进行网络连接以及消息消费。

Rebalance分区分配策略

通过在消费者客户端配置参数partition.assignment.strategy 来设置分配策略,默认为range

  • range 假如现在有10个分区,4个消费者,那么第一步计算平均每个消费者分配的分区数:10/4 = 2,这样每个消费者分到两个分区,还剩余 2 个分区,那么把剩下的两个分区分别分给前面两个消费者,最终分配结果: 第一个消费者:0,1,2 第二个消费者:3,4,5 第三个消费者:6,7 第四个消费者:8,9
  • round-robin(轮询分配) 很容易理解,同上有10个分区,4个消费者: 第一个消费者:0,4,8 第二个消费者:1,5,9 第三个消费者:2,6 第四个消费者:3,7
  • sticky 假如目前分区分配如下: 第一个消费者:0,4,8 第二个消费者:1,5,9 第三个消费者:2,6 第四个消费者:3,7 现在如果第四个消费者挂机,则重新分配后如下:第一个消费者:0,4,8,7 第二个消费者:1,5,9 第三个消费者:2,6,3 如果两个规则冲突,优先保证第一个原则
    • 分区尽可能均匀
    • 分区的分配尽可能与上次分配相同

producer发布消息过程

  1. 写入方式 生产者使用push模式将消息发布到broker中,每条消息都被追加到partition中,属于顺序写磁盘
  2. broker根据以下规则将消息发布到指定分区中
  • 如果指定分区,则直接发到指定分区
  • 如果没有指定分区,则根据key进行hash 取模分区数,得到分区
  • key和partition 都没有指定,则使用轮训方式
  1. 发送流程

重要参数acks解释:

  • ack=0 指producer把消息发送出去,不需要等待任何回应,就认为消息发送成功
  • ack=1 指producer把消息发送到leader之后,leader把消息写入磁盘,并回复producer ACK,则producer就认为消息发送成功
  • ack=all/-1 指producer把消息发送到leader之后,leader写入磁盘后,还要等待其他副本的ACK,只有都写成功了,leader才给producer回复ACK,这时producer才认为消息发送成功
  1. producer从zookeeper的state节点中中找到副本leader所在brokerid
  2. producer把消息发送到该leader
  3. leader将消息写入log
  4. follower从leader拉取消息,写入本地log后向leader回复ack
  5. leader收到所有ISR里面的副本恢复ACK之后,增加HW,并向producer发送ACK

HW与LEO到底是个啥?

HW俗称高水位,又称消费能消费到的最大offset,LEO是broker内部能看到的最大offset, 那么这个最大的offset是怎么产生的呢?正常情况下,LEO的offset和HW的offset是相同的 当有新消息发送到leader之后,leader的LEO就会增加,这个时候LEO的offset就与HW的offset不一样了,接下来副本开始拉取leader消息,对应的副本LEO也会增加,等到最后一个副本同步完成消息之后,LEO和HW的offset就会一致,这样做的目的是什么呢?是为了「数据的一致性」,保证消息同步完成后才能对消费者可见。

扫码关注我们,了解最新内容

成长心路 | 优质书单 | 面试资料

牛人故事 | 前沿技术 | 视频教程

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 乐哉开讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • kafka架构图
  • kafka核心控制器
    • 定义
      • 职责
        • 选举过程
          • Partition副本选择机制
          • 消费者消费的offset如何记录?
          • 什么是消费者rebalance?
            • 定义
              • Rebalance过程
                • Rebalance分区分配策略
                • producer发布消息过程
                  • HW与LEO到底是个啥?
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档