当前位置: 首页 > news >正文

从 Elastic 到 ClickHouse:日志系统性能与成本优化之路

文章目录

    • 需求背景
    • 需求目的
    • 计划完成时间
    • 阶段
    • 调研内容
      • 日志写入链路
      • 方案设计
        • 表结构设计
          • 落地表(ReplicatedMergeTree)
          • 分布式表
          • Kafka 引擎表
          • 物化视图
        • 保留策略
        • 前端选型
          • 配置ClickHouse连接信息与索引白名单
          • 配置需要切换到ClickHouse的index
      • 常见问题与解决方案
        • 1. `offset out of range`
        • 2. 消费延迟过高
      • 成果展示
      • 实际插入情况
    • 亮点
    • 不足

需求背景

当前系统日志主要存 ElasticSearch,存在以下问题:

  • 查询效率较低,尤其在高并发场景下性能瓶颈明显;
  • 存储成本较高,部分日志存储冗余,压缩效果不佳;
  • 查询维度较弱,难以支持多维分析与快速聚合。

ClickHouse 作为高性能列式 OLAP 引擎,在日志存储和分析方面具备显著优势,能够支持大吞吐量、高压缩比及亚秒级查询延迟。因此,计划将关键日志数据接入 ClickHouse 进行统一分析、降本增效。

需求目的

  • 实现日志写入 ClickHouse,提升查询性能与响应速度;
  • 支持常见的日志检索、聚合分析;
  • 兼容现有日志收集流程;
  • 降本增效;

计划完成时间

2025-07-31

阶段

  1. Clickhouse结合日志存储调研,是否自建表?补充字段如何处理?
  2. 分布式集群搭建
  3. 性能优化
  4. 结合监控数据展示及告警
  5. 前端组件调研使用
  6. 自动清理旧数据

调研内容

日志写入链路

Filebeat / Logstash↓Kafka↓ClickHouse(Kafka 引擎表 → MergeTree 表)
  • Kafka 消费:ClickHouse 原生支持 Kafka 引擎,无需额外消费者;
  • 数据转换:通过 Materialized View 进行字段映射与结构清洗;
  • 落盘存储:使用 MergeTree 表优化查询性能与数据保留策略。

方案设计

表结构设计
落地表(ReplicatedMergeTree)
CREATE TABLE IF NOT EXISTS default.ycloud_log_local
(`message` String,`host` String,`@timestamp` UInt64,`port` Int64,`secondFacility` String,`traceId` String,`logtime` String,`linenum` String,`procedure` String,`peerAddr` String,`level` String,`ck_assembly_extension` String,`orderId` String,`username` String,`spanId` String,`version` String,INDEX timestamp_index `@timestamp` TYPE minmax GRANULARITY 8192
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/ycloud_log_local', '{replica}')
PARTITION BY (toYYYYMMDD(toDateTime(`@timestamp` / 1000, 'Asia/Shanghai')), toHour(toDateTime(`@timestamp` / 1000, 'Asia/Shanghai')))
ORDER BY (intHash64(`@timestamp`))
SAMPLE BY intHash64(`@timestamp`)
TTL toDateTime(`@timestamp` / 1000) + INTERVAL 120 DAY DELETE
SETTINGS in_memory_parts_enable_wal = 0, index_granularity = 8192;
分布式表
CREATE TABLE IF NOT EXISTS default.ycloud_log_all AS default.ycloud_log_local
ENGINE = Distributed('gs_clickhouse_cluster', default, ycloud_log_local, rand());
Kafka 引擎表
CREATE TABLE default.ycloud_log_kafka
(`raw_json` String
)
ENGINE = Kafka
SETTINGSkafka_broker_list = '192.168.100.10:9092,192.168.100.20:9092,192.168.100.30:9092', kafka_topic_list = 'ycloud',  kafka_group_name = 'ycloud_test_group',kafka_format = 'JSONAsString',kafka_num_consumers = 10,   kafka_max_block_size = 1048576;
物化视图
CREATE MATERIALIZED VIEW IF NOT EXISTS default.ycloud_log_mv
TO default.ycloud_log_local
AS
SELECTJSONExtractString(raw_json, 'message')         AS message,JSONExtractString(raw_json, 'host')            AS host,toUnixTimestamp64Milli(parseDateTime64BestEffort(JSONExtractString(raw_json, 'logtime'))) AS `@timestamp`,toInt64OrNull(JSONExtractString(raw_json, 'port'))                 AS port,JSONExtractString(raw_json, 'secondFacility') AS secondFacility,JSONExtractString(raw_json, 'traceId')        AS traceId,JSONExtractString(raw_json, 'logtime')        AS logtime,JSONExtractString(raw_json, 'linenum')        AS linenum,JSONExtractString(raw_json, 'procedure')      AS procedure,JSONExtractString(raw_json, 'peerAddr')       AS peerAddr,JSONExtractString(raw_json, 'level')          AS level,raw_json                                       AS ck_assembly_extension,JSONExtractString(raw_json, 'orderId')           AS  orderId,JSONExtractString(raw_json, 'username')           AS  username,JSONExtractString(raw_json, 'spanId')           AS  spanId,JSONExtractString(raw_json, 'version')           AS  version	
FROM default.ycloud_log_kafka;
保留策略
  • 热数据:120 天内的日志使用主表存储;
  • 清理机制:定期使用 TTL 策略清理过期分区。
前端选型

Ckibana + kibana

踩坑 Ckibana不支持8.0以上版本,官方文档写着支持Ckibana。使用时获取不到正确的时间戳字段。

部署方式采用自定义 Helm Charts,kibana 依赖Ckibana

spring:application:name: ckibana
server:port: 8080
logging:config: classpath:logback-spring.xmlfile:path: logsmetadata-config:hosts: 192.168.100.10:9200headers:Authorization: ApiKey TzQ4N0VaZ0JjQWg3YWgzdw==
配置ClickHouse连接信息与索引白名单

设置ClickHouse连接信息:

curl --location --request POST 'localhost:8080/config/updateCk?url=ckUrl&user=default&pass=default&defaultCkDatabase=ops'
配置需要切换到ClickHouse的index
curl --location --request POST 'localhost:8080/config/updateWhiteIndexList?list=index1,index2'

⚡️: 实际使用 ES + Kibana 方式一致

常见问题与解决方案

1. offset out of range

日志:

offset reset to offset BEGINNING: fetch failed due to requested offset not available on the broker

原因:Kafka 中记录的 offset 已被删除,ClickHouse 自动回退到 earliest;

处理建议:

  • 设置 kafka_auto_offset_reset = 'latest' 避免历史 offset 回退;
  • 定期清理消费组;
  • 设置合理的 Kafka 数据保留时间。
2. 消费延迟过高

原因:Kafka TPS 高时 ClickHouse 消费不及时;主要出现在更添加INDEX时,TOPIC存储周期长,数据量大导致。

方案:

  • 增加消费者副本(表配置 kafka_num_consumers);
  • 将大表进行拆分;
  • 提前清洗复杂字段,避免落地时频繁 JSON 解析。

3.常用操作

toUnixTimestamp64Milli(now64(3)) 用于获取当前时间的 Unix 毫秒级时间戳。

## 添加字段
ALTER TABLE default.gsnormal_log_local 
ADD COLUMN facility String  AFTER level;
## 删除字段
ALTER TABLE default.gsnormal_log_local 
DROP COLUMN port;

成果展示

目标项目标值实际达成值差值分析
查询效率P95 ≤ 3sp95 1 s性能超出预期,ClickHouse 列式存储和分区裁剪发挥了优势,查询明显更快
写入性能QPS ≥ 10 万QPS 实测峰值约 15 万写入性能超额完成,Kafka 消费 + 批量 insert 提升了写入能力
存储成本降低 ≥ 50%实际约降低 60%替换 ELK,去除副本冗余和冷热分层后,存储成本进一步下降

实际插入情况

在这里插入图片描述

亮点

  • 提前规划固定字段(如 traceId、logtime、level 等)与原始 JSON 扩展字段(ck_assembly_extension)分开存储,保留日志灵活性,后期可快速应对字段变动需求,无需频繁修改表结构。
  • 引入 ClickHouse TTL 自动清理策略,保障长期稳定运行。
  • 使用 ReplicatedMergeTree 实现多副本同步,自动 failover 提升可用性,保证日志数据持久可靠。

不足

性能还需进一步加强,对极端写入压力的承载验证不足

http://www.dtcms.com/a/297908.html

相关文章:

  • 【大模型实战】提示工程(Prompt Engineering)
  • 优秀案例:基于python django的智能家居销售数据采集和分析系统设计与实现,使用混合推荐算法和LSTM算法情感分析
  • 九联UNT413AS_晶晨S905L3S芯片_2+8G_安卓9.0_线刷固件包
  • 短剧小程序系统开发:构建影视娱乐生态新格局
  • Spring Boot License 认证系统
  • C#(数据类型)
  • k8s的存储之secerts
  • Python数据可视化利器:Matplotlib全解析
  • 智能制造——解读39页MOM数字化工厂平台解决方案【附全文阅读】
  • Linux网络配置全攻略:IP、路由与双机通信
  • 北京-4年功能测试2年空窗-报培训班学测开-第六十天-准备项目中
  • 图的遍历:深度优先与广度优先
  • SpringBoot学习路径二--Spring Boot自动配置原理深度解析
  • Qt 状态机框架:复杂交互逻辑的处理
  • R 语言绘制六种精美热图:转录组数据可视化实践(基于 pheatmap 包)
  • 从零开始学习Dify-数据库数据可视化(五)
  • java的设计模式及代理模式
  • 负载均衡:提升业务性能的关键技术
  • Zabbix告警系统集成指南:从钉钉机器人到网易邮件的全流程配置
  • pytest-html 优势及与其他插件对比
  • 自动驾驶领域中的Python机器学习
  • VLA:自动驾驶的“新大脑”?
  • npm init vite-app runoob-vue3-test2 ,npm init vue@latest,指令区别
  • C语言第 9 天学习笔记:数组(二维数组与字符数组)
  • Java-Properties类和properties文件详解
  • 同声传译新突破!字节跳动发布 Seed LiveInterpret 2.0
  • 深入探索嵌入式仿真教学:以酒精测试仪实验为例的高效学习实践
  • C++常见面试题之一
  • win11平台上mysql 数据库迁移
  • 【C#补全计划:类和对象(七)—— 重写虚方法】