《我想进大厂》之kafka夺命连环11问(一)

wg204wg
发布于 2022-6-10 15:59
浏览
0收藏

 

干啥啥不行,看小说第一名。这不,好好写了一篇文章。

最近整理了一下文章目录,因为好早之前就有兄弟跟我说之前文章找不到,我也懒得整理,现在好好整了一下,发现有一篇文章写了一半我就放着了,抽空把他刚好补齐了一下,之前放着没写大概是很难想到从哪里凑这么多问题???

文章目录的话去看公众号菜单栏中间就有了,这样大家以后方便点。

说说你对kafka的理解
kafka是一个流式数据处理平台,他具有消息系统的能力,也有实时流式数据处理分析能力,只是我们更多的偏向于把他当做消息队列系统来使用。

如果说按照容易理解来分层的话,大致可以分为3层:

第一层是Zookeeper,相当于注册中心,他负责kafka集群元数据的管理,以及集群的协调工作,在每个kafka服务器启动的时候去连接到Zookeeper,把自己注册到Zookeeper当中

第二层里是kafka的核心层,这里就会包含很多kafka的基本概念在内:

record:代表消息

topic:主题,消息都会由一个主题方式来组织,可以理解为对于消息的一个分类

producer:生产者,负责发送消息

consumer:消费者,负责消费消息

broker:kafka服务器

partition:分区,主题会由多个分区组成,通常每个分区的消息都是按照顺序读取的,不同的分区无法保证顺序性,分区也就是我们常说的数据分片sharding机制,主要目的就是为了提高系统的伸缩能力,通过分区,消息的读写可以负载均衡到多个不同的节点上

Leader/Follower:分区的副本。为了保证高可用,分区都会有一些副本,每个分区都会有一个Leader主副本负责读写数据,Follower从副本只负责和Leader副本保持数据同步,不对外提供任何服务

offset:偏移量,分区中的每一条消息都会根据时间先后顺序有一个递增的序号,这个序号就是offset偏移量

Consumer group:消费者组,由多个消费者组成,一个组内只会由一个消费者去消费一个分区的消息

Coordinator:协调者,主要是为消费者组分配分区以及重平衡Rebalance操作

Controller:控制器,其实就是一个broker而已,用于协调和管理整个Kafka集群,他会负责分区Leader选举、主题管理等工作,在Zookeeper第一个创建临时节点/controller的就会成为控制器

第三层则是存储层,用来保存kafka的核心数据,他们都会以日志的形式最终写入磁盘中。

 《我想进大厂》之kafka夺命连环11问(一)-鸿蒙开发者社区
消息队列模型知道吗?kafka是怎么做到支持这两种模型的?
对于传统的消息队列系统支持两个模型:

点对点:也就是消息只能被一个消费者消费,消费完后消息删除
发布订阅:相当于广播模式,消息可以被所有消费者消费
上面也说到过,kafka其实就是通过Consumer Group同时支持了这两个模型。

如果说所有消费者都属于一个Group,消息只能被同一个Group内的一个消费者消费,那就是点对点模式。

如果每个消费者都是一个单独的Group,那么就是发布订阅模式。

实际上,Kafka通过消费者分组的方式灵活的支持了这两个模型。

能说说kafka通信过程原理吗?

  1. 首先kafka broker启动的时候,会去向Zookeeper注册自己的ID(创建临时节点),这个ID可以配置也可以自动生成,同时会去订阅Zookeeper的brokers/ids路径,当有新的broker加入或者退出时,可以得到当前所有broker信息
  2. 生产者启动的时候会指定bootstrap.servers,通过指定的broker地址,Kafka就会和这些broker创建TCP连接(通常我们不用配置所有的broker服务器地址,否则kafka会和配置的所有broker都建立TCP连接)
  3. 随便连接到任何一台broker之后,然后再发送请求获取元数据信息(包含有哪些主题、主题都有哪些分区、分区有哪些副本,分区的Leader副本等信息)
  4. 接着就会创建和所有broker的TCP连接
  5. 之后就是发送消息的过程
  6. 消费者和生产者一样,也会指定bootstrap.servers属性,然后选择一台broker创建TCP连接,发送请求找到协调者所在的broker
  7. 然后再和协调者broker创建TCP连接,获取元数据
  8. 根据分区Leader节点所在的broker节点,和这些broker分别创建连接
  9. 最后开始消费消息
     《我想进大厂》之kafka夺命连环11问(一)-鸿蒙开发者社区
    那么发送消息时如何选择分区的?

主要有两种方式:

  1. 轮询,按照顺序消息依次发送到不同的分区
  2. 随机,随机发送到某个分区
    如果消息指定key,那么会根据消息的key进行hash,然后对partition分区数量取模,决定落在哪个分区上,所以,对于相同key的消息来说,总是会发送到同一个分区上,也是我们常说的消息分区有序性。

很常见的场景就是我们希望下单、支付消息有顺序,这样以订单ID作为key发送消息就达到了分区有序性的目的。

如果没有指定key,会执行默认的轮询负载均衡策略,比如第一条消息落在P0,第二条消息落在P1,然后第三条又在P1。

除此之外,对于一些特定的业务场景和需求,还可以通过实现Partitioner接口,重写configure和partition方法来达到自定义分区的效果。

好,那你觉得为什么需要分区?有什么好处?
这个问题很简单,如果说不分区的话,我们发消息写数据都只能保存到一个节点上,这样的话就算这个服务器节点性能再好最终也支撑不住。

实际上分布式系统都面临这个问题,要么收到消息之后进行数据切分,要么提前切分,kafka正是选择了前者,通过分区可以把数据均匀地分布到不同的节点。

分区带来了负载均衡和横向扩展的能力。

发送消息时可以根据分区的数量落在不同的Kafka服务器节点上,提升了并发写消息的性能,消费消息的时候又和消费者绑定了关系,可以从不同节点的不同分区消费消息,提高了读消息的能力。

另外一个就是分区又引入了副本,冗余的副本保证了Kafka的高可用和高持久性。

详细说说消费者组和消费者重平衡?
Kafka中的消费者组订阅topic主题的消息,一般来说消费者的数量最好要和所有主题分区的数量保持一致最好(举例子用一个主题,实际上当然是可以订阅多个主题)。

当消费者数量小于分区数量的时候,那么必然会有一个消费者消费多个分区的消息。

而消费者数量超过分区的数量的时候,那么必然会有消费者没有分区可以消费。

所以,消费者组的好处一方面在上面说到过,可以支持多种消息模型,另外的话根据消费者和分区的消费关系,支撑横向扩容伸缩。

 《我想进大厂》之kafka夺命连环11问(一)-鸿蒙开发者社区
当我们知道消费者如何消费分区的时候,就显然会有一个问题出现了,消费者消费的分区是怎么分配的,有先加入的消费者时候怎么办?

旧版本的重平衡过程主要通过ZK监听器的方式来触发,每个消费者客户端自己去执行分区分配算法。

新版本则是通过协调者来完成,每一次新的消费者加入都会发送请求给协调者去获取分区的分配,这个分区分配的算法逻辑由协调者来完成。

而重平衡Rebalance就是指的有新消费者加入的情况,比如刚开始我们只有消费者A在消费消息,过了一段时间消费者B和C加入了,这时候分区就需要重新分配,这就是重平衡,也可以叫做再平衡,但是重平衡的过程和我们的GC时候STW很像,会导致整个消费群组停止工作,重平衡期间都无法消息消息。

另外,发生重平衡并不是只有这一种情况,因为消费者和分区总数是存在绑定关系的,上面也说了,消费者数量最好和所有主题的分区总数一样。

那只要消费者数量、主题数量(比如用的正则订阅的主题)、分区数量任何一个发生改变,都会触发重平衡。

下面说说重平衡的过程。

重平衡的机制依赖消费者和协调者之间的心跳来维持,消费者会有一个独立的线程去定时发送心跳给协调者,这个可以通过参数heartbeat.interval.ms来控制发送心跳的间隔时间。

  1. 每个消费者第一次加入组的时候都会向协调者发送JoinGroup请求,第一个发送这个请求的消费者会成为“群主”,协调者会返回组成员列表给群主
  2. 群主执行分区分配策略,然后把分配结果通过SyncGroup请求发送给协调者,协调者收到分区分配结果
  3. 其他组内成员也向协调者发送SyncGroup,协调者把每个消费者的分区分配分别响应给他们

《我想进大厂》之kafka夺命连环11问(一)-鸿蒙开发者社区

文章转自公众号:艾小仙

分类
标签
已于2022-6-10 15:59:43修改
收藏
回复
举报
回复
    相关推荐