• kafka学习(六)kafka核心设计原理


    一、Kafka核心总控制器

      定义:kafka集群中的一个负责管理所有分区和副本的状态的broker

      PS:kafka单台机器也叫集群。

      职能:选举新的leader副本、ISR变更通知所有broker更新其元数据、让新分区被其他节点感知。

    • 当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。
    • 当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。
    • 当使用kafka-topics.sh脚本为某个topic增加分区数量时,同样还是由控制器负责让新分区被其他节点感知到。

    Controller选举原理

    • kafka集群启动时,每个borker去ZK上创建一个“/controller 临时节点”,谁创建成功谁就是Controller
    • 当这个controller角色的broker宕机了,此时ZK上的临时节点会消失,集群里其他broker会一直监听这个临时节点,发现临时节点消失了,就竞争再次创建临时节点,ZK又会保证只有一个broker成为新的controller。

    Partition副本选举Leader原理

    • controller感知到分区leader所在的broker挂了,则会从ISR列表里挑第一个broker作为leader。
    • 若参数unclean.leader.election.enable为true,代表在ISR列表里所有副本都挂了,则可以在ISR列表以外的副本中选leader。

    副本进入ISR的条件

    • 副本节点不能产生分区,必须能与zookeeper保持会话以及跟leader副本网络连通。
    • 副本能复制leader上的所有写操作,并且不能落后太多。

      PS:之所以取ISR中的第一个broker升级Leader,是因为第一个broker最先放进ISR 列表,可能是同步数据最多的副本。

    二、消费者offset记录机制

    offset记录机制

    • 每个consumer会定期将自己消费分区的offset提交给kafka内部topic:__consumer_offsets
    • 提交过去的时候,keyconsumerGroupId+topic+分区号value就是当前offset的值。
    • kafka会定期清理topic里的消息,最后就保留最新的那条数据。

      PS:因为__consumer_offsets可能会接收高并发的请求,kafka默认给其分配50个分区(可以通过offsets.topic.num.partitions设置),这样可以通过加机器的方式抗大并发。

    三、消费者Rebalance机制

    Rebalance机制

      定义:如果消费组里的消费者数量有变化或消费的分区数有变化,kafka会重新分配消费者和消费分区的关系。

      PS:每个消费者都会有消费组,如果不指定会生成默认的组。

      PS:rebalance只针对subscribe这种不指定分区消费的情况,如果通过assign这种消费方式指定了分区,kafka不会进行rebanlance。

      PS:rebalance过程中,消费者无法从kafka消费消息!!!【尽量避免在系统高峰期时发生重平衡。】

      触发场景:

    • 1、消费组里的consumer增加或减少了
    • 2、动态给topic增加了分区
    • 3、消费组订阅了更多的topic

    Rebalance过程

      设计原理:分区方案制定过程中有两个组长,消费者组长负责制订分区策略,生产者组长负责通知其他消费者分区策略。【同一个消费者组中的消费者没有联系,需要通过kafka组长来协调。

      两个重要角色:

    • 组协调器【生产者组长】:每个消费者组都会选择一个broker作为自己的组协调器coordinator,负责监控这个消费组里的所有消费者的心跳,以及判断是否宕机,然后开启消费者rebalance
    • 消费组协调器【消费者组长】负责制定分区方案,并与组协调器进行通信

      PS:消费者组长不是我们所说的分区Leader!这个概念要区分好!

    第一阶段:选择组协调器【生产者组长】

      消费者组中的每个consumer启动时会向kafka集群中的某个节点发送查找组协调器的请求,并跟其建立网络连接

    组协调器选择方式

      公式:hash(consumer_group_id) % _consumer_offsets主题的分区数

      根据公式获取到分区地址后,这个分区leader对应的broker就是这个消费者组的组协调器。

    第二阶段:消费者入组

      在成功找到消费组所对应的组协调器后就进入消费组入组的阶段,在此阶段的消费者会向组协调器发送入组请求。

      组协调器从一个消费者组中选择第一个加入group的consumer作为消费者组长,把消费者组的情况发送给这个broker,接着这个broker会负责制定分区方案

    第三阶段:组协调器下发分区方案

      消费者组长通过给组协调器发送下发分区策略请求,接着组协调器就把分区方案下发给各个consumer,他们会与指定分区的leader对应的broker进行网络连接以及消息消费。

    Rebalance分区分配策略

    • range【默认】:根据分区数/消费者数量,然后给每个消费者分配n个分区。【消费者1:0~3  消费者2:4~6  消费者3:7~9】
    • round-robin轮询分配机制。【消费者1:0、3、6  消费者2:1、4、7  消费者3:2、5、8】
    • sticky粘性轮询机制。【当分区增加或者增加消费者时,只会重新分配挂掉的那台或者新的分区。】

      PS:range和轮询当分区增加或者增加消费者时,会重新轮询。而粘性策略则不会,粘性策略只会重新分配挂掉的那台或者新的分区。

    四、生产者发布消息机制

    写入方式

      producer采用push模式将消息发布到broker,每条消息都被append到patition中,属于顺序写磁盘

      PS:顺序写磁盘效率比随机写内存要高,可以保障kafka吞吐量。

    消息路由

      producer发送消息到broker时,会根据分区算法选择将其存储到哪一个partition。其路由机制为:

    • 1、指定了patition,则直接使用
    • 2、未指定patition但指定key,通过对key的value进行hash选出一个patition。【key的组成见本文上半部分的解析】
    • 3、patition和key都未指定,使用轮询选出一个 patition。

    写入流程

    五、高水位

    基本概念

    • HW:高水位
    • LEO:日志末端位移

    HW一个partition对应的ISR中最小的LEO(log-end-offset), consumer最多只能消费到HW所在的位置

    每个replica都有HW,leader和follower各自负责更新自己的HW的状态

    PS:对于leader新写入的消息,consumer不能立刻消费,leader会等待该消息被所有ISR中的replicas同步后更新HW,此时消息才能被consumer消费。

    快乐图解~

    六、日志分段存储原理

      Kafka一个分区的消息数据对应存储在一个文件夹下,以topic名称+分区号命名:

      消息在分区内是分段(segment)存储,每个段的消息都存储在不一样的log文件里,这种特性方便old segment file快速被删除,kafka规定了一个段位的log文 件最大为1G,做这个限制目的是为了方便把 log 文件加载到内存去。

    # 【部分消息的offset索引文件】,kafka每次往分区发4K(可配置)消息就会记录一条当前消息的offset到index文件
    # 如果要定位消息的offset会先在这个文件里快速定位,再去log文件里找具体消息
    00000000000000000000.index
    # 【消息存储文件】,主要存offset和消息体
    00000000000000000000.log
    # 【消息的发送时间索引文件】,kafka每次往分区发4K(可配置)消息就会记录一条当前消息的发送时间戳与对应的offset到timeindex文件 # 如果需要按照时间来定位消息的offset,会先在这个文件里查找
    00000000000000000000.timeindex 00000000000005367851.index 00000000000005367851.log 00000000000005367851.timeindex 00000000000009936472.index 00000000000009936472.log 00000000000009936472.timeindex

      这个partition有三组segment文件,当储存满时每个log文件的大小是一样的,但是存储的message数量是不一定相等的(每条的message大小不一致)。

      PS:每个日志段文件最大为1G

    • 文件的命名是以该segment最小offset来命名的,如00000000000000.index存储offset为0~5367850的消息...以此类推。
    • kafka就是利用分段+索引的方式来解决查找效率的问题。
  • 相关阅读:
    PE格式第五讲,手工添加节表
    PE格式第四讲,数据目录表之导入表,以及IAT表
    PE格式第三讲扩展,VA,RVA,FA(RAW),模块地址的概念
    PE文件格式详解,第三讲,可选头文件格式,以及节表
    PE文件格式详解,第二讲,NT头文件格式,以及文件头格式
    LVS
    Haproxy
    Nginx
    MySQL入门第一天——概述、数据表与约束操作
    NoSQL入门第五天——Java连接与整合操作
  • 原文地址:https://www.cnblogs.com/riches/p/15517403.html
Copyright © 2020-2023  润新知