资讯动态

Opik 自托管环境 ClickHouse 报 Too many parts 导致批量写入 500 怎么排查?

发布时间:2026/9/14 11:27:10 来源:尧图企业网站定制
Opik 自托管环境 ClickHouse 报 Too many parts 导致批量写入 500 怎么排查【免费下载链接】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当你自托管的 Opik 在持续高吞吐写入traces / spans 批量上报时出现这类现象就需要按下面的流程排查调用POST /api/v1/private/spans/batch或/traces/batch的客户端持续收到 HTTP 500ClickHouse 拒绝新 partopik-backend 日志中出现Code: 252 ... (TOO_MANY_PARTS)形如Code: 252. DB::Exception: Too many parts (N) in table opik.spans. Merges are processing significantly slower than inserts: While executing WaitForAsyncInsert. (TOO_MANY_PARTS)此时spans或traces表的活跃 part 数已经超过了 ClickHouse 的parts_to_throw_insert阈值默认3000并且持续不降。如果拖延opik-backend 的 ClickHouse 连接池还会被耗尽ConnectionRequestTimeoutException影响面进一步扩大。这个错误有两种根因完全不同的成因对应的修复手段互不通用所以下一步必须先诊断再决定走哪条修复路径Cause A — 碎片化merge 本身正常且在跑但新 part 产生速度超过了合并速度由高并发下 async-insert 的刷新频率驱动Cause B — 卡死的 merge某个 merge 队列条目卡住常见于Code: 76 ... CANNOT_OPEN_FILE堵死了整个调度器任何 merge 都不再执行part 无法下降。以下排查与修复命令基于 Opik 自托管故障排查文档 的 ClickHouseTOO_MANY_PARTSErrors and Stuck Merges 一节。生产环境 Opik 的 ClickHouse 是复制集群因此命令使用集群级形式单机部署时把clusterAllReplicas(...)包裹去掉直接查system.*表并去掉ON CLUSTER {cluster}子句即可。命令中有两个占位符执行前先确认替换{cluster}你的集群宏名可用SELECT * FROM system.macros查database_name分析库名默认opik由ANALYTICS_DB_DATABASE_NAME设置可用SHOW DATABASES查。第一步连入 ClickHouse 执行诊断查询先连到 ClickHouse 副本执行诊断Kubernetes 部署的示例命令# 连接第一个副本 kubectl exec -it chi-opik-clickhouse-cluster-0-0-0 -- clickhouse-client # 连接第二个副本如果运行了多个副本 kubectl exec -it chi-opik-clickhouse-cluster-0-1-0 -- clickhouse-client依次运行以下四组查询回答part 是不是高且还在涨merge 是不是卡了副本是否健康三个问题-- 每个节点每张表的活跃 part 数数量是否高且持续增长 SELECT hostName() AS host, table, count() AS active_parts FROM clusterAllReplicas({cluster}, system.parts) WHERE active AND database database_name GROUP BY host, table ORDER BY active_parts DESC; -- 是否有卡住的 merge找 num_tries 不断上涨、last_exception 重复出现的队列条目 SELECT hostName() AS host, database, table, type, num_tries, new_part_name, last_exception FROM clusterAllReplicas({cluster}, system.replication_queue) WHERE database database_name ORDER BY num_tries DESC; -- 每个节点实际在跑的 merge 数可与 background_pool_size 对照 SELECT hostName() AS host, count() AS running_merges FROM clusterAllReplicas({cluster}, system.merges) GROUP BY host; -- 副本健康状态用于排除 ZooKeeper 元数据丢失那一类问题 SELECT hostName() AS host, table, is_readonly, replica_is_active, zookeeper_exception FROM clusterAllReplicas({cluster}, system.replicas);如果system.replicas里出现Code: 999 / KEEPER_EXCEPTION / No node说明你遇到的是另一个问题ZooKeeper 元数据丢失SYSTEM RESTORE REPLICA针对的是那个场景不会解开卡死的 merge应转而去查同文档的 ClickHouse Zookeeper Metadata Loss 一节。第二步判定根因 A 还是 B用第一步的结果对照文档给出的判据Cause A碎片化merge 正常且快速完成running_merges健康system.replication_queue中没有num_tries很高且卡住的条目但活跃 part 数持续高于合并能力。Cause B卡死 merge尽管background_pool_size很大running_merges却接近 0replication_queue中有一条num_tries高且不断爬升、last_exception重复的条目——常见为Code: 76 ... CANNOT_OPEN_FILE指向损坏或缺失的源 part 文件。这一条毒条目会堵死调度器无论 CPU、磁盘余量多少part 都无法下降。修复路径 A调宽 async-insert 刷新窗口Cause A 的成因是 Opik 在 ClickHouse连接上固定了 async-insert 参数默认链路为async_insert1、wait_for_async_insert1、async_insert_busy_timeout_min_ms100、async_insert_busy_timeout_max_ms250、async_insert_use_adaptive_busy_timeout1默认值可在 config.yml 的queryParameters中看到。async_insert1时每次服务端 flush 都会产生一个新 part100–250 ms 的短刷新窗口在高并发下会制造大量小 part。有一个关键限制要注意这些 busy-timeout 参数被 Opik 钉死在连接上在 ClickHouse 服务端 profile 或用户设置里调async_insert_busy_timeout_*是无效的——连接上的值优先。必须通过 opik-backend 的环境变量来改ANALYTICS_DB_ASYNC_INSERT_BUSY_TIMEOUT_MAX_MS2000 # 自适应刷新窗口上限ms文档建议范围 1000–3000 ANALYTICS_DB_ASYNC_INSERT_BUSY_TIMEOUT_MIN_MS1000 # 自适应刷新窗口下限ms保持小于 max ANALYTICS_DB_ASYNC_INSERT_MAX_DATA_SIZE52428800 # 触发 flush 的缓冲字节数越大 part 越少这三个变量按设置了才生效的语义工作设置了会覆盖ANALYTICS_DB_QUERY_PARAMETERS链路中对应的值链路里没有则追加不设置则原样保留busy-timeout 回落到默认 100 / 250 msasync_insert_max_data_size走 ClickHouse 服务端/用户 profile 的值。如果要改链路里其他连接参数需要整体重写ANALYTICS_DB_QUERY_PARAMETERS字符串保留所有已有键、只调整需要改的部分。改完后重启 opik-backend让新连接参数生效然后观察两件事各表的活跃 part 数是否开始下降system.asynchronous_inserts的刷新行为并在 1000–3000 ms 区间内微调max_ms。新插入的碎片会明显减少存量积压的 part 仍需要被 merge 追平只要插入速率不再持续压过合并就会降下来。放宽刷新窗口是用少量写入延迟和缓冲内存数据最多晚max_ms才可见换更少的 part。由于 Opik 的写入是同步的wait_for_async_insert1max_ms调大同时会抬高 batch 和 create/update 端点的最坏响应时间请确认客户端的读超时明显大于max_ms——官方 Opik SDK 的读超时已经足够宽裕但自定义或直连 HTTP 的客户端需要自行检查并调大避免在成功写入返回前就超时。修复路径 B解开卡死的 merge按侵入性从低到高执行。第 1 步提阈值和第 2–3 步诊断是无损的第 4 步DETACH可恢复但影响数据第 6 步直接改 ZooKeeper 是最后手段。命令针对诊断中标记出的表执行——把table替换为spans或traces。1. 立即恢复写入可逆、无数据丢失临时调高抛错阈值让你在修复根因期间插入不再被拒绝ALTER TABLE database_name.table ON CLUSTER {cluster} MODIFY SETTING parts_to_throw_insert 20000, parts_to_delay_insert 20000;这是安全的临时止血手段——不删除任何数据——积压排空后要改回默认值。如果表是 Distributed 部署要操作底层的每分片 ReplacingMergeTree 表而不是 Distributed 代理表。2. 确认副本健康is_readonly 0、replica_is_active 1、zookeeper_exception 。若出现 KeeperNo node错误改走 ZooKeeper 元数据丢失的排查路径。3. 定位出问题的 merge 及其损坏的源 part从system.replication_queue.last_exception中的CANNOT_OPEN_FILE消息里拿到肇事 part 目录名。4. 尝试恢复损坏的源 part如果某个 part 在其他副本上仍完好DETACH掉本地损坏副本永远不要DROP——ClickHouse 会从健康副本重新拉取好副本被阻塞的 merge 就能完成。Detached 的 part 会保留在该表的detached/目录下ALTER TABLE database_name.table DETACH PART all_1_100_5; -- 对异常信息中列出的每个损坏 part 重复执行注意这是有数据影响的专家操作建议有 ClickHouse 专家在场。对ReplicatedMergeTree队列中的 merge 条目按名称引用源 partDETACH本身不会移除该队列条目——只有当 part 在其他副本完好、可以被重新拉取时才有用。如果该 part 在所有副本上都损坏没有东西可拉条目会持续重试必须走第 6 步清除且移除 part 也会丢它的行——对观测数据来说是有界的小窗口。5. 复查队列卡住的条目消失、merge 恢复执行后积压会自行排空。对某个节点执行SYSTEM RESTART REPLICA database_name.table可以帮助它重新读取队列。6. 最后手段——从 ZooKeeper 删除卡死的队列条目当重拉/DETACH都无法清除时直接删除毒条目是可靠的修复方式但危险只在第 4–5 步失败后、并尽量有 ClickHouse 专家在场时执行。在每个副本路径下删除对应卡死的queue-XXXXXXXXXX节点然后重启副本/clickhouse/tables/shard/database_name/table/replicas/replica/queue/queue-XXXXXXXXXX直接编辑 ZooKeeper 有可能在删错节点时破坏复制——只删精确卡住的那条条目、覆盖所有副本并且只要可能就走DETACH PART路径。7. 验证恢复并回退观察活跃 part 数回落然后把parts_to_throw_insert/parts_to_delay_insert改回默认值。另有一条明确的负面清单——这些操作不能解开卡死的 merge单独的SYSTEM RESTART REPLICA只重置num_tries并重试同一条目、SYSTEM STOP/START MERGES条目在暂停期间依然存在、KILL MUTATIONmerge 不是 mutation。预防与监控文档给出的预防建议高吞吐写入扩容前先把async_insert_busy_timeout_max_ms调大Cause A 一节并监控 part 数ClickHouse 大版本升级期间复制表滚动升级时副本可能短暂变只读导致 part 文件不一致、排入后来失败的 merge。升级期间应暂停或限流写入并在把写入拉回之前确认所有副本健康system.replicas且system.replication_queue干净监控告警对集群级每表活跃 part 数、以及system.replication_queue中num_tries持续上涨的条目设告警让卡死 merge 在演变成TOO_MANY_PARTS之前被发现。更多场景集群宏缺失、clickhouse-traces-topology健康检查失败、ZooKeeper 元数据丢失、Liquibase changelog 丢失等的完整排查方法见 troubleshooting.mdx。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价