目录

  • 三. kfk的架构深入
    • 3.4 kfk的消费者
      • 3.4.1 消费者的消费方式
      • 3.4.2 分区分配策略
        • 3.4.2.1 RoundRobin轮询
        • 3.4.2.2 Range范围(默认)
        • 3.4.2.3 什么时候会用到分区分配策略
      • 3.4.3 offset的维护
      • 3.4.4 消费者组案例
    • 3.5 kfk高效读写数据的原因
    • 3.6 zk在kfk中的作用
    • 3.7 Range策略再分析
    • 3.8 kfk事务
      • 3.8.1 producer事务
      • 3.8.2 consumer事务

三. kfk的架构深入

3.4 kfk的消费者

主要研究消费者的消费方式 和 消费者组的分区分配策略

3.4.1 消费者的消费方式

  • consumer采用pull拉取的方式从broker中拉取数据.
    push, broker推送数据的方式很难适应不同的消费者, 因为不同消费者的消费速率不同.
  • pull模式的缺点是如果kfk中没有数据, 消费者可能陷入循环, 一直返回空数据.
    • 针对这一点, kfk的消费者在消费数据时会传入一个时长参数timeout, 如果当前没有数据可供消费, consumer会等待一段时间之后再返回, 这段时长即为timeout.

3.4.2 分区分配策略

  • 一个consumer group中有多个consumer, 一个topic有多个partition, 所以必然会涉及到partition的分配问题, 即确定哪个partition由哪个consumer来消费.

  • 同一个消费者组中的不同消费者, 能同时消费同一个topic, 不能同时消费同一个partition.

  • kfk有两种消费者分区分配策略: RoundRobin 和 Range(默认).

  • RoundRobin是按照组来划分的, Range是按照主题来划分的.

3.4.2.1 RoundRobin轮询

  • 1个topic, 7个partition

  • 2个topic, 每个topic有3个partition

    • 假设消费者组同时订阅了两个topic(如上图). 那么在kfk轮询的策略中, 会把topic1和topic2中所有的partition看做一个整体, 根据每个partition的哈希值, 将这6个partition排序, 然后再轮询分配给consumer group中的两个consumer.

    • 在API中, 每个partition都会被封装成一个TopicAndPartition对象, 使用的是这个对象的哈希值.

    • 这样做的优点是consumer group中每个consumer 分配的partition的数量的差值最多差1个, 因为是轮询嘛. 即保证了每个consumer分配到的partition数量尽可能相同.

    • 这样做的缺点是假如同一个consumer group中的consumer-a订阅了topic1和topic2, consumer-b订阅了topic2和topic3, 那么轮询策略会把topic1 topic2 topic3中所有的partition看做一个整体, 轮询分配到consumer-a和consumer-b中, 这样的话consumer-a可能分配到topic3中的partition, consumer-b可能分配到topic1中的partition. 如下图.

    • 如果consumer-a消费topic1, consumer-b消费topic2, 那么按照轮询的分配策略, 会将topic1 topic2中的所有partition看做一个整体轮询分配到每个consumer中, 那么consumer-a可能分配到topic2中的partition, consumer-b可能分配到topic1中的partition. 如下图.

    • 所以使用轮询的分区分配策略的前提是: 必须保证consumer group中consumer订阅的topic是相同的(可以是多个).

    • 正是由于有上述的问题, 因此kfk默认的分区分配策略是Range.

3.4.2.2 Range范围(默认)

  • 这种策略按照topic分, 而不是按照partition分.
  • 1个topic, 7个partition
    • 按照 7/3 将partition分配到每个consumer中.

    • 这种策略的缺点是有的consumer分配的partition太多, 有的consumer分配的partition太少. 即consumer group中每个consumer分配的partition数量不均匀.

  • 2个topic, 每个topic有3个partition
    • 随着订阅的topic越多, 不同consumer中分配的partition数差距将越大.

  • 结论
    • RoundRobin策略优点是能让consumer group中每个consumer尽量分配到相同数量的partition, 缺点是当consumer group中consumer订阅的topic不同时会出问题, 因为所有的topic会被看做一个整体.
    • Range策略的优点是RoundRobin策略的缺点, Range策略的缺点是RoundRobin策略的优点.
    • 两种策略按照实际业务场景选择, 默认Range.

3.4.2.3 什么时候会用到分区分配策略

分区策略在API中就是一个方法. 这个方法何时被调用? 即何时会触发策略的执行? 即策略的触发时机是什么时候?

  • 当consumer group中消费者个数变化时就会重新触发分区策略. 即使消费者数量增加到比分区数量还多时, 仍然会触发分区策略.

3.4.3 offset的维护

  • 由于consumer在消费过程中可能会出现断电宕机等故障, consumer恢复后, 需要从故障前的位置继续消费, 所以需要consumer实时记录自己消费到了哪个offset, 以便故障恢复后继续消费.

  • kfk0.9前偏移量保存在zk, kfk0.9开始偏移量保存在kfk.

  • 从kfk0.9开始, consumer默认将offset保存在kfk一个内置的topic中, 该topic为_consumer_offsets.

  • offset由3个部分唯一确定: consumer group + topic + partition. offset是按照consumer group保存的而不是按照consumer保存的, 这样的好处就是如果一个consumer挂了, offset不至于丢失. 如果consumer-a保存了10条msg, 这是consumer group中新加consumer-b(此时触发分区策略), 这就能保证consumer-b能从第11条msg接着消费.

  • 查看zk中维护的offset

    • 创建一个topic名为topic100, 2个partition, 每个partition都有2个副本

      /opt/kafka/kafka/bin/kafka-topics.sh --create --topic topic100 --zookeeper localhost:2181 --partitions 2 --replication-factor 2
      
    • 启动一个生产者

      /opt/kafka/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic topic100
      
    • 启动一个消费者. 使用zk存储offset.

      /opt/kafka/kafka/bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic topic100
      
    • 生产者输入 “hello”

    • 进入zk

      # 进入zk
      /opt/zookeeper/zookeeper/bin/zkCli.sh# 展示根节点. # 根节点下面的内容, 除了zookeeper, 其他都是和kfk相关的. 其中的controller是kfk中的控制节点, 哪个broker先抢到资源, 哪个broker就是controller, 一般先启动的broker会成为controller. controller的作用和其他broker的作用相同, 只不过controller可以和zk进行交互. # brokers下面有ids,topics,seqid. 其中ids中记录了kfk的broker-id. 只要是注册到ids中的, 都是kfk集群中的一个节点. kfk并没有组织集群, 而是zk帮kfk组织了集群; /brokers/topics记录了kfk中所有的topic. # /consumers中存储了消费者向zk写的数据. 如下的"console-consumer-68063", 这实际上是消费者组, 以控制台的形式启动消费者, 会被默认分配到一个组, 组名就是"console-consumer-随机数". 如果使用API, 必须手动指定消费者组名, 不会自动创建. # 消费者组中有offset, offset中有topic, topic中有分区, 获取分区中值就能得到offset的值. [zk: localhost:2181(CONNECTED) 0] ls /
      [cluster, controller_epoch, controller, brokers, zookeeper, admin, isr_change_notification, consumers, latest_producer_id_block, config][zk: localhost:2181(CONNECTED) 3] ls /consumers
      [console-consumer-68063, console-consumer-39547, console-consumer-47083][zk: localhost:2181(CONNECTED) 4] ls /consumers/console-consumer-68063
      [ids, owners, offsets][zk: localhost:2181(CONNECTED) 8] ls /consumers/console-consumer-39547/offsets
      [topic100][zk: localhost:2181(CONNECTED) 9] ls /consumers/console-consumer-39547/offsets/topic100
      [0, 1][zk: localhost:2181(CONNECTED) 10] get /consumers/console-consumer-39547/offsets/topic100/0
      0 # 消息偏移量
      cZxid = 0x649
      ctime = Sat Dec 05 16:39:13 CST 2020
      mZxid = 0x649
      mtime = Sat Dec 05 16:39:13 CST 2020
      pZxid = 0x649
      cversion = 0
      dataVersion = 0
      aclVersion = 0
      ephemeralOwner = 0x0
      dataLength = 1
      numChildren = 0
      


  • 查看kfk本地维护的offset

    • 由于kfk中存储offset的主题是kfk内置的主题_consumer_offsets, 因此我们需要改一些配置才能消费这个topic中的数据.

      # 修改consumer.properties. 不除外内置的topics.
      exclude.internal.topis=false
      
    • 读取offset

      • kfk0.11之前的版本

      • kfk0.11开始的版本

3.4.4 消费者组案例

  • 测试同一个消费者组中的消费者, 同一时刻只能有一个消费者消费.

  • 使用控制台的consumer时, 每次启动一个consumer都会分配到一个新的consumer group中, 组名随机分配. 我们可以通过修改consumer.properties文件, 将group.id修改为任意, 那么启动任意个控制台的consumer就都会在同一个consumer group中了. group.id就是组名.

3.5 kfk高效读写数据的原因

研究集群版kfk中单个节点的读写效率为什么比其他mq效率高; 研究单台kfk的读写效率为什么比单台其他mq的效率高.

  • 集群读写高效原因

    1. kfk是分布式的, 能并发读写.
    2. 顺序写磁盘. 顺序写磁盘省去了大量磁头寻址的时间.
    3. 零拷贝技术.
  • 单节点读写高效原因

    1. 顺序写磁盘. 顺序写磁盘省去了大量磁头寻址的时间.
    2. 零拷贝技术.
  • 不用零拷贝

  • 使用零拷贝

3.6 zk在kfk中的作用

  • kfk集群中有一个broker会被选举为controller, 负责管理集群broker的上下线, 所有topic的分区副本分配leader选举等工作. broker被选为controller的策略是抢占资源, 谁先抢到谁就是controller, 一般最先启动的broker将成为controller.
  • controller的管理工作都是依赖于zk的.
  • leader选举流程:

3.7 Range策略再分析

  • 上述使用的策略是Range
  • 使用轮询的话, 看消费者组, 看整个组订阅了哪些topic, 然后将这些topic中的所有partition作为一个整体 进行轮询. 所以上述的情况不能使用轮询策略, 否则consumer-A可能会分配到topic2的partition.

3.8 kfk事务

3.8.1 producer事务

  • 保证跨分区跨会话级别的精准一次性.

3.8.2 consumer事务

  • 保证消费者消费的数据是只消费一次的. (这一块很少聊, 关键还是生产者那边的事务)

kafka基础入门(三)相关推荐

  1. kafka基础入门_CodingPark编程公园

    文章介绍 本文是kafka基础入门篇,讲解内容包括: 1. 消息队列对比表 2. Kafka概念及特性 3. kafka总体结构 4. kafka各项配置 5. 生产者 6. kafka Broker ...

  2. Kafka基础入门篇

    1 kafka简介 Kafka 是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用与大数据实时处理领域.其主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化 ...

  3. kafka基础入门(4):kafka消费者

    kafka消费者 kafka消费方式 kafka采用pull(拉)模式,consumer从broker中拉取数据 pull模式的不足:如果Kafka没有数据,消费者可能会陷入循环中,一直返回空数据 k ...

  4. kafka基础入门(五)

    目录 五. KafKa监控 5.1 介绍 5.2 安装 5.3 使用 六. Flume对接Kafka 七. KafKa Streams 八. KafKa面试题 五. KafKa监控 可以参考:http ...

  5. Unity Shader-Universal Render Pipeline(URP)基础入门三

    Physically Based Shading 在学习之前首先贴个基础知识普及 英文原版:https://marmoset.co/posts/basic-theory-of-physically-b ...

  6. Arduino基础入门三:数字IO口作为输出

    一.信号分类: 1.数字信号:物理量的变化在时间和幅值上都是离散的(不连续),反映在电路上就是高电平和低电平两种状态(即只有0和1两个逻辑值).比如:灯有亮和不亮两种状态,天气有晴天和雨天两种状态,门 ...

  7. bigdecimal判断大于零_Python零基础入门(七):运算符

    点击蓝字 一起划水 Review: Python零基础入门(一):对Python的简单认识 Python零基础入门(二):字符串基础 Python零基础入门(三):字符串进阶 Python零基础入门( ...

  8. java反射三种方法_Java基础入门要学哪些 怎么掌握反射和枚举

    Java基础入门要学哪些?怎么掌握反射和枚举?Java是老牌编程语言,是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java所包含的基础知识点很多,只有掌握了这些知识才能更好地运用,下面就来给 ...

  9. 变量的三重属性_TypeScript基础入门 - 变量声明(三)

    转载地址TypeScript基础入门 - 变量声明(三)​www.gowhich.com 项目实践仓库 https://github.com/durban89/typescript_demo.gitt ...

最新文章

  1. 企业品牌网站建设都涉及收取哪些方面的费用?
  2. BOM之navigator对象和用户代理检测
  3. java 泛型 比较_java 泛型和object比较
  4. Here we want to mention one thing
  5. 你靠什么在单位立足?此文堪称经典
  6. 字符串模式匹配sunday算法
  7. Python实现借助聚合数据API接口生成某一年的节假日对照表
  8. Python-Seleium模拟登陆163邮箱
  9. 一种最低级的按键状态机
  10. java随机生成车牌号函数
  11. [SV]SystemVerilog 断言(SVA)检查器库(OVL)
  12. 路由声明式传参和编程式传参
  13. 泪目!这篇博士论文致谢走红:感谢博一与我结婚的妻子
  14. 高博RGBD SLAM
  15. IM即时通讯项目讲解(一)--实现类似qq微信表情面板无缝切换
  16. 华为平板如何换计算机的皮肤,走出护肤误区,华为镜子携手皮肤专家化解护肤难题...
  17. python输出字符的ascii码_如何获取一个字符的ASCII码
  18. java脏字过滤_分享JavaWeb中filter过滤器的案例妙用 - 脏话过滤/编码过滤/代码过滤...
  19. 双击jar包运行,出现使用压缩软件打开的情况
  20. 如何在 Mac 上查看显示刷新率

热门文章

  1. 产品设计 计算机辅助设计学什么,产品设计专业课程有哪些 主要学什么
  2. python findall用法_Python 正则表达re模块之findall()详解
  3. 小白笔记:selectKey的使用方法
  4. 如何用css实现div高度自适应占满屏幕
  5. python的热潮_行业观察|全民学Python的热潮,是如何掀起的?
  6. php去除重复的数据保留一条,mysql查找删除重复数据并只保留一条实例详解
  7. Linux思维导图汇总
  8. pc酷狗网页最简洁代码2023最新
  9. 各位看官,来看下建站基本流程吧!
  10. java键盘监听事件代码_JavaScript监听键盘事件代码实现