FEATURED · 精选文章

当追踪记录突破每日 4000 万条:Opik 写入、存储与查询的调优路径

发布时间 / 2026/9/6 21:45:44
来源 / 创域科博编辑部
栏目 / 资讯中心
当追踪记录突破每日 4000 万条:Opik 写入、存储与查询的调优路径 当追踪记录突破每日 4000 万条Opik 写入、存储与查询的调优路径【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llmOpik 是面向 LLM 应用的开源可观测性与评估平台核心能力是追踪、评估与生产监控。当追踪记录量涨到每日数千万条性能瓶颈会沿数据链路逐层显形写入先扛不住存储和索引跟不上查询变慢告警随之变多。下面按写入、存储索引、查询分析、监控生命周期四层逐层说清瓶颈在哪、对应怎么解。 写入层批量接口先扛住峰值写入层最大的风险不是吞吐不够而是把在线评分、线程更新这些重活压在写路径上导致单条写入的延迟被放大。Opik 的解法是把写路径做薄把重活挪到事件之后异步执行。批量接口POST /traces/batch一次收 1 到 1000 条 trace先按idlast_updated_at去重再用一条批量 SQL 落 ClickHouse最后才发TracesCreated事件。整条链路用 Project Reactor 做非阻塞处理落库走 ClickHouse 的async_insert配合wait_for_async_insert和async_insert_deduplicate把逐条插入变成攒批异步刷盘。重活全部挂到事件总线上线程状态更新、项目元数据、BI 上报各走各的监听器在线评分由OnlineScoringSampler按规则里的sampling_rate0–1采样后丢进 Redis Stream评分在流里慢慢做不占写路径。限流是写入层的背压阀workspace维度默认 5000 事件/60 秒、user维度 10000 事件/60 秒超限直接挡在门外避免某个项目突发流量把共享后端打挂。写路径上还有一个容易忽略的点projects.last_updated_trace_at这种每条 trace 都要碰的行Opik 用 Redis 缓冲 定时默认 30 秒批量刷回 MySQL而不是每条同步写从而避开projects行的锁竞争。️ 存储与索引分区、排序键和跳过索引决定上限存储层的瓶颈在于 trace 是宽行、写入不可逆地累积一旦分区和排序键没对齐热查询任何全表扫描都会拖垮整库。Opik 的traces_local_v2布局就是围绕放得下、查得快设计的。分区与排序键表用ReplicatedReplacingMergeTree按toMonday(id_at)周分区id_at由每行的 UUIDv7id派生——同一行无论 upsert 多少次都落在同一周分区时间范围查询可以直接跳分区。排序键定为(workspace_id, project_id, id)恰好对齐最高频的两类查询按 workspace project 过滤、按 id 点查。id留在键里不是白占内存而是让点查能做 granule 级裁剪键再短一点省下的内存索引很小换来的却是实打实的点查开销。跳过索引与 granule 调优热字段上挂了 minmax 索引id、id_at、created_at、last_updated_at、bloom filter 索引id、thread_id和 set 索引source、environment。id同时挂 minmax 和 bloom 两种minmax 服务id x AND id y这类范围判断bloom 服务id x/id IN (...)这类精确匹配二者互不替代。granule 调成index_granularity 8192行、index_granularity_bytes ≈ 40 MiB目的是让宽行能把 granule 填满到接近 8192 行跳过索引的裁剪才真正生效。编码与物化列时间列用Delta ZSTD(1)长度计数列用T64 ZSTD(1)input/output/metadata这类大文本用ZSTD(3)其余走ZSTD(1)基线。end_time、ttft、duration改为非空缺失值用纪元 / NaN 哨兵顶替直接省掉热读路径上的 null 掩码开销。duration、input_length、truncated_output、output_keys等都做成MATERIALIZED读的时候不再重算。表刻意不建SAMPLE BY——采样需要把哈希列塞进排序键会破坏 id/时间排序这一主访问路径而 Opik 的分析是按 workspace/project 精确查的采样换不回这点成本。 查询分析点查裁剪与只读隔离查询层的瓶颈是一条没边界的大查询能拖垮整个库以及分析查询与在线点查抢资源。Opik 的思路是让点查尽量走裁剪把重的分析查询隔离到受限账号。点查命中(workspace_id, project_id, id)排序键后按 granule 裁剪配合use_skip_indexes_if_final1和do_not_merge_across_partitions_select_final1避免无谓地跨分区分片合并。Distributed 拓扑下再开optimize_skip_unused_shards1让查询只路由到真正有数据的分片。分析侧单独建了一个只读的 free-form SQL 账号Agent Insights 用带受限 profile 和行级策略max_execution_time上限 180 秒、socket 超时设 200 秒让服务端先掐断长查询而不是让客户端等满超时。读接口同样限流getTraces/searchTraces默认每 workspace 30 次/60 秒单条查询体上限 100 MB。这套组合保证一个跑偏的聚合不会把点查的 p99 一起拖上去。 监控告警与生命周期TTL、冷热分层和健康检查长期运行最怕的不是某次慢而是数据无界增长 删除残留 配置悄悄跑偏三者叠加后性能是缓慢失血的。这一层的任务是把增长和漂移都变成可观测、可自动收敛的事。TTL 与冷热分层冷数据按is_deleted走 ReplacingMergeTree 的删除元列用墓碑行 upsert 后在后台合并时自然消掉不占用在线查询路径。配合 TTL 和分层存储策略冷数据下沉到cold_s3对象存储盘热数据留在本地、冷数据出账存储曲线才能长期可控。健康检查与基准测试健康检查里专门有clickhouse-traces-topology校验 Distributed 包装与traces_local拓扑一致不一致就摘出轮转和clickhouse-cold-storage-disk冷盘不可达就降级。写入侧还有 UUIDv7 校验可开关、可先只审计计数opik.ingestion.uuid_v7.rejected不拦截让脏 id 先暴露出来。回归基线靠tests_load的负载套件10 万 trace×1 span、25 万 span、以及约 1 GB 的重载荷场景每周定时跑一遍性能退化在进生产前就能被抓住。 落地顺序先做什么怎么验证效果调优按投入产出从高到低排先验证再扩量先把写路径做薄确认 SDK 侧 flush 合并成批单批 ≤1000、后端async_insert已开在线评分走 Redis Stream 采样、不占写路径。核对存储 DDL用system.tables确认线上是分区 排序键(workspace_id, project_id, id) 跳过索引齐备的版本granule 是否按 8192 行 / ~40 MiB 配置。抓慢查询对最热的 workspace project 点查和列表查做查询剖析确认走主键 granule 裁剪和跳过索引而不是全分区扫描。接监控与生命周期开 TTL 冷热分层挂拓扑 / 冷盘健康检查跑一轮tests_load基线留档。设分级告警写入排队、查询 p99、存储增长各设阈值按严重度触发不同动作。优化不是一次性交付写入量每上一个量级就要沿这条链路重新测一遍基线、调一次参数。参考批量写入流程 · traces 表结构迁移手册 · traces_local_v2 建表 DDL · 后端配置【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻