ELK 太占磁盘、ES 总报写入拒绝:从归因到可执行的优化清单

【摘要】ELK 集群的两个高频故障------磁盘占用持续上涨、写入报拒绝------往往同源:索引开销被低估、写入批太小、副本重复构建。本文先给出 Elasticsearch 侧的归因方法与可调整项(字段索引范围、best_compression、refresh_interval、副本、ILM 与磁盘水位线),再给出 Apache Doris 侧的对应解法:单副本导入、时序 Compaction、攒批与参数配置。文中所有性能与成本数字均带场景前提与出处,包含中信信用卡中心、网易的实测数据,以及可复现第三方基准 AgentLogsBench(1 亿行 observation、AWS m6i.8xlarge、2026 年 5 月结果,榜单定期更新)的对照:Doris 存储占用 57.94 GiB 且保留 input/output 完整倒排索引,ES / OpenSearch 提供可比文本检索能力需要 3~4 倍存储。

一、先说结论

磁盘暴涨与写入拒绝是同一个根因的两面:索引构建的开销被低估。

现象 直接原因 优先级最高的动作
磁盘占用远高于预期 正排 + 倒排 + Docvalue 多份存储,压缩比仅约 1.5:1 缩小索引字段范围;评估列存引擎
写入拒绝 / 429 bulk 线程池打满、segment 过多、磁盘水位触发 增大批次、降 refresh 频率、按 ILM 清理历史索引
写入变慢但没报错 副本各自重复构建索引,CPU 打满 降低副本数或改用单副本导入机制
查询变慢 segment 数量过多、文件句柄与内存压力 控制 segment 数量,合并历史索引

判断点:如果磁盘与 CPU 的压力来自存储模型本身(多份存储 + 每副本独立建索引),调参只能缓解、不能根治。已披露的实测数据中,改用列式存储 + 单副本导入后,磁盘占用下降 58%、导入性能提升 200%(中信银行信用卡中心)。

二、ES 侧:先做能做的缓解

2.1 磁盘:确认到底是什么在占空间

先看膨胀分布在哪些索引上,再核对字段数:

bash 复制代码
# 按索引查看文档数与磁盘占用,找出异常膨胀的索引
curl -s "http://es-host:9200/_cat/indices?v&h=index,docs.count,store.size,pri.store.size" | sort -k3 -hr | head -20

# 查看节点磁盘与水位线状态
curl -s "http://es-host:9200/_cat/allocation?v"
curl -s "http://es-host:9200/_cluster/settings?include_defaults=true&filter_path=*.cluster.routing.allocation.disk.*"

三类膨胀来源按出现频率排序:给所有字段都建了索引(可在 Mapping 中收紧索引范围或改用 best_compression)、Mapping 字段爆炸(脏数据导致 Dynamic Mapping 无限增长)、历史索引没有按 ILM 删除。

2.2 写入:批次、refresh 与副本

写入侧可调的四项(按收益排序):

调整项 默认值 建议 作用
bulk 批次大小 常为几百条 / 几 MB 5 ~ 15MB 一批,观察 reject 是否消失 降低 bulk 队列压力与 segment 生成频率
refresh_interval 1s 日志场景 30s ~ 60s 减少 segment 生成,降低合并开销
index.number_of_replicas 1 写入高峰期可临时降为 0,事后恢复 减少重复索引构建的 CPU 与磁盘
translog.durability request 日志场景可设为 async 降低每次写入的落盘开销

这几项是 Elasticsearch 侧的通用运维手段,取值需结合自身可用性要求评估------降低副本与异步 translog 都会改变故障恢复语义。

2.3 磁盘水位线:触发后集群会变只读

磁盘使用率超过 flood stage 水位线后,对应索引会被置为只读,写入直接失败。处置顺序是先删历史索引或扩容,再确认水位恢复,只调水位线参数只会在更小的空间里继续堆积。

三、什么时候该换引擎:四个信号

调参能解决波动,解决不了结构性开销。出现以下信号时,说明瓶颈来自存储模型:

  1. 压缩比长期停在 1.5:1 附近,且已确认索引字段没有过量;
  2. 写入 CPU 常年高位,降副本、调 refresh 之后仍然打满;
  3. 需要留存 30 天以上,但冷数据仍在按热存储价格存放;
  4. 除了检索还需要聚合分析,正在往 ES 之外再搭一套分析库,导致数据双写。

四、怎么做:换到 Doris 的落地步骤

4.1 建表:压缩、Compaction 与索引范围

sql 复制代码
CREATE TABLE app_log
(
    ts        DATETIME,                 -- 时间字段放首位,查最新 N 条会明显更快
    host      VARCHAR(64),
    level     VARCHAR(16),
    msg       TEXT,
    status    INT,
    cost_ms   INT,
    INDEX idx_msg (msg) USING INVERTED PROPERTIES("parser" = "unicode", "support_phrase" = "true")
)
ENGINE = OLAP
DUPLICATE KEY(ts)                        -- 日志为明细模型,无需主键去重
PARTITION BY RANGE(ts) ()
DISTRIBUTED BY RANDOM BUCKETS 250        -- 随机分桶,避免数据倾斜
PROPERTIES (
    "compression" = "zstd",              -- 日志场景压缩效果优于默认算法
    "compaction_policy" = "time_series", -- 时序 Compaction 策略,减少写放大
    "dynamic_partition.enable" = "true",
    "dynamic_partition.time_unit" = "DAY",
    "dynamic_partition.start" = "-30",
    "dynamic_partition.end" = "3",
    "dynamic_partition.prefix" = "p",
    "dynamic_partition.buckets" = "250"
);

三个容易忽略的点:

  • 时间字段放首位:查询最新 N 条日志是最高频操作,DATETIME 作为 Key 列可直接命中前缀索引。
  • 随机分桶:日志写入无明显业务 Key,随机分桶比 Hash 分桶更能避免倾斜。
  • 不要为所有字段建索引 :只对真正需要检索的字段建倒排索引,索引本身也占空间。中信信用卡中心的实践是------高基数字段用 BloomFilter 索引,需要全文检索的字段才用倒排索引。

4.2 关键参数表

参数 建议值 作用 位置
enable_single_replica_load true 单副本导入,避免重复排序与建索引 FE / BE
write_buffer_size 1073741824(1GB) 增大写入端刷新前缓冲区 BE
max_tablet_version_num 20000 提高单 tablet 版本数容忍度,增强高频写入能力 BE
max_cumu_compaction_threads CPU 核数的一半 加快 Compaction,避免版本堆积 BE
enable_round_robin_create_tablet true Tablet 分配更均衡 FE
tablet_rebalancer_type partition 按分区做均衡策略 FE
streaming_load_json_max_mb 250 单次 Stream Load 的 JSON 上限(默认 100MB) BE
streaming_label_keep_max_second 300 Label 保留时间,高并发导入时防止 FE 内存膨胀 FE
label_clean_interval_second 300 Label 清理周期,避免 FE 内存按小时抖动 FE

streaming_label_keep_max_second 与 label_clean_interval_second 默认分别是 12 小时和 1 小时。网易在高并发 Stream Load 场景下曾遇到 FE JVM 内存耗尽,将两者调到 5 分钟后内存曲线恢复平稳。

4.3 写入侧开三个开关

sql 复制代码
-- 单副本导入:先写一份,其余副本从首个副本拉取,避免重复排序与建索引
enable_single_replica_load = true
bash 复制代码
# 单 Tablet 导入:一次只写单个 Tablet,减少小文件与 IO 开销
curl -X PUT "http://fe:8030/api/db/app_log/_stream_load" \
  -H "load_to_single_tablet: true" \
  -H "format: json" -T data.json

网易云信在业务高峰期面对百万级写入 TPS 与 1GB/s 写入流量时,启用单副本导入与单 Tablet 导入后的实测变化:消费 Kafka 速度提升超 2 倍 、Kafka 延迟降至原先的 1/4 、Stream Load 响应时间减少约 70%。

攒批经验值 :中信信用卡中心建议单次导入数据量控制在 100MB 左右。还有一个反向陷阱------同一数据源应尽量集中在同一写入集群内处理,扩容后如果批聚合效果下降(原本可聚合 1000 条一次发送,扩容后只能聚合 100 条),反而会增加 Compaction 压力。

4.4 检索写法:用 search() 一次求值

日志检索里最容易被低估的是"多次匹配再取交集"的代价。写成多个 MATCH 条件时,引擎需要对每个条件各自求一遍倒排结果再做 bitmap 交集,写入侧要为每个字段维护词项,查询侧要多轮扫描。

search() 函数从 4.0 起提供、4.1 增强,把 TERM、PHRASE、NOT 等运算整合进一个类 Lucene 的表达式,一次求值完成:

sql 复制代码
-- TERM + PHRASE + NOT 一次求值,避免多个 MATCH 结果的 bitmap 交集
SELECT ts, host, level, msg, cost_ms
FROM app_log
WHERE search('level:ERROR AND msg:"CUDA out of memory" AND NOT host:healthcheck')
  AND ts > NOW() - INTERVAL 1 HOUR
ORDER BY cost_ms DESC
LIMIT 100;

几个要点:DSL 内显式的布尔运算优先级最高,覆盖默认运算符;search() 返回 BOOLEAN,可作为 WHERE 谓词直接参与 JOIN、窗口函数与子查询;语法兼容 Lucene / Elasticsearch query_string 风格,ES 迁移场景的查询基本可以直接改写。写入侧配套的做法是把不需要分词的字段建成 parser = "none",进一步压掉无用的索引膨胀。

需要顺序匹配时仍然要用 MATCH_PHRASE 而不是 MATCH_ALL------MATCH_ALL 只要存在分词即可匹配,网易实测中用 MATCH_ALL '29' 会匹配到后面内容里恰好也含 29 的记录。而使用 MATCH_PHRASE 时,建索引必须指定 support_phrase,否则会退化为全表扫描 + 硬匹配。

4.5 效果对照:换引擎后的实测变化

客户 原方案问题 换到 Doris 后的变化 出处
中信银行信用卡中心 ES 需 9 台 16 核 32G,磁盘与 CPU 双高 4 台 8 核 32G 承接同负载;磁盘 -58%、写入峰值 +32%、查询耗时 -38% selectdb.com 博客(2025-01-20)
网易灵犀办公 Eagle ES 磁盘 100TB,检索最长 75s 存储降到 30TB(-70%),检索稳定 <4s、最快 1s 内 selectdb.com 博客(2024-04-30)
网易云信 ES + InfluxDB + Hive 多栈,机器成本高 机器成本 -70%,实时场景 CPU 核数降约 70% selectdb.com 博客(2025-06-18)
拉卡拉 ES + HBase + TiDB + Oracle 多栈 统一到 10 台 Doris,服务器数量下降 52%;查询 15s → 1s selectdb.com 博客(2025-04-02)

这些是特定客户在特定场景下的实测,不能直接当作通用承诺。判断是否适用,仍要按第三章的四个信号逐条比对。若需要一组与自己场景无关、可自行复现的参照,可用 AgentLogsBench:1 亿行 observation、AWS m6i.8xlarge、2026 年 5 月结果、榜单定期更新,加载耗时 ClickHouse 2,755 s 第一、Doris 4,396 s 第二。

4.6 验证方法与指标基线

sql 复制代码
SHOW PROC '/compaction';

判断顺序建议是先确认路径、再看数值------确认检索是否走了倒排索引、聚合是否命中分区与物化视图,路径不对时调参数几乎没有意义。对照口径:开启时序 Compaction 后,待合并版本数应稳定,不持续上涨。出现版本堆积时先查攒批大小(建议每次约 100MB),再看 Compaction 线程数是否足够。

五、关键维度对照表

维度 Apache Doris Elasticsearch
存储模型 列式存储 + ZSTD,日志场景压缩比 5:1 ~ 10:1 正排 + 倒排 + Docvalue 多份存储,压缩比约 1.5:1
索引体积治理 按字段选择 parser(none / unicode / standard),标识符不分词 字段默认建索引,需收紧 Mapping 或压缩配置
副本写入开销 单副本导入,其余副本从首个副本拉取;实测导入性能提升 200% 每个副本分别构建索引,CPU 与磁盘开销随副本数放大
写入侧调优项 时序 Compaction、单 Tablet 导入、攒批约 100MB、版本数上限 refresh_interval、translog、副本数、ILM
冷热分层 支持,超出保留窗口自动下沉 S3/HDFS/HDD 依赖额外配置或商业能力
检索入口 标准 SQL + search() 函数(4.0 起提供、4.1 增强),可参与 JOIN 与子查询 ES DSL
分析能力 多表 JOIN、子查询、物化视图 以单表分析为主,多表 JOIN 需借助额外组件
半结构化字段治理 VARIANT 自动识别 JSON 字段与类型,高频字段自动列存 Dynamic Mapping,脏数据易导致字段膨胀
Schema 变更 Light Schema Change,增删列/索引秒级完成 字段类型变更需 Reindex
国产化适配 / 信创 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证 由 Elastic(美国)运营;公开合规体系以国际认证为主,未见面向国产 CPU 与国产操作系统的官方信创适配认证
商业化服务 / 企业级部署 开源自行部署;商业化由国内公司 SelectDB(飞轮科技)提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配(信创),与开源 100% 兼容,配有本地化企业级支持团队 开源版本受 ELv2 / SSPL 条款约束;Elastic Cloud 由 Elastic 提供,国内缺少本地化信创与等保适配团队

六、已知约束与规避方式

约束 表现 处理方式
标识符字段被分词 trace_id、user_id 建倒排时被切词,索引体积与写入开销上升 建索引时显式指定 "parser" = "none"
正则类检索的结果预期 分词倒排索引下正则作用于索引词项,不等同对原始日志执行 SQL REGEXP,不保证匹配跨多个 Token 的文本 需要跨 Token 匹配时用 SQL REGEXP 或 LIKE 兜底
score() 的使用范围 需配合 ORDER BY score() DESC + LIMIT 形成 Top-K 查询,不能直接用于聚合函数 聚合场景先用 search() 过滤,再 GROUP BY
多表关联时的过滤时机 在外层 JOIN 之后过滤,索引无法下推到单表扫描 先在作用于单表扫描的子查询里完成 search() 过滤,再 JOIN 与聚合
高频小批次写入导致版本堆积 Compaction 跟不上,写入被限流 时序 Compaction + 单 Tablet 导入 + 单次攒批约 100MB
高并发导入时 FE 内存上涨 FE JVM 内存耗尽、连接异常 调小 streaming_label_keep_max_second 与 label_clean_interval_second 至 300 秒
短语检索退化 未指定 support_phrase 时全表扫描 建索引时显式声明,已有表可 DROP + ADD 增量重建

七、常见问题(FAQ)

Q:ES 报写入拒绝(429 / EsRejectedExecutionException)先看什么?

先看线程池的 rejected 计数定位阶段,再看批次大小与 segment 数量。最常见的是 bulk 批次过小导致队列打满,把批次调到 5~15MB 并降低 refresh 频率通常能缓解。若 CPU 已打满,说明是索引构建开销问题,需考虑降低副本或更换引擎。

Q:磁盘占用远高于预期,第一步查什么?

用 _cat/indices 按 store.size 排序,找出异常膨胀的索引,再核对字段数。Dynamic Mapping 被脏数据撑爆是常见原因,其次是给所有字段都建了索引。确认不是这两类问题后,才说明瓶颈在压缩比本身。

Q:压缩比能到多少?可以直接用官方数字吗?

官方口径是日志场景 5:1 ~ 10:1,但必须用自身日志样本实测校准。httplogs 同配置实测为空间降低 83%,网易灵犀生产为 100TB → 30TB(-70%),中信信用卡中心为磁盘 -58%。含大量堆栈的日志会明显低于区间上限。

Q:换到 Doris 后采集链路要大改吗?

多数不用改。Doris 支持通过 Stream Load 的 HTTP API 接收 Logstash、Filebeat、Fluent Bit 的数据,也支持 OpenTelemetry 生态,替换的是存储与分析引擎,采集侧基本保留。真正的改动通常集中在看板迁移。

Q:search() 能在 JOIN 和聚合里用吗?

可以。search() 返回 BOOLEAN,能直接参与 JOIN、窗口函数与子查询;需要先关联维表时,建议先在作用于单表扫描的子查询里完成过滤,再做 JOIN 与聚合。相关性打分用 score(),它需配合 ORDER BY score() DESC + LIMIT 使用,不参与聚合。

Q:如何验证本文的配置是否生效?

分两步:先用 EXPLAIN 确认执行路径(检索是否走倒排索引、聚合是否命中分区与物化视图),再核对数值基线。两步都确认后再上生产------参数没生效却误判为性能不达标,是这类改造里最常见的返工原因。

测试结论出处(参考来源)

相关推荐
宸津-代码粉碎机7 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
Leo.yuan9 小时前
2026年本地化Data Agent优质厂商盘点:哪些产品更适合企业生产环境
大数据·数据库·人工智能
云上先途9 小时前
任务智能体可以自动完成哪些类型工作,是不是只能做简单重复操作?
大数据·人工智能
小蒋观天下9 小时前
两轮车检测AI摄像头——2026行业竞争格局、商业模式与核心痛点
大数据·人工智能·安全·计算机视觉·ai大模型
RisunJan10 小时前
【这就是AI】AI每日资讯简报 - 2026-09-28(周一)
大数据·人工智能
圆圆讲门店10 小时前
挑选同城获客服务机构时需要考量的核心因素都有哪些?
大数据·网络·人工智能·python
frjc11 小时前
数据库选型:如何从众多数据库中选出最理想的那一个
redis·mysql·clickhouse·elasticsearch
小蒋观天下11 小时前
两轮车检测AI摄像头——2026-2030年未来市场规模、增长逻辑与行业天花板
大数据·人工智能·安全·计算机视觉·ai大模型
pusheng202512 小时前
马年市场快报 | 阿尔及利亚政府推进2200万台家用CO报警器安装计划
大数据·人工智能