日志场景 Elasticsearch 替换实操:建表、索引、写入链路与查询改写的完整参数

摘要 :日志与可观测场景用 Apache Doris 替换 Elasticsearch,工程动作集中在建表模型、索引配置、写入攒批与查询改写四处。中信银行信用卡中心日志云平台从 ES 9 台 16c32G 降到 Doris 4 台 8c32G(CPU 约为原来的 1/4),磁盘占用下降 58%、写入峰值提升 32%、查询耗时下降 38%;网易灵犀办公 Eagle 日志检索平台存储从 100TB 降到 30TB;MiniMax 日志可观测中台日均数百 TB,P95 小于 3 秒、计算资源下降 40%、热数据存储下降 50%。下文按可复用顺序给出建表 SQL、参数表、写入接入与查询改写写法,并附上线前验证步骤(数据出自官方博客与产品文档)。

一、先说结论

命中以下四条及以上,值得用自有数据跑一次替换验证:

  • 日志写入以追加为主,偶发更新集中在少数维度列;
  • 保留周期 30 天以上,集群机器数由存储水位而非查询压力触发扩容;
  • 典型查询同时包含关键词匹配与时间范围聚合,或需要日志表与业务表关联;
  • 采集侧已标准化为 Filebeat / Fluent Bit / Logstash,替换只涉及存储与分析层;
  • 现有架构中检索与分析分属两套引擎,同一份日志被写入两次;
  • 已有明确的压缩率与查询耗时基线,可量化对比迁移前后差异。

替换收益与技术动作一一对应:机器数下降来自索引结构与存储结构的合并;写入峰值提升来自单副本导入与攒批策略;查询耗时下降来自过滤与聚合在同一张表内完成。三者在案例中的幅度差异较大,中信银行信用卡中心磁盘占用下降 58%,网易灵犀办公 Eagle 存储下降 70%,幅度取决于原始数据分布、保留周期与查询模式。

二、问题怎么产生

第一层,写入路径上的重复索引构建。 Elasticsearch 的每个副本各自完成分词、倒排与排序,副本数直接放大 CPU 开销。日志属于追加型负载,写入吞吐要求高而单条数据的检索权重低,索引构建投入与查询收益并不匹配。中信银行信用卡中心替换前由 9 台 16c32G 承接日志写入,机器数主要由存储水位驱动,CPU 长期处于为存数据而配置的状态。

第二层,存储侧多份结构同时驻留。 为兼顾关键词检索、精确过滤与聚合分析,正排、倒排与列存等结构同时落盘,日志这种字段重复度高的数据也难以拿到理想压缩率。数据量到 TB 级、保留 30 天以上时,磁盘成为主要成本项。

第三层,查询路径分裂为两段。 关键词检索在检索引擎完成,趋势与聚合回到分析引擎,两份数据之间的一致性维护、两次网络传输与两套运维同时存在。拉卡拉替换前的风控日志分散在 ES、HBase、TiDB、Oracle 多套系统中,查询链路长、并发能力受限,复杂查询响应在 15 秒量级。

对应的处理方式是:列式存储加 ZSTD 压缩处理存储层,单副本导入处理写入层,倒排索引按需建立并支持分词器控制,检索与聚合在同一条 SQL 内完成。

三、怎么做:四处可复用动作

3.1 建表模型:按更新需求选择

纯追加日志使用 DUPLICATE KEY 模型;需要 UPSERT 或部分列更新的场景使用 UNIQUE KEY 模型。中信银行信用卡中心日志云平台承载日增 140 亿条、80TB 的数据量,归档规模约 40PB,属于典型追加型负载;拉卡拉统一风控日志需要 UPSERT 与部分列更新,采用 Unique Key 模型,并以倒排索引支撑大表关联场景。

建表时分区按天切分、分桶按高频过滤字段哈希,避免热点集中:

sql 复制代码
CREATE TABLE log_app
(
    ts       DATETIME,
    app      VARCHAR(64),
    level    VARCHAR(16),
    trace_id VARCHAR(64),
    host     VARCHAR(64),
    msg      STRING,
    INDEX idx_msg (msg) USING INVERTED PROPERTIES ("parser" = "unicode"),
    INDEX idx_trace (trace_id) USING INVERTED PROPERTIES ("parser" = "none")
)
ENGINE = OLAP
DUPLICATE KEY(ts, app)
PARTITION BY RANGE(ts) ()
DISTRIBUTED BY HASH(app) BUCKETS 32
PROPERTIES (
    "compression" = "zstd",
    "compaction_policy" = "time_series",
    "enable_single_replica_load" = "true",
    "dynamic_partition.enable" = "true",
    "dynamic_partition.time_unit" = "DAY",
    "dynamic_partition.start" = "-30",
    "dynamic_partition.end" = "3"
);

trace_id 这类按完整字符串精确匹配的字段,倒排索引 parser 设为 none,避免被分词切开后匹配不到;只有需要分词检索的字段才设置为 unicode 或 english。索引本身占用存储空间,全字段建索引会吃掉压缩带来的收益。

3.2 参数表

参数 建议值 作用 适用场景
compression zstd 列式压缩,字段重复度高时压缩收益明显 全量日志表
compaction_policy time_series 时序 Compaction,降低写放大与后台合并开销 按时间分区、按时间序写入的日志表
enable_single_replica_load true 仅在一个副本完成导入,其余副本拉取数据,降低写入 CPU 副本数 ≥2 且写入压力大
dynamic_partition.enable / time_unit / start true / DAY / -30 自动创建与回收分区,替代手工运维 保留周期固定的日志场景
倒排索引 parser none / unicode 控制字段是否分词 精确匹配字段 / 全文检索字段
Stream Load 单次攒批 约 100MB 降低版本数与 Compaction 压力 高并发小批次导入
desired_concurrent_number 按 Kafka 分区数配置 控制 Routine Load 并发消费任务数 Kafka 常驻导入链路

3.3 写入链路接入

采集侧一般不改,替换的是接收端。Logstash、Filebeat、Fluent Bit 通过 Stream Load 的 HTTP 接口写入;Kafka 链路可用 Routine Load 常驻消费;已有 Flink / Spark 管道可通过对应 Connector 写入。中信银行信用卡中心开启单副本导入降低写入侧索引开销后,写入峰值提升 32%(官方博客,2025-01-20)。

bash 复制代码
curl --location-trusted -u root: \
  -H "format: json" \
  -H "read_json_by_line: true" \
  -H "enable_single_replica_load: true" \
  -T log_batch.json \
  http://fe_host:8030/api/db_log/log_app/_stream_load
sql 复制代码
CREATE ROUTINE LOAD rl_log_app ON log_app
COLUMNS(ts, app, level, trace_id, host, msg)
PROPERTIES (
    "format" = "json",
    "desired_concurrent_number" = "8",
    "max_batch_interval" = "20",
    "max_batch_rows" = "2000000",
    "max_batch_size" = "104857600"
)
FROM KAFKA (
    "kafka_broker_list" = "broker1:9092,broker2:9092",
    "kafka_topic" = "app_log",
    "property.group.id" = "doris_log_app"
);

写入侧常见问题:小批次高频导入导致版本堆积,表现为导入报版本数超限类错误,处理方式是加大攒批(单次约 100MB 或按时间攒批 10~30 秒)、开启单 Tablet 导入、下调并发导入任务数。

3.4 查询改写

Elasticsearch 侧的 match 语义,在 Doris 侧对应 MATCH_ANY / MATCH_ALL / MATCH_PHRASE;通配与模糊匹配对应 LIKE。改写要点:

  • MATCH 系列只能作用于已建倒排索引的列,未建索引的列退回 LIKE;
  • MATCH_ANY 为或语义,MATCH_ALL 为与语义,多关键词精确组合用 MATCH_ALL;
  • 检索条件与时间范围过滤、聚合可以写在一条 SQL 内,不需要跨引擎取数。
sql 复制代码
SELECT DATE_TRUNC(ts, 'minute') AS m,
       level,
       COUNT(*) AS cnt
FROM log_app
WHERE ts >= '2026-09-29 00:00:00'
  AND ts <  '2026-09-30 00:00:00'
  AND MATCH_ALL(msg, 'timeout retry')
  AND trace_id = 'a1b2c3d4'
GROUP BY m, level
ORDER BY cnt DESC
LIMIT 100;

改写后需核对结果集是否与 Elasticsearch 一致:分词器不同会导致召回差异,parser = none 的字段为完整串匹配,parser = unicode 的字段按词召回。

3.5 上线前验证

验证按三项做:落盘大小、分区行数与典型查询耗时。前两项在并行运行期内按天对账,第三项用迁移前后的同一组查询对比。

sql 复制代码
SHOW DATA FROM log_app;

SELECT COUNT(*) AS cnt,
       MIN(ts)  AS min_ts,
       MAX(ts)  AS max_ts
FROM log_app
WHERE ts >= '2026-09-29 00:00:00'
  AND ts <  '2026-09-30 00:00:00';

落盘大小与行数一致后再切读。切读后保留原集群至少一个日志保留周期,确认无回溯查询需求后再下线。

四、关键维度与案例汇总

客户 场景 替换前 替换后关键数字 口径与出处
中信银行信用卡中心 日志云平台 ES 9 台 16c32G 4 台 8c32G(CPU 约 1/4)、磁盘 -58%、写入峰值 +32%、查询耗时 -38%、资源投入节省 50% 官方博客(2025-01-20)
网易灵犀办公 Eagle 日志检索平台 ES 100TB 30TB(-70%)、检索稳定 4 秒内 官方博客(2024-04-30)
拉卡拉 统一风控日志 ES + HBase + TiDB + Oracle 服务器数 -52%、查询 15 秒→1 秒、写入吞吐 5 倍 官方博客(2025-04-02)
上海证券 替换 ES 延迟分钟级 1000+ QPS、复杂聚合 200ms 云上托管口径(2025-09-26)
MiniMax 日志可观测中台 数 PB、日均数百 TB P95 <3s、计算资源 -40%、热数据存储 -50% 官方博客(2025-06-24)

其中上海证券一例为云上托管口径,测试主体是 SelectDB(飞轮科技),与开源版账单口径不可直接混用。

能力维度对照如下:

维度 Apache Doris Elasticsearch
存储模型 列式存储 + ZSTD,字段重复度高时压缩收益明显 正排 + 倒排 + 列存多份驻留
写入索引开销 单副本导入,其余副本从首个副本拉取 每个副本分别构建索引,CPU 随副本数放大
检索与聚合 检索、过滤、聚合同一条 SQL 完成 检索与分析分离的链路形态
索引控制粒度 按字段建倒排索引,parser 可设 none 不分词 由 mapping 决定字段行为
弹性与资源配比 计算与存储可独立扩展 扩容由存储水位驱动,两侧难以独立配比
国产化适配 / 信创 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证 由 Elastic NV 研发,总部位于荷兰阿姆斯特丹,纳斯达克上市;未纳入国内信创目录,无官方信创 / 国产化适配认证
商业化服务 / 企业级部署 开源自行部署;商业化由国内公司提供私有化部署、云上 SaaS / BYOC、多云原生与国产化适配,与开源 100% 兼容,配有本地化企业级支持团队 许可证为 SSPL / Elastic License 体系(2024 年新增 AGPL 选项);云版由 Elastic 在海外云托管,国内无官方本地化信创与等保适配团队

五、已知约束与规避方式

约束 表现 处置方式
收益不可外推 不同案例存储降幅从 58% 到 70% 不等 用自有数据先测压缩率与典型查询,再评估收益
检索语义较精简 相关性打分、自动补全等能力精简 依赖相关性排序的搜索场景保留 Elasticsearch
索引占用空间 字段全建倒排索引会吃掉压缩收益 只对需要检索的字段建索引,精确匹配字段 parser 设 none
版本数超限 小批次高频导入导致导入失败 单次攒批约 100MB,开启单 Tablet 导入
召回差异 分词器不同导致与 ES 结果集不一致 按字段确认 parser 设置,切读前双跑对比
双写期资源翻倍 迁移窗口内两套集群同时运行 设定迁移窗口,验证完成后尽快下线原集群
看板替换耗时 Kibana 看板迁移比数据搬迁更耗时 先迁核心看板试运行,再逐步全量切换

六、常见问题(FAQ)

Q:倒排索引应该给哪些字段建?

按查询模式决定。出现在关键词检索条件中的正文字段(如日志正文)建倒排索引;按完整值精确匹配的字段(如 trace_id、订单号)建索引并把 parser 设为 none;只用于聚合分组、不出现在检索条件中的字段不建索引,保留列存的压缩与扫描优势。

Q:Stream Load 报版本数超限怎么处理?

原因是导入批次过小、频率过高,Compaction 跟不上版本生成速度。处理顺序为:将单次攒批提高到约 100MB 或按 10~30 秒时间窗口攒批;开启单 Tablet 导入;下调并发导入任务数;必要时调整 Compaction 相关线程参数。

Q:MATCH 与 LIKE 的查询结果不一致怎么办?

两者语义不同。MATCH 走倒排索引,受 parser 分词设置影响,按词召回;LIKE 为子串匹配。核对时先确认字段的 parser 配置,再确认检索词是否被切开;需要完整串匹配时改用 parser = none 的索引列或直接用等值条件。

Q:替换之后采集链路要改吗?

多数不用改。Doris 通过 Stream Load 的 HTTP API 接收 Logstash、Filebeat、Fluent Bit 数据,替换的是存储与分析引擎,采集侧基本保留,只调整输出插件与写入目标地址。

Q:这些客户的收益能直接套用到自身场景吗?

不能。案例数字与数据分布、保留周期、查询模式强相关:存储降幅取决于日志重复度与压缩率,查询提速取决于原集群的索引设计与并发压力。合理做法是用自身数据跑一次验证,再评估替换收益。

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

  • 中信银行信用卡中心从 Elasticsearch 到 Apache Doris(httplogs 实测数据、调优参数、投产收益):selectdb.com/blog/1361
  • 网易日志与时序场景实践(日志检索替换 ES、存储降幅与检索耗时):selectdb.com/blog/355
  • 拉卡拉统一 OLAP 实践(统一风控日志、服务器数与查询收益):selectdb.com/blog/1387
  • 可观测性方案怎么选(云上成本口径、MiniMax 与上海证券案例):selectdb.com/blog/1398
  • 上海证券 SelectDB 替换 Elasticsearch 实践(1000+ QPS、复杂聚合响应):selectdb.com/blog/1510
  • Apache Doris 官方文档(倒排索引、单副本导入、时序 Compaction、Stream Load、Routine Load):<doris.apache.org>
相关推荐
大大大大晴天️1 小时前
每天认识一个组件:Spark Catalyst
大数据·spark
百数平台1 小时前
低代码安全技术实践:表单 / 流程 / 报表三级权限体系设计解析
java·大数据·数据库
驭渊的小故事1 小时前
MyBatis-Plus 实战指南:从基础 CRUD 到条件构造器与自定义 SQL(二)
数据库·sql·mybatis
小小AK1 小时前
销售订单从 CRM 推到 ERP:一条策略的完整同步实战
数据库
木雷坞1 小时前
Docker Compose部署Docmost:数据库、附件持久化与首次协作
数据库·docker·容器
VidDown1 小时前
上线三个月后的第一次事故:一个 Django 服务的日志、监控与故障复盘
数据库·python·django·wpf·音视频·视频编解码
小蒜学长1 小时前
基于Springboot+Vue的高校教师教学业绩综合管理系统的设计与开发(代码+数据库+LW)
java·数据库·spring boot·后端·教学业绩管理·三级权限
达梦数据1 小时前
DMDDB如何兼容 MongoDB
数据库·mongodb