SkyWalking 日志又积压 1900 万:Kafka 分区明明均匀了,凶手却藏在 ES 段合并里
摘要SkyWalking 日志积压逼近 1900 万但 Kafka 分区已均匀瓶颈下移到 ES。顺着「生产→消费→落库」逐段排查用 hot_threads、_cat/shards、thread_pool 三连定位真凶大头日志被 SkyWalking 归为 super dataset36 分片/0 副本/DAY_STEP5单分片 20GB 让段合并轮流打满磁盘 IO、反压积压。DAY_STEP 从 5 改成 1、单分片降到 4.6GB 后几分钟清空。两坑分片配置是烟雾弹、热点轮动≠数据倾斜。上一集我们把 SkyWalking 的 Kafka 分区倾斜治好了——把 Agent 里固定的key改成null数据从此均匀落到 12 个分区。我以为这事儿就此翻篇了。结果没过多久监控大盘又红了消费积压逼近 1900 万而且这次 Kafka 分区是均匀的。生产均匀、消费均匀、却照样堆积——这就好比 12 个食堂窗口排队人数一样多可饭菜还是出不来。那问题一定不在窗口而在更后面的厨房。这一篇就是从「分区都均匀了为什么还积压」一路追到 ES 段合并热点、最后靠一个参数收工的完整复盘。前置阅读第一阶段「Kafka 分区倾斜 → key 改 null」的完整故事见上一篇 《SkyWalking 消费积压 6 亿条一次 Kafka 分区倾斜的深度复盘》。本篇假设你已经知道「keynull 让数据均匀分区」这个背景不再展开。一、问题现象分区均匀却又积压了距离上次治理过去没多久SkyWalking 的 Kafka 消费组又开始积压峰值逼近1900 万条。研发同学的体感和上次一样难受日志查询又开始延迟“查不到最新日志”链路追踪页面数据滞后积压量持续往上爬不收敛但有一个地方和上次完全不同——上次是分区严重倾斜少数分区在 996、其他在摸鱼这次打开分区维度的监控生产均匀、消费也均匀12 个分区齐头并进可整体还是在积压。上次的病根已经治好了分区不歪了。这说明瓶颈不在 Kafka 这一层而是被它下游卡住了——消息消费出来写不进去。二、排查现场顺着「生产 → 消费 → 落库」往下找SkyWalking 的数据链路很清晰Agent → Kafka → OAP消费 → Elasticsearch落库Kafka 那层已经确认均匀了OAP 消费也跟得上那就只剩最后一环——ES 写入。1. 先看大头在哪个 topic在 Kafka UI 上扫一眼各 topic 的数据量skywalking-logs一骑绝尘——500 GB 量级、7 亿多条其余 topic 加起来都不够它一个零头。所以这次的主战场是日志落库目标是 ES 的日志索引。2. ES 机器一个节点被打满而且读 IO 高得离谱集群是 3 台机器sw2 / sw3 / sw4装 ES另有一台sw1 完全空闲、没装 ES。拉一眼资源总览主机健康值CPUIOutil磁盘读磁盘写sw470最差78%82%247 MiB/s10 MiB/ssw38454%54%262 MiB/s21 MiB/ssw29326%28%184 MiB/s7 MiB/ssw1无 ES998%0%0—两个细节非常刺眼单节点被打满sw4 的 IOutil 飙到 82%其他两台轻松。瓶颈是读不是写热点节点磁盘读 200 MiB/s写才 10 MiB/s。一个日志写入场景凭什么读这么猛3. 反直觉的一幕热点机器会漂移过了几天再看热点居然换了一台机主机6/76/11sw4IOutil82%热点IOutil 31%恢复了sw3IOutil 54%IOutil82%变热点了sw2IOutil 28%IOutil 55%热点不固定在某一台而是在节点之间轮流坐庄。到这里一个特别容易让人跳进去的坑出现了——“热点会轮动肯定是数据倾斜某些大分片今天落 sw4、明天落 sw3……”我一开始也是这么猜的。但这个直觉是错的下一节用证据打脸打的是我自己的脸。三、原因分析一个烟雾弹两个被推翻的假设️先给张对照表上文资源监控用的是主机名sw*下文 ES 命令输出用的是节点名es0*两套名字指的是同一批机器——sw4 es01、sw2 es02、sw3 es03sw1空闲、没装 ES。所以下面hot_threads里 78% 那台es01正是上一节 IOutil 82% 的热点sw4——对着这张表看就不会把它俩当成两台机。1. 烟雾弹SHARDS_NUMBER12看着完全没问题第一反应是去翻 ES 分片配置结果看到SW_STORAGE_ES_INDEX_SHARDS_NUMBER1212 个分片摊到 3 个节点每节点 4 个理论上完美均衡。看到这行配置很容易得出配置没问题是 SkyWalking OAP 存储逻辑有 bug的结论。但这行配置是个烟雾弹——先按下不表我们用三条命令把现场钉死再回头看它为什么是烟雾弹。2.hot_threads凶手是 Lucene 段合并直接问 ES“你的 CPU 到底在忙什么”GET _nodes/hot_threads78.1% cpu by thread elasticsearch[es01][[sw_log-20260608][15]: Lucene Merge Thread] ...ConcurrentMergeScheduler$MergeThread.run 21.7% cpu by thread elasticsearch[es03][[sw_log-20260608][4]: Lucene Merge Thread] ...SegmentMerger.merge清一色的Lucene Merge Thread——是**段合并segment merge**在吃 CPU 和磁盘读。而且search线程池三节点全是 0这解释了读 IO 为什么这么高——不是查询是合并在读老段、写新段。段合并要把多个小 segment 读出来归并成大 segment是个典型的读密集操作。凶手锁定段合并热点。3._cat/shards数据其实完全均匀倾斜假设当场被推翻那是不是大分片扎堆某台机查分片分布GET _cat/shards/*log*?vsstore:desc按节点汇总后画面让我有点意外ES 节点分片数数据量es0148~515 GBes0248~515 GBes0348~517 GB三节点分片数一样、数据量几乎一样均匀得不能再均匀。我猜的数据倾斜被自己的命令打脸了。那热点轮动到底怎么回事答案在分片的大小上sw_log-20260603约 800 GB / 36 分片 单片约 22 GBsw_log-20260608约 720 GB / 36 分片 单片约 20 GB等等——配置里明明写的 12 分片这里怎么变成36 分片了而且单片 20 GB 是什么概念烟雾弹要现形了先记住这两个数。4.recoverythread_pool排除搬迁顺手找到反压出口再补两刀把其他可能性排干净GET _cat/recovery?active_onlytrue # 返回 [] → 没有任何分片在搬迁/重平衡排除 rebalance GET _cat/thread_pool/write,search?vhnode_name,name,active,queue,rejectedES 节点线程池activequeuerejectedes03此刻正在 mergewrite82320es01write000es02write000三节点search000正在做段合并的 es03write队列堆到了 232它也正是上面hot_threads里那个在合并[sw_log-20260608][4]的节点。反压链路一下就通了合并把节点的 IO/CPU 吃满 → 该节点写入队列堆积 → OAP 的 bulk 写入变慢甚至被拒 → OAP 放慢从 Kafka 拉取的速度 →Kafka 积压。而search全 0再次确认这台机不是被查询拖垮的纯粹是合并。5. 真相大头日志根本没走那个 12而是 super dataset 的另一套参数现在回收烟雾弹。翻 SkyWalking 文档才反应过来SW_STORAGE_ES_INDEX_SHARDS_NUMBER12只管 metrics 这类普通索引。而日志、链路这种海量数据SkyWalking 专门归到一类叫super dataset走的是另一套参数SW_STORAGE_ES_SUPER_DATASET_INDEX_SHARDS_FACTOR3# 分片 12 × 3 36SW_STORAGE_ES_SUPER_DATASET_INDEX_REPLICAS_NUMBER0# 日志 0 副本SW_STORAGE_ES_SUPER_DATASET_DAY_STEP5# 5 天才滚一个索引三个参数凑出了一条完整的因果链参数值后果SHARDS_FACTOR336 分片分片数其实够多不是分片数的锅DAY_STEP55 天一个索引5 天的日志约 165 GB/天全塞进同一批 36 分片 → 单片撑到 20 GBREPLICAS00 副本无读冗余且任一节点宕机即丢日志埋了个雷见后文症结是DAY_STEP5把单分片养成了 20 GB 的巨无霸。合并一个 20 GB 的大分片是一次巨型的读 CPU 操作而段合并是突发的、按分片各自触发的——哪几个大分片碰巧在同一时刻、同一台机上一起合并那台机的 IO 就瞬间被打满。合并完了转到别的分片、别的机器于是看起来像热点在轮动。所以「热点轮动」不等于「数据倾斜」。底层数据是均匀的轮动只是段合并的突发性在不同节点上轮流引爆的假象。我一开始那个肯定是倾斜的直觉正是被这个假象带偏的。一句话总结根因大头日志走的是 super datasetDAY_STEP5让单分片高达 20 GB巨型段合并轮流打满各个 ES 节点的磁盘 IO反压回 Kafka 形成积压。和SHARDS_NUMBER12、和数据倾斜都没关系。把前面三节的排查证据串成一条因果链根因DAY_STEP5红→ 单分片 20GB → 巨型段合并在均匀节点间轮流引爆制造热点轮动假象→ 节点 IO 打满、write 队列堆 232 → OAP 放慢拉取 → Kafka 积压 1900 万红。解法只需回到链条源头把DAY_STEP改成 1。四、解决方案把单分片喂瘦根因清楚了思路就一句话——让单个分片别那么大段合并自然就轻了。最直接的杠杆就是改DAY_STEP。方案一治本DAY_STEP5 → 1索引按天滚SW_STORAGE_ES_SUPER_DATASET_DAY_STEP1同样 36 分片但一个索引只装 1 天的数据单片从20 GB 直接降到约 4.6 GB落进 ES 推荐的健康区间。段合并的规模和耗时随之降到约 1/5单台机器再也不会被一次大合并打满。⚠️改之前必须知道的两个坑DAY_STEP 是对存量不友好的参数只对新建索引生效。SkyWalking 是按时间戳 当前 DAY_STEP反推索引名去查的。改成 1 之后老的 5 天大索引里除了窗口首日之外的日志会查不到数据还在盘上只是索引名对不上了直到老索引被 TTL 清掉。老大索引可能不被 TTL 自动清理。同样因为反推索引名对不上那两个 20 GB 的老索引可能赖着不走需要手动DELETE确认回收。实操建议改完DAY_STEP1等新索引正常产出、确认不再需要历史日志后手动删掉老的 super dataset 大索引——一举三得消除查询空洞、回收上 TB 空间、存量大索引的合并压力当场归零。方案二配套从源头减量DAY_STEP治的是切分数据总量本身也偏大约 165 GB/天可以再做减法缩短日志保留天数SW_CORE_RECORD_DATA_TTL少留几天分片更小、合并更轻评估日志按错误 / 慢请求采样上报从采集端减少skywalking-logs的量思路同上一篇给链路降采样。方案三兜底 隐患处理临时止血合并其实已经在限速hot_threads里能看到MergeRateLimiter.maybePause实在急可再调小index.merge.scheduler.max_thread_count给写入让路但治标。白捡一台那台空闲的 sw1 加进 ES 集群3 节点扩 4 节点每节点分片从 48 降到 36合并并发头寸更宽。0 副本的雷super dataset 是 0 副本任一 ES 节点宕机 该节点的日志分片直接丢失且不可查。这是稳定性隐患治理时一并评估要不要给它配 1 副本代价是写入和存储翻倍需权衡。五、解决验证7 分钟从 1900 万降到 10 万以下把DAY_STEP改成 1 后重建 SkyWalking OAP效果立竿见影时间状态00:05:45 开始重建 OAP此刻 Kafka 积压约1893 万00:12积压从 1893 万降到正常的 10 万以下消费积压过程中三台 ES 的 CPU 终于均衡了不再有某台被打满积压消费完毕后CPU 整体回落整体积压曲线断崖式下跌一个参数7 分钟积压清零。六、举一反三三条能带走的经验这次复盘最值钱的不是改 DAY_STEP这个动作而是过程里踩过的三个认知坑1. 积压排查要顺着「生产 → 消费 → 落库」逐段走别停在第一层第一阶段我们停在 Kafka治好了分区倾斜。但积压的根可能在更下游——这次 Kafka 完全正常瓶颈在最末端的 ES 写入。看到积压别只盯着消息队列沿着数据最终要去的地方一段段往下查。2. “配置看着对” ≠ “配置在起作用”SHARDS_NUMBER12是个教科书级的烟雾弹——它语法正确、值也合理却根本不管大头日志。很多组件都有普通配置和特殊数据集旁路配置之分SkyWalking 的 super dataset 就是典型。当一个配置看着没问题但现象还在先确认它到底管不管你这条数据路径而不是急着甩锅给框架有 bug。3. “热点轮动” ≠ “数据倾斜”热点在机器间漂移最容易让人脑补成数据偏了。但突发型后台任务段合并、GC、compaction……在多个均匀节点上轮流引爆同样会制造轮动热点的假象。别靠直觉下结论用hot_threads在忙什么_cat/shards数据均不均recovery有没有在搬三件套把现场钉死证据比直觉可靠得多。三条命令、一个参数把一次分区都均匀了为什么还积压的悬案破了。如果你也在用 SkyWalking ES 存日志不妨现在就去看一眼自己的SUPER_DATASET_DAY_STEP和单分片大小——别等积压 1900 万了才想起它。觉得有用的话点个赞收藏一下下次半夜被 SkyWalking 积压告警叫醒时方便快速翻出来抄作业。上一集在这儿《SkyWalking 消费积压 6 亿条一次 Kafka 分区倾斜的深度复盘》。延伸阅读SkyWalking 消费积压 6 亿条一次 Kafka 分区倾斜的深度复盘 —— 本系列上一集先把 Kafka 分区倾斜key 固定治好本篇承接其后从 MQ 积压追到事件总线诊断 4K 线程吃光 7G 内存的实战 —— 同为消费积压逐层排查从积压现象追到根因【待发布后补充引用关系《一台机磁盘读 180MB/s、另两台几乎为 0SkyWalking 又积压凶手是抢走 page cache 的同机 OAP》】 —— 本系列第三集待发布上线后换 CSDN 链接️ 标签SkyWalkingElasticsearch消息积压Kafka线上排障性能优化