从启动崩溃到 UPDATE 阻塞:Webfunny 埋点 CK 容器运维完整排错实战

一只会飞的鱼儿 16小时前 ⋅ 6 阅读
ad

前言

使用 Docker 官方clickhouse-server:24.3.2.23承载 Webfunny 埋点 / APM 大数据业务,接连踩中 3 类生产级故障:容器启动直接退出、Node 后端镜像版本兼容报错、UPDATE 更新长时间不生效。本文完整记录全套故障根因、可直接复制落地的修复步骤,覆盖 Docker 镜像、ZK 集群、MergeTree 线程池、Mutation 异步机制全维度优化,运维 Webfunny 埋点、ClickHouse 大数据集群可直接复用。

一、前置业务环境说明

  1. ClickHouse 部署:Docker Compose 容器化,镜像clickhouse/clickhouse-server:24.3.2.23,ReplicatedMergeTree 复制引擎,依赖 3 节点 ZooKeeper 集群;
  2. 业务场景:Webfunny 前端埋点、APM 性能监控、报表卡片管理,大量ALTER TABLE UPDATE修改报表配置;
  3. 配套后端:Node14 镜像打包 Webfunny 监控服务,PM2 托管进程。

二、故障 2:ClickHouse 容器启动退出码 36,服务起不来

阶段 1:第一重致命配置报错

日志核心错误:

number_of_free_entries_in_pool_to_execute_mutation(20) > background_pool_size * background_merges_mutations_concurrency_ratio(8)
BAD_ARGUMENTS, Code:36

根因

ClickHouse MergeTree 强制参数校验:用于执行 UPDATE/Mutation 的预留空闲线程数,不能超过后台合并池总可用 mutation 线程上限;配置数值冲突直接触发进程退出。

修复:补充 merge_tree 参数

修改config.xml<merge_tree>节点,新增参数限制数值≤8:

<merge_tree>
    <max_suspicious_broken_parts>5</max_suspicious_broken_parts>
    <parts_to_delay_insert>300</parts_to_delay_insert>
    <parts_to_throw_insert>600</parts_to_throw_insert>
    <max_parts_in_total>100000</max_parts_in_total>
    <number_of_free_entries_in_pool_to_execute_mutation>5</number_of_free_entries_in_pool_to_execute_mutation>
</merge_tree>

阶段 2:新增第二重同类型校验报错

修改后再次启动,抛出全新同类型异常:

number_of_free_entries_in_pool_to_execute_optimize_entire_partition(25) > 8

根因

CK24.3 版本新增全局 optimize 整分区合并校验,同样受线程池上限约束,两个参数必须同时配置。

完整修复 merge_tree 配置(最终可用)

<merge_tree>
    <max_suspicious_broken_parts>5</max_suspicious_broken_parts>
    <parts_to_delay_insert>300</parts_to_delay_insert>
    <parts_to_throw_insert>600</parts_to_throw_insert>
    <max_parts_in_total>100000</max_parts_in_total>
    <!-- Mutation UPDATE 预留线程限制 -->
    <number_of_free_entries_in_pool_to_execute_mutation>5</number_of_free_entries_in_pool_to_execute_mutation>
    <!-- OPTIMIZE整分区合并预留线程限制 -->
    <number_of_free_entries_in_pool_to_execute_optimize_entire_partition>5</number_of_free_entries_in_pool_to_execute_optimize_entire_partition>
</merge_tree>

阶段 3:ZK 集群域名解析失败致命报错

日志报错:

Cannot resolve host (zk1), Host not found
DB::NetException: Not found address of host: zk1

根因

容器内部 DNS 无法识别宿主机 hostname zk1/zk2,ReplicatedMergeTree 启动阶段加载集群元数据失败,进程崩溃。

两种修复方案

  1. 推荐方案:ZK 节点直接填写内网 IP,无 DNS 依赖
<zookeeper>
    <node>
        <host>111.11.17.25</host>
        <port>2181</port>
    </node>
    <node>
        <host>112.11.17.24</host>
        <port>2181</port>
    </node>
    <node>
        <host>112.19.17.14</host>
        <port>2181</port>
    </node>
</zookeeper>

 2.兼容方案:docker-compose 添加 hosts 映射,保留域名写法

extra_hosts:
  - "zk1:12.19.17.125"
  - "zk2:12.19.17.124"

阶段 4:无关警告(无需处理,仅日志提示)

  1. IPv6 监听失败警告:宿主机未开启 IPv6,可通过<listen_host>0.0.0.0</listen_host>关闭 IPv6 监听消除;
  2. Linux transparent hugepages 透明大页警告:仅性能提示,不影响服务启动。

验证容器启动成功标准

  1. 执行docker ps,容器 STATUS 为Up X minutes,不再显示 Exited;
  2. 日志输出Application: Ready for connections.
  3. clickhouse-client本地登录可正常执行 SQL。

三、故障 3:UPDATE 更新操作不生效,Mutation 长期阻塞

故障现象

Webfunny 后台修改报表卡片BuryPointCard执行 UPDATE,页面刷新数据无变化; 日志显示后台合并池全部被webfunny_apm_db_cluster埋点表的 Merge 任务占满,Mutation 排队等待空闲线程。

核心原理

ClickHouse ALTER TABLE UPDATE属于异步 Mutation 任务,与分区合并、OPTIMIZE 共用同一套background_pool_size后台线程池;APM 埋点表数据量大、Part 数量多,持续占用全部合并线程,报表更新任务无法执行。

四层优化方案(由应急到根治)

1. 实时监控线程池与堆积任务

-- 查询未完成的更新任务
SELECT database, table, mutation_id, command, create_time, is_done FROM system.mutations WHERE is_done = 0;

-- 查看各表当前合并占用线程
SELECT table, count() AS merge_count FROM system.merges GROUP BY table ORDER BY merge_count DESC;

-- 后台线程池负载指标
SELECT name, value FROM system.metrics WHERE name LIKE '%background%pool%';

2. 应急清理卡死 Mutation

-- 清空指定表所有未执行更新任务
KILL MUTATION WHERE database = 'webfunny_cloud_db' AND table = 'BuryPointCard';

3. 扩容全局后台合并线程池(推荐长期优化)

修改 config.xml 全局参数,放大线程池与 Mutation 并发比例,重启容器生效:

<!-- 全局后台合并总线程,默认4,扩容至24 -->
<background_pool_size>24</background_pool_size>
<!-- 可用于mutation的线程比例,默认2,提升至3 -->
<background_merges_mutations_concurrency_ratio>3</background_merges_mutations_concurrency_ratio>

扩容后计算上限:24 × 3 =72,远大于 5,无配置冲突,同时大幅提升 Mutation 并发能力。

4. 表级隔离优化,报表业务优先抢占线程

单独给报表卡片表调高合并并发,不受 APM 大表阻塞:

ALTER TABLE BuryPointCard MODIFY SETTING
number_of_free_entries_in_pool_to_execute_mutation = 5,
max_background_merges = 10;

5. 业务源头减负(Webfunny 埋点专属)

  1. 给 APM 埋点表配置 TTL 自动清理过期数据,减少 Part 堆积:
ALTER TABLE webfunny_apm_db.* MODIFY TTL event_time + INTERVAL 30 DAY DELETE;
  1. 低峰期定时执行 OPTIMIZE,避免白天业务高峰大量合并抢占线程;
  2. 后台报表修改逻辑批量 UPDATE,杜绝单条循环高频 Mutation。

四、完整运维避坑总结

  1. Docker 容器化 ClickHouse,配置挂载目录权限必须为 101:101,否则会出现读写崩溃;
  2. MergeTree 线程池两组 mutation/optimize 预留参数必须同时配置,漏一个直接启动退出;
  3. ZK 集群优先使用 IP 地址,规避容器 DNS 域名解析失败问题;
  4. Node 镜像版本必须匹配依赖包 ES 语法要求,生产推荐 node:18-lts;
  5. Mutation 异步机制是 CK 原生特性,大埋点业务必须扩容后台合并池,否则报表更新长期延迟;
  6. 配套 clickhouse-backup 增量备份方案,应对 Part 损坏、磁盘满等数据风险。

五、文末福利

本文所有 Dockerfile、ClickHouse config.xml、运维监控 SQL、微信告警备份脚本均可直接复制落地,适配 Webfunny 全链路埋点监控生产环境,覆盖容器部署、集群运维、数据备份全链路需求。


Webfunny全链路监控埋点平台是一站式前端监控 + 用户行为埋点 + 大数据分析平台,天然适配点位细查、用户行为回溯、批量导出等场景:

一体化架构:监控 + 埋点同一套 SDK,数据互通无壁垒
私有化部署:数据完全本地化,满足企业合规要求
高吞吐支撑:基于 ClickHouse 构建,亿级日志秒级查询
全端覆盖:H5 / 小程序 / APP / 鸿蒙全覆盖,统一导出口径
可定制强:支持接口扩展、分布式锁、限流降级等企业级能力

关于Webfunny

Webfunny专注于前端监控系统,前端埋点系统的研发。 致力于帮助开发者快速定位问题,帮助企业用数据驱动业务,实现业务数据的快速增长。支持H5/Web/PC前端、微信小程序、支付宝小程序、UniApp和Taro等跨平台框架。实时监控前端网页、前端数据分析、错误统计分析监控和BUG预警,第一时间报警,快速修复BUG!支持私有化部署,Docker容器化部署,可支持千万级PV的日活量!

  点赞 0   收藏 0
  • 一只会飞的鱼儿
    共发布86篇文章 获得10个收藏
全部评论: 0