上周帮一个综合能源平台排查了一次“数据晚点”:大屏上光伏电站的功率曲线比现场晚了将近5分钟,电站侧坚称采集正常,平台侧却说数据没到。我登录服务器后先看的不是数据库,而是Kafka的消费组状态,Lag直接顶到了几十万条。消息管道是最薄的一环,也是最容易背锅的一环。这个场景在能源科技领域太典型了——分布式光伏、风电场、储能站、智能电表,每秒钟都有大量设备测点数据往平台涌,处理链路长、下游系统多,没有一条像样的消息管道,数据迟早会出事。
这篇东西不打算从“Kafka是什么”这种概念讲起,而是结合能源科技数据处理的真实需求,把Kafka在采集链路里的定位、集群规划、生产端消费端配置、数据质量保障、故障排查和日常监控整个串一遍。适合正在搭能源数据平台、或者接手了类似系统但被Kafka配置和异常搞得头大的朋友。写这个的时候,我会尽量把参数为什么这么配、排查为什么这么走讲透,而不是只给你一堆可以直接抄的配置——当然,配置我也会给。
1. 能源数据的真实脾气:为什么消息管道必须能“扛突刺”
1.1 海量点位、秒级采集:数据量是算出来的,不是感觉出来的
先算一笔账。以常见的大型风电场为例,50万千瓦规模大约100台风机,每台风机的SCADA系统会采集机舱风速、发电机转速、齿轮箱油温、轴承温度、振动、有功无功、桨距角等等,少说200个测点。如果按秒级采集一次,整个风场每秒就是100台×200点=20000条数据。一天下来,20000×86400=17.28亿条。每条消息如果用JSON序列化,平均200字节左右,一天的原始数据就是345GB;即使压缩后传输、二进制编码,也轻松超过80GB。这才是一个风场。
再往上一层,省级或区域级的集控中心往往要接几十个风场、光伏电站、储能站、升压站,数据量直接到每秒几十万条。这还不算智能电表百万级终端的上报流量。这就是能源数据和传统业务数据的本质区别——它不是用户点击产生的一条条行为记录,而是设备自动产生、7×24小时不间断的时序数据流。
这种量级的数据,直接让业务系统对数据库做写入,基本是找死。哪怕你用ClickHouse或时序数据库,也扛不住上游瞬时突增的冲击。所以数据链路的第一件事就是把“采集”和“处理”拆开,中间用一个能扛流量、能暂存、能分发的管道。这个管道,在当前的工程实践里,最主流的选择就是Kafka。
1.2 数据质量天然“脏”:传感器会撒谎,网络会抽风
能源现场和纯互联网机房不一样,设备部署在野外、屋顶、戈壁、海上。传感器故障、通信断连、PLC重启、网络抖动,这些全都会反映到数据上。我见过太多实际情况:某个风机的风速测点突然读到-87m/s,某个逆变器的功率在凌晨三点瞬间跳到满发值,某个站点的数据链路因为4G信号不好每隔几分钟断一次。
这些“脏数据”如果直接落到数据库、直接进大屏、直接喂给AI模型,后面的事故排查会让你怀疑人生。而Kafka在中间起的作用之一,就是给数据质量检查留出缓冲地带——数据先落到管道,流处理程序可以在这边做过滤、规整、异常标记,然后再决定哪些数据继续往下走。没有消息管道,你就必须在采集端或者存储端硬扛质量校验,要么太紧导致误杀正常数据,要么太松导致脏数据一路污染到应用层。
1.3 为什么不选RabbitMQ或RocketMQ
经常有同行问我:消息队列那么多,为什么能源场景大家默认Kafka?我一般会给一个横向对比:
- 这里需要极高的写入吞吐和长时间消息堆积能力。RabbitMQ核心是业务消息路由,性能和堆积能力面对亿级/天的时序数据会很吃力,积压到一定量级吞吐还急剧下降。RocketMQ吞吐不错,也支持事务消息,但整个生态和流计算框架的集成度不如Kafka。
- 这里的数据是“流”而不是“事件”。能源的测点数据是连续的流,下游通常对接Flink、Spark Streaming做流式计算、告警检测、指标聚合。Kafka和主流流计算框架的集成是最顺滑的,这个话题,后面聊生态时还会展开。
- 这里需要数据重放能力。下游算法模型调参时,经常要从Kafka里重新消费最近几小时甚至几天的数据。Kafka基于持久化日志的设计让“重放”几乎零成本,RabbitMQ的消费确认机制则很难做到这个。
一句话总结:如果消息管道是给业务系统传递订单、工单、通知,RabbitMQ够用;但如果管道里流的是设备测点数据、要做流计算和回溯分析,Kafka是更省心的方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据链路里的Kafka分工:管道、缓冲还是临时仓库?
2.1 一条完整的数据链路长什么样
在能源科技项目里,从设备端到大屏的完整链路通常是这样的:
text复制传感器/PLC/电表 → 采集网关 → 边缘处理 → Kafka → 流处理 → 存储/数仓 → 应用展示
最外层是现场设备,通过Modbus、IEC 104、OPC UA或者私有协议把数据送到采集网关。采集网关一般部署在场站边缘侧,干三件事:协议转换、数据合法性与频率校验、断点续传。边缘处理后的数据再通过网络(专线、5G、光纤)上报到中心侧的Kafka集群。
Kafka之后是流处理层,负责做实时告警(比如温度越限)、指标计算(比如5分钟平均功率)、异常检测(比如数据突变)。处理结果写到时序数据库、ClickHouse或数据湖里,最终喂给大屏、报表、AI预测模型和运维工单系统。
2.2 Kafka在这条链路里的“能和不能”
Kafka在链路里的定位非常清晰:它是数据中枢和缓冲池,不是数据库,也不是流处理引擎。
先说它“能”干什么:
- 削峰填谷。现场上报不是匀速的,白天光伏出力高、数据点位变化快,深夜量小;风来了整个风场疯狂上报,没风时安静。Kafka通过消息堆积机制,让后端处理系统始终以自己最舒服的速率消费,不会被上游流量尖峰打垮。
- 解耦生产与消费。采集端不需要关心下游是谁、下游是否可用。即使Flink任务挂了、数据库慢查询了,采集端照样往Kafka写,数据安全待在管道里,等下游恢复后继续消费。这个在运维事故期间真的太重要了。
- 多消费者广播。同一份设备数据,流处理要做实时告警,数仓要落明细数据,AI模型要特征输入,三个不同的消费者组可以互不干扰地各自消费同一个Topic里的数据。这个能力是“数据中枢”的核心。
再看它“不能”干什么,这部分往往被低估:
- 不能替代流计算引擎。Kafka Streams能做轻量级处理,但复杂窗口计算、多流关联、状态管理,还是Flink等引擎更合适。
- 不能做长期存储。Kafka的数据持久化是为了“缓冲”和“重放”设计的,不是廉价存储。数据保留30天没问题,保留一年,成本和维护复杂度就上去了。
- 不适合传大文件。视频监控帧、点云文件这类体积大的数据,别塞Kafka。Kafka擅长的是小而高频的消息,一条消息1MB以内都算大,实际工程里几百KB就该警惕了。
2.3 Topic与分区设计:按业务域拆分,按并发定分区
Topic和分区是Kafka里最核心的设计决策,而且改起来成本高,一开始就要想清楚。
我的建议是按业务域分Topic,而不是按数据源分。比如一个能源平台至少有这么几个Topic:
device-metric:设备运行测点数据,体量最大,是主Topicdevice-event:设备状态变更、告警事件、操作日志model-result:AI模型和流计算的输出结果raw-data:原始数据备查,可以设置较短保留时间
这样划分的好处是消费端可以按需订阅——告警服务只需要消费device-event,不用面对海量的device-metric。如果所有数据塞进一个Topic,消费者要过滤大量无关消息,效率和资源都是浪费。
分区数怎么定?关键在于消费并发度。Kafka的分区是并行消费的最小单位,一个消费组里的消费者数量最多只能等于分区数。如果你有3个消费者实例在跑,但Topic只有2个分区,那第3个消费者就是空转。反过来,如果分区数远大于消费者数,又会增加broker的元数据压力。一般经验是:分区数=预期的最大消费者实例数×1~2,同时考虑单个分区的吞吐能力(单分区每秒写入几千条在工程上很常见),两者取大。大多数能源项目从6~12个分区起步,完全够用。
3. 集群部署与参数调优:按吞吐量和保留天数倒推配置
3.1 版本选型与集群规模估算
现在的Kafka,新项目我建议直接上3.7以上版本,用KRaft模式,也就是把元数据管理从ZooKeeper里解放出来。早期Kafka依赖ZooKeeper做集群元数据存储,运维上多一套系统要管。KRaft模式下Kafka自己管理元数据,部署简单,故障恢复也快。如果你还在用ZooKeeper模式的老集群,能迁就早点迁。
集群规模怎么定?回答这个问题得先算两个指标:写入吞吐量和磁盘容量。
假设一个省级集控中心接入50个场站,平均每个场站5000条/秒,总写入就是25万条/秒。按单条200字节算,就是50MB/s的写入流量。这是一个中等偏上的能源项目规模。Kafka单broker顺序写磁盘的能力通常在100MB/s甚至更高,所以3个broker的集群在写入上完全能扛住。
磁盘容量按保留天数倒推。还是按50MB/s算,一天的数据是50×86400≈4.3TB。保留7天就是30TB,如果保留30天就是130TB。这个数字很现实,所以很多项目会开压缩(占满CPU但省带宽和存储)、限制单条消息大小,或者在Topic级别单独设置较短的保留期给原始数据。
3.2 磁盘、内存与网络:三个硬件瓶颈
Kafka的硬件选型,我踩过不少坑,说几点实在的:
- 磁盘:Kafka写入是顺序追加,所以机械盘顺序写也不是不能跑。但一旦涉及多个分区随机读写、副本同步、消费者追拉,机械盘就容易成为瓶颈。预算允许直接上SSD,单盘容量不需要太大,但I/O能力要好。另一个重要的是别把Kafka和ZooKeeper(如果还用老模式)、其他业务混在一块磁盘上,I/O争抢会让性能变得不可预测。
- 内存:Kafka主要靠PageCache加速读写,broker的堆内存不需要很大,反而操作系统PageCache越充裕越好。一般建议堆内存4~6GB足够,系统内存16~32GB,剩下的交给PageCache。
- 网络:Kafka是带宽敏感型系统,网卡建议千兆起步、万兆更好。尤其副本数设为3时,每次写入都会产生额外的副本网络流量。很多节点配置看起来很强,结果网卡先跑满了,这是最容易忽略的瓶颈。
3.3 关键参数调优清单
部署完成后,server.properties里这些参数值得逐个过一遍,我列一下在能源场景下常用的取值和建议:
| 参数 | 推荐值 | 说明 |
|---|---|---|
log.retention.hours |
168(7天) | 能源数据一般保留7~30天,具体看下游是否有长时间重放需求 |
log.segment.bytes |
1073741824(1GB) | segment过小会导致文件碎片多,过大则日志清理和重放不够灵活 |
num.partitions |
3 | 默认值,但其实每个Topic会单独指定分区,这个默认值影响不大 |
default.replication.factor |
2或3 | 能源数据不想丢,至少2,重要Topic可以3 |
min.insync.replicas |
2(配合3副本) | 保证写入时至少2个副本确认,防止“假成功” |
log.retention.check.interval.ms |
300000 | 日志清理检查频率,默认5分钟即可 |
auto.create.topics.enable |
false | 生产环境一定要关掉,否则误发消息会自动创建分区数不对的Topic |
message.max.bytes |
10485760(10MB) | 单条消息上限,能源数据一般很小,但留点余量给边端偶尔的批量上报 |
还有一个实践注意事项:default.replication.factor决定了自动创建的Topic副本数,但生产环境建议所有Topic都通过kafka-topics.sh显式创建,认真指定分区数和副本数,而不是依赖自动创建。自动创建在开发和测试环境方便,但到了生产环境,它会成为配置不统一的温床——某个服务忘记关自动创建,写了一个奇数分区的Topic,后面消费倾斜排查起来很痛苦。
4. 生产端与消费端:把数据“准确、不重复、不丢”地放上管道
4.1 生产者配置:acks=all、幂等开启、批量攒着发
数据能不能安全进管道,生产端的配置是第一道关口。我见过太多项目生产端用默认配置,结果数据丢了对不上账,根本不知道哪一环出了问题。这里给出一套适合能源数据上报场景的生产者配置:
properties复制acks=all
enable.idempotence=true
retries=10
max.in.flight.requests.per.connection=5
linger.ms=20
batch.size=65536
compression.type=lz4
逐个解释一下你为什么要这么配:
- acks=all:生产者要求所有同步副本都确认写入才返回成功,配合broker端的
min.insync.replicas=2,保证消息不会因为单个副本故障而丢失。这是“不丢数据”的核心保障。 - enable.idempotence=true:开启幂等生产者,Kafka会为每个生产者会话分配序列号,broker端对重复消息去重。配合
retries重试机制,既保证重试发送不会产生重复数据,也保证不会因为网络短暂抖动就丢失消息。 - linger.ms=20:意思是消息在缓冲区攒20毫秒再批量发送。能源数据允许秒级延迟,20毫秒的攒批对实时性几乎没影响,但能把吞吐量提上去不少。
- compression.type=lz4:能源数据重复度很高,压缩比可观。lz4是压缩速度和压缩率均衡的选择,snappy也行。压缩能显著降低带宽和broker磁盘占用。
这里有个权衡要说清楚:如果你在下游做了幂等消费,acks=all配合幂等生产端是最稳妥的组合;如果业务对吞吐极致敏感、可以容忍极少量消息丢失,那acks=1、关掉幂等也能跑,但能源数据我建议还是“不丢”优先。
4.2 消费者配置:手动提交、消费语义选择
消费端的配置和代码决定了数据能不能准确进入下游系统。核心要回答两个问题:offset怎么提交?处理失败怎么办?
我的建议是:能手动提交就别自动提交。enable.auto.commit默认是true,每5秒自动提交offset,但如果你处理完数据要写库、要调外部API,自动提交会导致两种坑:一是处理还没完成offset就提交了,程序崩溃后这部分数据消费不到了;二是处理成功了但offset提交延迟,重启后重复消费一批数据。
所以流程要调成:
- 拉取一批消息
- 处理并写下游
- 处理成功后手动提交offset(
commitSync,同步提交确保不丢;对性能极端敏感的场景用commitAsync但要做好失败补偿)
消费语义上,绝大多数能源数据处理走的是“at least once”语义:不丢,但可能有重复。要解决重复,不能靠Kafka,要靠下游的幂等——写入数据库时用唯一键、INSERT ... ON DUPLICATE KEY UPDATE或者按时间戳去重。这样即使消费端重复处理,结果也是对的。
还有一个在能源场景很常见的坑:消费处理的慢操作会把整个消费组拖垮。如果每条消息处理时都要查一次设备档案数据库、调一次外部API,吞吐量会惨不忍睹。我之前遇到过消费线程因为等待一个不稳定的设备档案查询接口,阻塞了几十秒,导致整个消费组Rebalance,空窗期数据积压成山。解决办法是批量查询档案并做本地缓存、给外部调用加超时熔断,后面故障排查章节我会详细展开。
4.3 消息格式与序列化:JSON够用,但要认真定义Schema
Kafka本身对消息格式没有要求,字节进去字节出来。但工程上最忌讳的就是“大家想怎么发就怎么发”——同一批设备数据,网关上报用JSON、流处理输出又换了一套字段,下游消费方对接起来全是坑。
我的经验是,至少要把消息格式和Schema固化下来。简单场景用JSON,字段名、类型、单位、时间格式必须写清楚;复杂场景直接上AVRO配合Schema Registry,好处是带Schema的消息自带版本管理,消费端能自动识别字段变更,解析性能也比JSON好很多。能源数据体量大、字段多,AVRO不是过度设计。
还有一个容易忽略的点:消息里的时间戳必须统一语义。设备产生数据的时间是event_time,Kafka接收消息的时间是ingest_time,流处理计算结果的时间可能是process_time。三个时间各有用途,但下游计算延迟时,必须明确用哪个时间作为基准。能源场景一般用event_time(设备侧时间)来计算指标,用ingest_time来监控链路延迟,两个都不能扔,设计消息格式时就把它们都带上。
5. 数据质量防线:从端侧校验到流上修正
5.1 三层质量防线
能源数据“脏”不是偶然,是必然。所以数据质量不能靠单一环节,而要做三层防线。
第一层是端侧采集网关校验。在边缘侧就把明显的非法数据过滤掉:数值超出合理范围(比如风速不可能为负数)、时间戳不在合理窗口内、设备状态码非法。网关侧的处理原则是“能拦就拦”,但要注意不能过度过滤——有些看起来异常的数据,可能是真实故障信号,直接扔掉等于把设备告警也丢了。所以更好的做法是给异常值打上标记(一个quality_flag字段),而不是直接删掉。
第二层是管道侧规整与修正。消费端从Kafka拿到数据后,流处理做完整性检查:补全缺失字段、归一化单位、识别重复消息、做乱序处理。这一层是数据质量的最后防线,处理逻辑用Flink、Kafka Streams或者普通消费者都能做。
第三层是消费侧幂等与约束。数据写入存储前,通过数据库唯一键约束、去重逻辑保证最终一致性。存储层的质量问题,不能指望上游完全干净。
5.2 重复与乱序:Kafka机制背后的两个隐藏陷阱
先讲重复。Kafka的at least once语义下,重复消息是常态:生产者网络超时重试、消费者处理成功但提交offset失败,都会造成重复。上一章说了靠下游幂等解决,这里再补充一个思路:流处理层可以用“去重窗口”,比如Flink基于device_id + event_time做状态去重,窗口大小根据网络延迟和重复概率设定。但Kafka本身不做这个事,它只保证分区内的有序和持久化。
再讲乱序。很多新手以为Kafka是“有序队列”,其实它的有序是有条件的分区内有序:同一个分区,消息按写入顺序存储,消费者看到的顺序就是写入顺序。但如果你有多个分区,业务上同一个设备的数据被路由到不同分区,跨分区的顺序就没有保证了。
所以生产者端要注意:同一类需要保序的数据,分区键要设计好。比如同一台设备的数据,用device_id做key,Kafka会保证同一个key的消息进同一个分区,天然有序。如果你的Topic有12个分区,100台设备,那么每台设备的数据始终落在固定分区,场景内有序是能保证的。
乱序的另一个来源是事件时间。比如网络断连导致设备端缓存了5分钟数据,恢复后一次性上报,Kafka收到这些消息时,它们的产生时间其实是5分钟前的。此时如果用处理时间做窗口计算,这些迟到的数据会被归到错误的窗口。工程上的标准做法是用事件时间窗口,并设置允许乱序的容忍延迟(Flink里是Watermark和AllowedLateness),让迟到5分钟以内的数据仍能进入正确窗口。
5.3 质量指标监控:每个Topic都应该有体检指标
数据质量不能靠出了事再去翻日志,得有日常体检指标。我们在生产环境里重点盯这些:
- 消息缺失率:消费端统计到的时间戳连续性,如果某个设备的消息时间戳出现大段空白,说明上游采集或传输有问题。
- 异常值占比:消费端对关键测点做范围校验,统计每秒或每分钟的非法值比例。比例骤升,往往是传感器批量故障或采集程序bug。
- 重复消息率:流处理去重模块统计的重复消息数量,如果重复率长期偏高,要去查生产端重试策略和消费端提交逻辑。
- 消费Lag:消费组落后生产端的消息数量,这是链路健康的温度计,后面专门讲。
这些指标不需要自己造轮子,流处理任务里顺手统计输出到另一个Topic,或者直接用Prometheus暴露指标都行。关键是让每个数据使用方都能看到“我今天消费的数据质量怎么样”,而不是等下游应用报错。
6. 一次真实故障排查:消息延迟5分钟,问题出在哪一环
6.1 现象与第一反应
回到开头那个场景。某综合能源平台大屏显示的光伏电站功率数据比现场晚5分钟,同时告警事件也延迟。平台侧数据库里数据正常,但时间上始终慢一截。当时团队第一反应是“是不是Kafka崩了”,但查了一下broker的CPU、磁盘、网络,都正常。
这只是表象。Kafka看起来正常,真正的问题恰恰藏在“看起来正常”的背后。
6.2 逐层排查链路
我的排查顺序是:先看生产端有没有堆积,再看消费端Lag,然后看分区分布,最后看下游处理瓶颈。
第一步,确认生产端是否正常。看采集网关到Kafka的发送速率和成功率,以及broker端的写入速率。如果在kafka-run-class.sh kafka.tools.JmxTool或者监控面板里看到Topic的每秒写入速率稳定,且生产端没有报错,说明数据进管道没问题。
第二步,看消费组Lag。执行:
bash复制kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group device_metric_consumer
输出里能看到每个分区的Current-offset、Log-end-offset和LAG。当时我们看到的结果很有代表性:6个分区里,5个分区Lag为0,只有分区2的Lag有几十万。这不是整体消费能力不足,而是典型的数据倾斜。
第三步,分析分区倾斜的原因。Kafka round-robin分区策略下,消息会均匀分布到各个分区。某个分区突然Lag,要么是分区key分布不均,要么是那个分区对应的消费者线程处理特别慢。
当时查了消费端的日志,发现分区2对应的消费线程,平均每条消息处理耗时比其它分区高一个数量级。顺着代码看,这个消费任务里有一段逻辑要调用设备档案查询接口——正好这个接口最近超时严重,每次调用要等30秒超时,而其它分区不涉及这段逻辑。
6.3 根因与修复方案
根因找到了:消费端的一个外部API调用没有超时控制,API故障导致对应分区的消费线程几乎停摆,整个消费组Lag集中在单分区。
修复做了三件事:
- 给外部调用加超时和熔断。HTTP客户端设置连接超时500ms、读取超速300ms,并加熔断器,连续失败就快速失败,不再等待。
- 把逐条查询改成批量预取+本地缓存。设备档案数据更新频率低,完全可以在消费启动时或者按分钟级批量加载,这个改动把消费单条消息的耗时从几百毫秒降到几毫秒。
- 消费线程池调整。让阻塞型操作和目标分区解耦,避免单分区单线程成为瓶颈。
修复后观察了半小时,Lag快速清零,大屏延迟恢复秒级。这个案例值得记住的倒不是具体故障,而是排查思路:Kafka延迟高,先分“生产问题、消费问题、倾倒问题”,再分“全局还是局部”。全局Lag高,通常是消费能力不足或者下游存储慢;局部Lag高,几乎都是分区倾斜或者单分区消费者卡住。
还有一个实操习惯:生产环境一定要对消费组Lag做告警,比如Lag超过10000或者持续增长超过5分钟就报警。因为很多时候,Lag是故障的前兆,早发现一小时,可能就避免一次全网大屏数据失效的事故。
7. 可视化与日常运维:不靠眼睛盯,靠指标和告警
7.1 可视化工具选型
Kafka的日常运维,光靠命令行确实累。尤其面对几十个Topic、十几个消费组的时候,没有可视化界面,排查问题全靠肉眼看命令输出,实在太原始了。目前社区常用的工具有这么几款:
| 工具 | 特点 | 适合场景 |
|---|---|---|
| Kafka UI | 开源免费,界面清爽,支持Topic管理、消费组Lag查看、消息浏览 | 日常开发调试,生产监控辅助 |
| AKHQ | 功能全面,支持Schema管理、消息查询、节点状态 | 团队规模大、需要权限管理的场景 |
| Kafka Eagle(EA) | 监控告警功能强,自带告警通知 | 已有运维体系,需要自定义告警的团队 |
| Prometheus + kafka-exporter + Grafana | 指标监控最强,可定制化程度高 | 监控告警体系完善、愿意投入精力搭建的团队 |
我的建议是:开发测试环境用Kafka UI这种轻量工具,生产环境至少用Prometheus+exporter做指标采集和告警,再配一个可视化面板。注意一点:可视化工具里的“消息浏览”功能在生产环境要收着用,直接去消费生产Topic有影响——有些工具会注册一个独立的消费组去读消息,如果分区数不允许这个消费组有足够的并发,反而可能引发Rebalance。
7.2 必须盯的核心指标
不依赖可视化工具,光用命令行也要能判断Kafka集群健康。我每天巡检和告警配置里必盯这几个指标:
- UnderReplicatedPartitions:分区副本落后的数量。大于0说明副本同步异常,可能是网络问题、broker故障或磁盘I/O瓶颈,持续存在会带来丢数据风险。
- OfflinePartitionsCount:离线分区数,大于0直接告警,说明分区leader不可用。
- ActiveControllerCount:Controller负责分区leader选举,这个值正常是1。频繁变化说明集群元数据不稳定,集群可能处于抖动状态。
- RequestHandlerAvgIdlePercent:请求处理线程空闲率。持续低于30%,说明broker的请求处理线程忙不过来,可能是网络或CPU瓶颈。
- 消费组Lag:前面讲过了,这是数据延迟的直接指标,必须告警。
这些指标通过JMX暴露,Prometheus的kafka-exporter和JMX exporter都能采集。在Grafana里配好面板后,集群状态一目了然。不需要盯指标实时变化,重点是设好告警阈值。
7.3 告警阈值设定与巡检习惯
告警阈值怎么定,每个环境不一样,但可以参考以下经验值:
| 指标 | 告警阈值 | 理由 |
|---|---|---|
| UnderReplicatedPartitions | >0 持续5分钟 | 短暂的副本同步滞后可能只是网络抖动,持续5分钟要注意 |
| OfflinePartitionsCount | >0 立即告警 | 离线分区直接影响读写,拖不得 |
| ActiveControllerCount | ≠1 持续1分钟 | 持续的非1说明集群元数据不稳定 |
| RequestHandlerAvgIdlePercent | <30% 持续10分钟 | 长期低空闲率说明broker处理能力告急 |
| 消费组Lag | >10000 或 增长速率>1000/秒 | 说明消费端处理跟不上或下游出错 |
| 磁盘使用率 | >80% | Kafka写满磁盘会直接拒绝写入 |
日常巡检我保持一个习惯:每天上班先看一遍消费组Lag的总览,哪个消费组今天比昨天峰值Lag高,就去查一下对应的业务在做什么变更。很多问题不是突然爆发,是慢慢累积的——消费Lag从100涨到1000再到10000,等你发现时业务大概率已经感知到延迟了。所以早发现的核心不是“巡检更勤快”,而是“告警阈值要设得更敏感”。
巡检时可以用的几个命令也顺手分享:
bash复制# 查看所有Topic的详情,注意分区数和副本分布
kafka-topics.sh --bootstrap-server localhost:9092 --describe
# 查看所有消费组的Lag情况
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --all-groups
# 查看broker节点的运行状态
kafka-broker-api-versions.sh --bootstrap-server localhost:9092
# 如果某个broker被卡住,用jstack抓线程栈分析
jstack <kafka_broker_pid>
有人可能觉得命令行的方式不够“现代化”,但在一次线上事故中,往往最快的路径就是CS亮起、直接命令行拉消费组状态。图形界面和命令行各有所长,关键是别只依赖一个。
最后再多说一句我自己踩坑换来的经验:Kafka的版本升级别拖。旧版本上一些已知的bug(比如长时间运行后的元数据不一致、消费者Rebalance风暴)在新版本里早就修了,但很多人会因为“线上稳定就不动了”一直拖着。实际上,Kafka的小版本升级(比如3.5升3.7)在滚动重启下基本不影响业务,找业务低峰期操作,收益远大于风险。数据管道是能源数据处理系统的心脏,心脏健康了,上面的业务才不会整天跟着数据延迟和数据丢失的问题折腾。
