kafka中topic默认属性_分享:Kafka 的 Lag 计算误区及正确实现

前言

消息堆积是消息中间件的一大特色,消息中间件的流量削峰、冗余存储等功能正是得益于消息中间件的消息堆积能力。然而消息堆积其实是一把亦正亦邪的双刃剑,如果应用场合不恰当反而会对上下游的业务造成不必要的麻烦,比如消息堆积势必会影响上下游整个调用链的时效性,有些中间件如RabbitMQ在发生消息堆积时在某些情况下还会影响自身的性能。对于Kafka而言,虽然消息堆积不会对其自身性能带来多大的困扰,但难免不会影响上下游的业务,堆积过多有可能会造成磁盘爆满,或者触发日志清除策略而造成消息丢失的情况。如何利用好消息堆积这把双刃剑,监控是最为关键的一步。

正文

消息堆积是消费滞后(Lag)的一种表现形式,消息中间件服务端中所留存的消息与消费掉的消息之间的差值即为消息堆积量,也称之为消费滞后(Lag)量。对于Kafka而言,消息被发送至Topic中,而Topic又分成了多个分区(Partition),每一个Partition都有一个预写式的日志文件,虽然Partition可以继续细分为若干个段文件(Segment),但是对于上层应用来说可以将Partition看成最小的存储单元(一个由多个Segment文件拼接的“巨型文件”)。每个Partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到Partition中。我们来看下图,其就是Partition的一个真实写照:

c3fb7ea3823fb156947341de8a0b80a4.png

上图中有四个概念:

  • LogStartOffset:表示一个Partition的起始位移,初始为0,虽然消息的增加以及日志清除策略的影响,这个值会阶段性的增大。
  • ConsumerOffset:消费位移,表示Partition的某个消费者消费到的位移位置。
  • HighWatermark:简称HW,代表消费端所能“观察”到的Partition的最高日志位移,HW大于等于ConsumerOffset的值。
  • LogEndOffset:简称LEO,
  • 代表Partition的最高日志位移,其值对消费者不可见。比如在ISR(In-Sync-Replicas)副本数等于3的情况下(如下图所示),消息发送到Leader
  • A之后会更新LEO的值,Follower B和Follower C也会实时拉取Leader
  • A中的消息来更新自己,HW就表示A、B、C三者同时达到的日志位移,也就是A、B、C三者中LEO最小的那个值。由于B、C拉取A消息之间延时问题,所以HW必然不会一直与Leader的LEO相等,即LEO>=HW。
29d24aced88d39704d6d14ab6c3fdd0d.png

要计算Kafka中某个消费者的滞后量很简单,首先看看其消费了几个Topic,然后针对每个Topic来计算其中每个Partition的Lag,每个Partition的Lag计算就显得非常的简单了,参考下图:

由图可知消费Lag=HW - ConsumerOffset。对于这里大家有可能有个误区,就是认为Lag应该是LEO与ConsumerOffset之间的差值,笔者在这之前也犯过这样的错误认知,详细可以参考《如何使用JMX监控Kafka》。LEO是对消费者不可见的,既然不可见何来消费滞后一说。

那么这里就引入了一个新的问题,HW和ConsumerOffset的值如何获取呢?

be556c3e12459545f1f789175e1a5b90.png

首先来说说ConsumerOffset,Kafka中有两处可以存储,一个是Zookeeper,而另一个是”__consumer_offsets这个内部topic中,前者是0.8.x版本中的使用方式,但是随着版本的迭代更新,现在越来越趋向于后者。就拿1.0.0版本来说,虽然默认是存储在”__consumer_offsets”中,但是保不齐用于就将其存储在了Zookeeper中了。这个问题倒也不难解决,针对两种方式都去拉取,然后哪个有值的取哪个。不过这里还有一个问题,对于消费位移来说,其一般不会实时的更新,而更多的是定时更新,这样可以提高整体的性能。那么这个定时的时间间隔就是ConsumerOffset的误差区间之一。

再来说说HW,其也是Kafka中Partition的一个状态。有可能你会察觉到在Kafka的JMX中可以看到“kafka.log:type=Log,name=LogEndOffset,topic=[topic_name],partition=[partition_num]”这样一个属性,但是这个值不是LEO而是HW。

那么怎样正确的计算消费的Lag呢?对Kafka熟悉的同学可能会想到Kafka中自带的kafka-consumer_groups.sh脚本中就有Lag的信息,示例如下:

1[root@node2 kafka_2.12-1.0.0]# bin/kafka-consumer-groups.sh --describe --bootstrap-server localhost:9092 --group CONSUMER_GROUP_ID

2TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID

3topic-test1 0 1648 1648 0 CLIENT_ID-e2d41f8d-dbd2-4f0e-9239-efacb55c6261 /192.168.92.1 CLIENT_ID

4topic-test1 1 1648 1648 0 CLIENT_ID-e2d41f8d-dbd2-4f0e-9239-efacb55c6261 /192.168.92.1 CLIENT_ID

5topic-test1 2 1648 1648 0 CLIENT_ID-e2d41f8d-dbd2-4f0e-9239-efacb55c6261 /192.168.92.1 CLIENT_ID

6topic-test1 3 1648 1648 0 CLIENT_ID-e2d41f8d-dbd2-4f0e-9239-efacb55c6261 /192.168.92.1 CLIENT_ID

71

我们深究一下kafka-consumer_groups.sh脚本,发现只有一句代码:

1exec $(dirname $0)/kafka-run-class.sh kafka.admin.ConsumerGroupCommand "$@"

其含义就是执行kafka.admin.ConsumerGroupCommand而已。进一步深究,在ConsumerGroupCommand内部抓住了2句关键代码:

1val consumerGroupService = new KafkaConsumerGroupService(opts)

2val (state, assignments) = consumerGroupService.describeGroup()

代码详解:consumerGroupService的类型是ConsumerGroupServicesealed trait类型),而KafkaConsumerGroupService只是ConsumerGroupService的一种实现,还有一种实现是ZkConsumerGroupService,分别对应新版的消费方式(消费位移存储在__consumer_offsets中)和旧版的消费方式(消费位移存储在zk中),详细计算步骤参考下一段落的内容。opt参数是指“ –describe –bootstrap-server localhost:9092 –group CONSUMER_GROUP_ID”等参数。第2句代码是调用describeGroup()方法来获取具体的信息,即二元组中的assignments,这个assignments中保存了上面打印信息中的所有内容。

Scala小知识:在Scala中trait(特征)相当于Java的接口,实际上它比接口更大强大。与Java中的接口不同的是,它还可以定义属性和方法的实现(JDK8起的接口默认方法)。一般情况下Scala中的类只能继承单一父类,但是如果是trait的话就可以继承多个,从结果来看是实现了多重继承。被sealed声明的trait仅能被同一文件的类继承。

ZkConsumerGroupService中计算消费lag的步骤如下:

通过zk获取一些基本信息,对应上面打印信息中的:TOPIC、PARTITION、CONSUMER-ID等,不过不会有HOST和CLIENT-ID。

1、通过OffsetFetchRequest请求获取消费位移(offset),如果获取失败则在通过zk获取。

2、通过OffsetReuqest请求获取分区的LogEndOffset(简称为LEO,可见的LEO)。

3、计算LogEndOffset与消费位移的差值来获取lag。

4、KafkaConsumerGroupService中计算消费lag的步骤如下:

通过DescibeGroupsRequest请求获取一些基本信息,不仅包括TOPIC、PARTITION、CONSUMER-ID,还有HOST和CLIENT-ID。其实还有通过

1、FindCoordinatorRequest请求来获取coordinator信息,如果不了解coordinator在这里也没影响。

2、通过OffsetFetchRequest请求获取消费位移。

3、通过OffsetReuqest请求获取分区的LogEndOffset(简称为LEO)。

4、计算LogEndOffset与消费位移的差值来获取lag。

可以看到KafkaConsumerGroupService与ZkConsumerGroupService的计算Lag的方式都差不多,但是KafkaConsumerGroupService能获取更多消费详情,并且ZkConsumerGroupService也被标注为@Deprecated的了,后面内容都针对KafkaConsumerGroupService来做说明。既然Kafka已经为我们提供了线程的方法来获取Lag,那么我们有何必再重复造轮子,这里笔者写了一个调用的KafkaConsumerGroupService的示例(KafkaConsumerGroupService是使用Scala语言编写的,在Java的程序里使用类似scala.collection.Seq这样的全名称以防止混淆):

1String[] agrs = {"--describe

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手机系统安装打印机服务器错误代码,OKI打印机报错?各型号代码故障解决方法...

原标题:OKI打印机报错?各型号代码故障解决方法这一期干货贴邀请大家一起看看OKI打印机常见报错代码↓↓↓1、报错代码 610/611/612/613黄色/品红色/青色/黑色碳粉盒未安装产生原因:◆可替代芯片安装不正确、芯片触点上有异物遮挡、鼓组件探针…

python3 批量定义多个变量_Python 3.8 新功能大揭秘

Python 3.8是Python语言的最新版本,它适合用于编写脚本、自动化以及机器学习和Web开发等各种任务。现在Python 3.8已经进入官方的beta阶段,这个版本带来了许多语法改变、内存共享、更有效的序列化和反序列化、改进的字典和更多新功能。Python 3.8还引入了…

div独占一行 html_web前端基础-HTML及CSS选择器

HTML及CSS选择器一、html基本结构二、html标签1、标题标签2、a标签3、img标签4、div和span标签5、列表标签6、表格标签7、form表单8、select下拉框标签9、textarea标签三、CSS1、css样式引入方式2、标签嵌套3、css选择器一、html基本结构html是一种超文本标记语言,进…

监控系统服务器如何配置,监控系统服务器的配置

监控系统服务器的配置 内容精选换一换裸金属服务器安装Agent后,裸金属实例出现在云监控服务管理控制台的“主机监控 > 弹性云服务器”列表中。主机监控Agent根据169.254.169.254提供的服务来判断是弹性云服务器还是裸金属服务器。如果该地址的路由被修改&#xf…

解析markdown_markdown-it 原理浅析

前言最近使用 markdown-it 比较多,也开发了一些插件,在这个过程中对源码进行了研读,最终写了这篇文章。需要了解细节的读者可以自行阅读文档。此文分为两个部分:原理剖析和原理应用(编写插件)。markdown-it…

第一次失效_特斯拉螺栓腐蚀失效分析_搜狐汽车

本文车型速览除了文章作者的主观观点外,我们正尝试基于全网可查的客观数据,为您提供中立、客观的参考依据:本文部分车型速览:展开微信扫码,直接一次看完附近所有城市低价(附近城市均有经销商可售卖至本市) 提交成功&am…

c#计算长方形的周长和面积公式_Java面向对象练习题之计算圆的面积和周长

创建一个圆Circle类。为该类提供一个变量r表示半径,一个常量PI表示圆周率;同时为该类提供两个方法:方法一用于求圆的面积,方法二用于求圆的周长;为该类提供一个无参的构造方法,用于初始化r的值为4。在main方…

简单计算机面试题库及答案_试讲可以看教案吗?必看的面试考前问题解答

“皮卡皮卡!”教资面试倒计时4天啦快使尽全力发出你的十万伏特胜利就在前方部分小伙伴们还对教资面试存在种种疑惑下面牛奶为大家一一作出解答教师资格面试题目是如何确定的?答:面试题目分为试讲题目、结构化题目和答辩题目。▲试讲题目是考生在备课前&…

python输出读取的空格数目_Python 3基础教程: 输入和输出具体代码实例

在前面文章中,我们其实已经接触了 Python 的输入输出的功能。本章节我们将具体介绍 Python 的输入输出。输出格式美化Python两种输出值的方式: 表达式语句和 print() 函数。(第三种方式是使用文件对象的 write() 方法; 标准输出文件可以用 sys.stdout 引用。)如果你…

点击button后改变文字_27. 教你零基础搭建小程序:小程序的常见组件—button

筒子们,这一章接着讲Button 标签。开放能力的属性button标签的开放能力是指open-type 属性。其中,这个属性的合法值包括如下:这一部分呢,需要分为两个方式来演示。一是可在模拟器中直接看效果; 二是要通过真机调试看效…

语言把数据写入csv文件_把JSON/CSV文件打造成MySQL数据库

生活中,你我一定都看到过这种「xx元爆改出租屋」,「爆改小汽车」之类的文章,做为IT人,折腾的劲头一点也不差。软件开发过程中,你是否有时候,会拿着业务提供的一个个CSV或者JSON的数据文件,写个解…

图片饱和度_摄影后期完全调色指南(三):饱和度与自然饱和度有什么区别?...

泼辣年度大课 | 摄影后期完全调色指南(一)摄影后期完全调色指南(二):详解色温与色调在上一篇教程里面我们讲到了全局色彩调整中的色温和色调工具,今天来讲解剩下的两个工具:饱和度与自然饱和度工具,这两个工具使用的频率也非常的高…

windows 下的文件对比工具

deffinity,一款专用于文件对比的工具,安装简单,使用方便 下载链接如下: https://www.appinn.com/diffinity-for-win/

点名册_骑士新书《万界点名册》十万收藏火爆气势不减当年修真聊天群

最近好多人都在讨论圣骑士的传说新书《万界点名册》,新书还没有发布,起点就给了闪屏推荐,引得的很多读者心痒痒的想要看看到底是怎样的神作。所以才发布两万多字的新书投资人就快一万人了,收藏也突破了十万。这速度好像是坐了火箭…

500张思维导图记38000单词_思维导图记单词,环环相扣难遗忘——2020奇速英语夏令营第三天...

2020年8月6日,是奇速英语19期夏令营第二批单词阅读营正式上课的第3天,为了激发各班学员学习兴趣,保证学习效果,奇速英语专门制定了小组PK的积分奖励制在今天的学习当中发挥了极大的效果。在这一机制的刺激和奇速英语老师们的高效教…

语音识别热词_出门问问 TWS 耳机语音交互解决方案

随着芯片、算法商在技术及应用方面的演进,尤其是连接、降噪方向的重大突破,越来越多的手机及耳机厂商推出了自家功能丰富、交互舒适的 TWS 耳机。近日,出门问问新品发布会上推出的 TicPods 2 系列产品,在人机交互和语音助理方面&a…

go tcp连接_TCP漫谈之keepalive和time_wait

TCP是一个有状态通讯协议,所谓的有状态是指通信过程中通信的双方各自维护连接的状态。一、TCP keepalive先简单回顾一下TCP连接建立和断开的整个过程。(这里主要考虑主流程,关于丢包、拥塞、窗口、失败重试等情况后面详细讨论。)首先是客户端发送syn(Syn…

mysql update 联合更新_Mysql update多表联合更新的方法小结

下面我建两个表,并执行一系列sql语句,仔细观察sql执行后表中数据的变化,很容易就能理解多表联合更新的用法student表 class表1. 执行 UPDATE student s , class c SET s.class_nametest00,c.stu_nametest00 WHERE s.class_id c.idstudent表 …

mysql查询开启事务_MySQL中的查询事务问题

之前帮同学做个app的后台,使用了MySQLMyBatis,遇到了一个查询提交的问题,卡了很久,现在有时间了来复盘下环境情况假设有学生表:USE test;CREATE TABLE student (Id int NOT NULL PRIMARY KEY AUTO_INCREMENT,Name varc…

通过gparted 调整 ubuntu 磁盘

1. 启动和安装 1. 安装 sudo apt-get install gparted 2. 启动 sudo gparted2.配置 如果想扩充磁盘,需要有未分配空间,且该未分配空间位于partition相邻的格子