前几篇我们都在"用" SkyWalking:埋点、关联、告警。但当你真把大模型链路全量接进生产,第一个被冲垮的往往不是 Agent,而是 OAP 背后的存储。大模型 Trace 有几个特点:Span 多(三层 + 流式)、Tag 和日志体量大、写入峰值高(并发问答)。选错存储,OAP 会出现写入堆积、查询超时,最终监控自己先挂了。

SkyWalking 通过 `storage.selector` 支持多种后端,官方主推 Elasticsearch,也支持 H2(单机演示)、MySQL、PostgreSQL、BanyanDB 等。本篇对比 H2 / MySQL / ES 三类最常用的后端,给出配置实战、性能数据、调优要点,帮你为大模型场景选对存储。

  1. SkyWalking 后端的存储角色
  2. 三种存储后端概览:H2 / MySQL / ES
  3. 部署配置实战(三种)
  4. 性能对比与压测数据
  5. ES 调优实战
  6. 存储容量与 TTL 管理
  7. 最佳实践与踩坑

1. SkyWalking 后端的存储角色

OAP 是无状态计算节点,所有原始数据(Trace、指标、拓扑、日志)都落在外接存储。存储承担三件事:

  • 写入:探针上报的 Span / 指标经 OAP 聚合后批量写库,峰值由写入吞吐决定。
  • 查询:UI 的"追踪""拓扑""指标"查询,由随机读性能决定。
  • 保留:历史数据按 TTL 滚动删除,由存储的删除效率与容量决定。

大模型场景对存储的压力集中在写入(流式 Span 高频)和容量(日志 + Tag 多)。因此选型的核心指标是:写入吞吐、单条查询延迟、水平扩展能力、运维成本。

2. 三种存储后端概览:H2 / MySQL / ES

**H2**:内嵌文件数据库,零依赖,OAP 默认。优点是开箱即用,适合本地调试和演示。缺点是完全不支持水平扩展,写入并发一高就锁表,且重启有数据损坏风险。生产禁用。

**MySQL**:关系型,团队熟悉、运维简单。优点是不用引入新组件,已有 DBA 体系。缺点是 SkyWalking 的时序模型(每秒上万条 Span)对 MySQL 极不友好:单表行数爆炸、二级索引维护重、批量插入和范围删除都慢。仅适合中小规模(日 Trace 量百万级以下)。

**Elasticsearch**:分布式搜索引擎,SkyWalking 官方推荐生产后端。优点是写入吞吐极高(LSM + 批量)、水平扩展好、按时间建索引天然适配 TTL 滚动。缺点是需要独立维护 ES 集群,内存占用大,查询需要懂 DSL。大模型大规模链路首选。

简单对比:

维度

H2

MySQL

Elasticsearch

---

---

---

---

部署复杂度

极低

中高

写入吞吐

水平扩展

不支持

弱(分库麻烦)

强(分片)

查询延迟

低(量小)

低(量大也稳)

适合规模

演示

百万 Trace/日

千万级+/日

运维成本

几乎无

中高

3. 部署配置实战(三种)

所有存储通过 `config/application.yml` 的 `storage.selector` 切换。下面分别给出配置片段。

H2(默认,仅演示):

storage:
  selector: ${SW_STORAGE:h2}
  h2:
    driver: org.h2.jdbcx.JdbcDataSource
    url: jdbc:h2:mem:skywalking-oap-db
    user: sa
    maxPoolSize: 10

 

MySQL(需先建库并执行 `db-scripts/mysql.sql`):

storage:
  selector: ${SW_STORAGE:mysql}
  mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://mysql:3306/sw?rewriteBatchedStatements=true"}
      dataSource.user: ${SW_DATASOURCE_USER:root}
      dataSource.password: ${SW_DATASOURCE_PASSWORD:root}
    maxPoolSize: 50

 

注意 `rewriteBatchedStatements=true` 很关键,它让 MySQL 把批量插入合并,写入性能可提升数倍。

Elasticsearch(推荐生产):

storage:
  selector: ${SW_STORAGE:elasticsearch}
  elasticsearch:
    clusterNodes: ${SW_ES_CLUSTER_NODES:es:9200}
    protocol: ${SW_ES_PROTOCOL:http}
    user: ${SW_ES_USER:""}
    password: ${SW_ES_PASSWORD:""}
    indexShardsNumber: ${SW_ES_INDEX_SHARDS_NUMBER:3}
    indexReplicasNumber: ${SW_ES_INDEX_REPLICAS_NUMBER:1}
    # 大模型场景建议调大批量写入
    bulkActions: ${SW_ES_BULK_ACTIONS:2000}
    bulkSize: ${SW_ES_BULK_SIZE:20}
    flushInterval: ${SW_ES_FLUSH_INTERVAL:10}

 

`bulkActions` / `bulkSize` / `flushInterval` 控制 OAP 向 ES 批量写入的节奏,是大模型高写入场景的首要调优点。

4. 性能对比与压测数据

以下为同构压测(单 OAP、模拟大模型流式 Trace,每条 Trace 含 4 个 Span + 1 条日志)的近似参考值,实际取决于机器规格:

后端

写入峰值 (Span/s)

P99 查询延迟

日留存上限(单节点)

备注

---

---

---

---

---

H2

~800

随量飙升

数十万

锁表明显

MySQL

~6000

500ms~2s

百万级

依赖批量参数

ES(3 节点)

~50000

200ms 内

千万级

线性扩展

结论很清晰:H2 在几百 QPS 就到顶;MySQL 到几千写入就开始出现查询变慢;ES 在三节点下可轻松扛住大模型高峰(单接口数千并发问答)。若你们日 Trace 量级在千万以上,或要保留日志做关联,ES 是几乎唯一选择。

一个常被忽略的点:查询延迟随数据量增长曲线。H2/MySQL 是"数据越多越慢"的线性退化;ES 因为按天分索引 + 时间范围查询,数据量翻倍查询延迟几乎不变,这对长期可观测性至关重要。

5. ES 调优实战

针对大模型高写入,ES 侧有几个直接见效的调优。

第一,分片数。`indexShardsNumber` 默认 1~2,大模型写入建议 3~5(按数据节点数 × 1.5 估算)。分片太少写入单点瓶颈;太多则元数据开销大、查询扇出多。

第二,批量写入。上面 `bulkActions=2000, bulkSize=20MB, flushInterval=10s` 表示累积 2000 条或 20MB 或 10 秒任一条件满足即刷盘,大幅降低 ES 写入压力。

第三,副本与写入分离。写入高峰可临时把 `indexReplicasNumber` 设为 0,写入完成后再动态调回 1,避免写入时同步副本拖累。命令:

curl -X PUT "es:9200/sw_segment-*/_settings" -H 'Content-Type: application/json' \
  -d '{"index":{"number_of_replicas":0}}'

 

第四,JVM 与堆。ES 堆建议不超过 31GB(避免压缩指针失效),数据节点堆外留足。OAP 侧也要给足堆(`-Xms4g -Xmx4g` 起步),否则批量缓冲撑爆。

第五,冷热架构。大模型 Trace 查询大多只看最近 7 天。用 ES ILM(索引生命周期管理)把热索引放 SSD 节点、冷索引迁移到普通节点,既保性能又省成本。

6. 存储容量与 TTL 管理

大模型链路数据膨胀快,必须靠 TTL 滚动清理,否则存储被撑满后 OAP 写入失败、监控全盲。

ES 的 TTL 在 `application.yml` 用 `recordDataTTL` 和各类留存天数控制:

storage:
  elasticsearch:
    # 各类数据保留天数
    metricsDataTTL: ${SW_ES_METRICS_TTL:7}        # 指标保留 7 天
    recordDataTTL: ${SW_ES_RECORD_TTL:3}          # Trace/日志保留 3 天
    # 是否启用按天索引(强烈建议)
    dayStep: ${SW_ES_DAY_STEP:1}

 

`dayStep` 控制几天建一个索引,大模型高量场景可设为 1(每天一索引),让删除就是"删整个索引",比按文档逐条删高效得多。

MySQL/H2 没有原生 TTL,SkyWalking 靠定时任务按 `ttl` 删行,量大时删除会锁表、拖慢写入,这也是它们不适合大规模的另一原因。

容量预估公式(粗略):单 Trace 平均 4 Span + 1 日志 ≈ 8KB;若日 2000 万 Trace,则日增约 160GB,保留 3 天需 ~500GB 可用空间(含副本翻倍则 1TB)。务必留 30% 余量,避免写满。

7. 最佳实践与踩坑

第一,生产别用 H2,哪怕"先跑起来"。H2 内存模式重启即丢,文件模式并发写入会锁,事故复盘时你最需要的恰恰是全量历史 Trace,而它没了。演示可以,生产必须 ES。

第二,MySQL 务必开 `rewriteBatchedStatements`。不开的话 SkyWalking 的批量插入退化成逐条 INSERT,写入直接掉一个数量级,OAP 后台疯狂报超时。

第三,ES 分片数提前规划。后期改分片要重建索引、重灌数据,成本极高。按"未来 6 个月峰值"预留,而不是当前量。

第四,监控你的监控。OAP 和 ES 自己也要被监控(ES 的 heap、写入队列、磁盘使用率)。曾经有团队 SkyWalking 静默挂了一周,才发现是 ES 磁盘写满、索引变只读,那一周的大模型事故全无链路可查。

第五,TTL 与合规平衡。金融、医疗类大模型日志可能要求留存更久,但全量 Trace 留 30 天成本惊人。建议:指标留久(趋势分析),Trace/日志按需缩短,敏感内容脱敏后再存。

第六,升级注意存储兼容。SkyWalking 大版本升级常改 ES 索引 mapping,直接连旧集群可能报错。升级前要么新建存储、要么执行官方提供的 `index-name` 兼容脚本,并备份。

选对存储,SkyWalking 才能扛住大模型的高写入、大容量、长周期。一句话建议:演示用 H2,中小用 MySQL(开批量),生产大规模一律 ES + TTL + 冷热分层。

更多推荐