万亿级日志数据的采集、清洗与存储:从Filebeat到ClickHouse的全链路实践
万亿级日志数据的采集、清洗与存储从Filebeat到ClickHouse的全链路实践一、每秒百万行日志涌入旧架构在第三个小时就崩溃了当业务日志量从每天的 500GB 增长到 10TB 时基于 Elasticsearch Logstash KibanaELK的日志平台开始出现数据断层——日志采集延迟从 5 秒飙升到 30 分钟ES 节点频繁 OOMKibana 打开一个 Dashboard 需要 2 分钟。分析 ELK 架构的瓶颈后发现Logstash 的 JVM 内存模型在大量并发写入时存在 GC 停顿、ES 的倒排索引在每个字段都建立索引导致写入放大 5-10 倍、Kibana 的聚合查询在 TB 级别数据上近乎不可用。每个组件都不是不好只是它们面对的不是千万级而是万亿级数据。新的架构选型是 Filebeat Kafka ClickHouse Grafana——用 ClickHouse 的列式存储和向量化执行引擎替代 ES 的倒排索引用 Filebeat 的轻量级采集替代 Logstash 的重量级处理用 Kafka 做流量削峰。本文将详细记录这三步改造的完整过程。二、全链路数据流架构设计flowchart LR subgraph Production[业务服务器集群] S1[App Server 1br/Filebeat] S2[App Server 2br/Filebeat] S3[App Server Nbr/Filebeat] end S1 -- K1 S2 -- K2 S3 -- K3 subgraph Kafka[Kafka 集群 (缓冲层)] K1[Broker 1br/Partition 0-2] K2[Broker 2br/Partition 3-5] K3[Broker 3br/Partition 6-8] end K1 -- C1 K2 -- C2 K3 -- C3 subgraph Consumer[消费与写入] C1[ClickHouse Writer 1] C2[ClickHouse Writer 2] C3[ClickHouse Writer 3] end C1 -- CH1 C2 -- CH2 C3 -- CH3 subgraph ClickHouse[ClickHouse 集群] CH1[Node 1] CH2[Node 2] CH3[Node 3] end CH1 -- G CH2 -- G CH3 -- G G[Grafana Dashboard]关键设计决策Filebeat 替代 LogstashFilebeat 用 Go 编写内存占用仅 30MB而 Logstash 的 JVM 占用超过 1GB。在 500 台服务器上部署这就是 500GB vs 15GB 的内存差异。Kafka 作为缓冲层当 ClickHouse 写入遇到背压如正在做 Part Merge时Kafka 可以缓存数小时的数据。没有这个缓冲层Filebeat 会因为下游不可用而丢弃数据。ClickHouse 替代 ES用 MergeTree 引擎 分区 排序键替代倒排索引存储空间减少 80%查询性能提升 5-10 倍。三、全链路代码实现3.1 Filebeat 配置# filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/app/*.log - /var/log/nginx/access.log # 多行日志合并 (Java 异常堆栈) multiline.pattern: ^\d{4}-\d{2}-\d{2} multiline.negate: true multiline.match: after # 字段预处理 fields: service: order-service environment: production datacenter: shanghai fields_under_root: false # 解析 JSON 格式日志 json.keys_under_root: true json.add_error_key: true json.overwrite_keys: true # 输出到 Kafka output.kafka: hosts: [kafka1:9092, kafka2:9092, kafka3:9092] topic: app-logs partition.round_robin: reachable_only: true required_acks: 1 compression: lz4 max_message_bytes: 1048576 # 日志记录与监控 logging.level: info logging.to_files: true logging.files: path: /var/log/filebeat name: filebeat.log keepfiles: 73.2 Kafka → ClickHouse 消费写入#!/usr/bin/env python3 Kafka 消费者消费日志并批量写入 ClickHouse from kafka import KafkaConsumer from clickhouse_driver import Client import json import time from typing import List, Dict from datetime import datetime import logging logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class LogWriter: 日志写入 ClickHouse 的消费者 BATCH_SIZE 100000 # 每批最多 10 万条 FLUSH_INTERVAL 5 # 每 5 秒刷一次 MAX_RETRIES 3 def __init__(self, kafka_brokers: List[str], ch_host: str): self.consumer KafkaConsumer( app-logs, bootstrap_serverskafka_brokers, group_idch-log-writer, auto_offset_resetlatest, enable_auto_commitFalse, max_poll_records50000, fetch_max_bytes50 * 1024 * 1024, value_deserializerlambda m: json.loads(m.decode(utf-8)) ) self.ch Client( hostch_host, port9000, databaselogs, settings{ max_partitions_per_insert_block: 100, async_insert: 1, wait_for_async_insert: 0 } ) self.buffer [] self.last_flush time.time() def run(self): 主消费循环 try: for msg in self.consumer: self.buffer.append(msg.value) # 达到批量大小或时间间隔时写入 if (len(self.buffer) self.BATCH_SIZE or time.time() - self.last_flush self.FLUSH_INTERVAL): self._flush() except Exception as e: logger.error(f消费异常: {e}) self._flush() raise def _flush(self): 批量写入 ClickHouse if not self.buffer: return rows [] for record in self.buffer: row self._transform(record) if row: rows.append(row) if not rows: self.buffer [] return # 带重试的写入 for attempt in range(self.MAX_RETRIES): try: self.ch.execute( INSERT INTO app_logs VALUES, rows ) logger.info(f成功写入 {len(rows)} 条日志) break except Exception as e: logger.error(f写入失败 (尝试 {attempt 1}): {e}) if attempt self.MAX_RETRIES - 1: time.sleep(2 ** attempt) self.buffer [] self.last_flush time.time() # 手动提交 offset self.consumer.commit() def _transform(self, record: Dict) - tuple: 日志格式转换与清洗 try: ts record.get(timestamp, datetime.now().isoformat()) timestamp datetime.fromisoformat( ts.replace(Z, 00:00) ) return ( timestamp, record.get(service, unknown), record.get(level, INFO), record.get(logger, ), record.get(message, ), record.get(fields, {}).get(trace_id, ), record.get(fields, {}).get(user_id, 0), record.get(fields, {}).get(duration_ms, 0), json.dumps(record.get(fields, {}), ensure_asciiFalse) ) except Exception as e: logger.warning(f日志转换失败: {e}) return None3.3 ClickHouse 表结构-- 1. 本地表每个节点独立 CREATE TABLE app_logs_local ON CLUSTER log_cluster ( timestamp DateTime, service LowCardinality(String), level LowCardinality(String), logger String, message String, trace_id String, user_id UInt64, duration_ms UInt32, extra String ) ENGINE MergeTree() PARTITION BY toYYYYMMDD(timestamp) ORDER BY (service, level, timestamp) TTL timestamp INTERVAL 30 DAY -- 30天自动过期 SETTINGS index_granularity 8192; -- 2. 分布式表查询入口 CREATE TABLE app_logs ON CLUSTER log_cluster AS app_logs_local ENGINE Distributed(log_cluster, logs, app_logs_local, rand());四、三条架构边界的警醒边界一Kafka 的无限缓冲是幻觉Kafka 的 Topic 大小由磁盘容量决定。当消费者故障超过 Kafka 的保留时间默认 7 天数据将永久丢失。因此 Kafka 不是无限缓冲而是有限缓冲。边界二ClickHouse 的写入峰值ClickHouse 的最大写入吞吐受 Part Merge 速度限制。当 Merge 速度跟不上 Insert 速度时Parts 数量爆炸10000查询性能急剧下降。解决方案是控制写入批次大小和合理分区。边界三日志清洗在哪里做在 Filebeat 端做清洗Processor可以减少无效数据进入 Kafka但会消耗业务服务器资源。在消费端做清洗可以利用消费者组的并行能力。实践中在 Filebeat 端做轻量过滤在消费者端做复杂清洗是最佳平衡。五、总结万亿级日志系统的改造表面上是工具替换ELK → Kafka ClickHouse实质上是架构思想的转变解耦采集与存储Filebeat 负责采集Kafka 负责缓冲ClickHouse 负责存储——每层职责单一列式存储是日志的天配日志查询多为按服务、时间、级别聚合ClickHouse 的列存天然适合这类 OLAP 查询TTL 自动过期是运维的福报不需要手动清理过期日志MergeTree Engine 的 TTL 机制自动完成改造后日志平台的 TCO总拥有成本降低了 67%主要是存储成本ES 的倒排索引开销极大和服务器成本Logstash 的 JVM 需求。查询响应时间从分钟级降到秒级运维团队终于可以在故障时实时查看日志而非等待 Kibana 加载。

相关新闻

营商环境优化:AI 成为看不见的 “服务员”

营商环境优化:AI 成为看不见的 “服务员”

开办企业、申报政策、项目审批、信用修复、合规自查……对于无数创业者和小微企业而言,以往这些高频经营环节,总绕不开“材料多、流程繁、等待久、找不准”的痛点。过去优化营商环境,更多是靠制度改革、流程精简、人员提效,而如今…

2026/7/8 14:55:38阅读更多 →
Agent 工具注册中心落地:让每个工具都有版本和回滚路径

Agent 工具注册中心落地:让每个工具都有版本和回滚路径

Agent 工具注册中心落地:让每个工具都有版本和回滚路径 一、当 Agent 的工具一夜之间全部不可用 Agent 的核心能力来自工具调用。给大模型挂载搜索、计算、数据库查询等能力。但工具变更往往成为事故的温床。上周,搜索工具的 API 参数从 query 改成了 se…

2026/7/8 14:55:38阅读更多 →
GlusterFS Dashboard社区指南:如何参与讨论、报告问题和获得支持的终极指南 [特殊字符]

GlusterFS Dashboard社区指南:如何参与讨论、报告问题和获得支持的终极指南 [特殊字符]

GlusterFS Dashboard社区指南:如何参与讨论、报告问题和获得支持的终极指南 🚀 【免费下载链接】glusterfs-dashboard dashboard for glusterfs 项目地址: https://gitcode.com/openeuler/glusterfs-dashboard 前往项目官网免费下载:h…

2026/7/8 14:55:38阅读更多 →
Windows B站客户端终极指南:如何用原生应用提升观影体验

Windows B站客户端终极指南:如何用原生应用提升观影体验

Windows B站客户端终极指南:如何用原生应用提升观影体验 【免费下载链接】BiliBili-UWP BiliBili的UWP客户端,当然,是第三方的了 项目地址: https://gitcode.com/gh_mirrors/bi/BiliBili-UWP 你是否曾在Windows电脑上观看B站视频时&am…

2026/7/8 15:55:48阅读更多 →
XUnity Auto Translator终极指南:3步实现Unity游戏实时自动翻译的完整教程

XUnity Auto Translator终极指南:3步实现Unity游戏实时自动翻译的完整教程

XUnity Auto Translator终极指南:3步实现Unity游戏实时自动翻译的完整教程 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 你是否曾经因为语言障碍而错过优秀的日本或韩国游戏?XUn…

2026/7/8 15:55:48阅读更多 →
XUnity Auto Translator终极指南:5分钟快速实现游戏自动翻译的完整教程

XUnity Auto Translator终极指南:5分钟快速实现游戏自动翻译的完整教程

XUnity Auto Translator终极指南:5分钟快速实现游戏自动翻译的完整教程 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 你是否因为语言障碍而无法畅玩心仪的日系、韩系或欧美游戏?…

2026/7/8 15:55:48阅读更多 →
Beyond Compare 5 密钥生成器:3种方法永久激活文件对比神器

Beyond Compare 5 密钥生成器:3种方法永久激活文件对比神器

Beyond Compare 5 密钥生成器:3种方法永久激活文件对比神器 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 如果你正在为Beyond Compare 5的试用期到期而烦恼,或者需要为…

2026/7/8 15:55:48阅读更多 →
高效手机号码定位:3个实用场景的开源解决方案

高效手机号码定位:3个实用场景的开源解决方案

高效手机号码定位:3个实用场景的开源解决方案 【免费下载链接】location-to-phone-number This a project to search a location of a specified phone number, and locate the map to the phone number location. 项目地址: https://gitcode.com/gh_mirrors/lo/l…

2026/7/8 15:55:48阅读更多 →
3步解锁百度网盘满速下载:Python直链解析效率革命

3步解锁百度网盘满速下载:Python直链解析效率革命

3步解锁百度网盘满速下载:Python直链解析效率革命 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘那令人绝望的下载速度而挣扎吗?baidu-…

2026/7/8 15:50:47阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/8 5:12:14阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/8 7:00:12阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/8 2:26:06阅读更多 →
作为一个给团队打绩效的人,我想说几句

作为一个给团队打绩效的人,我想说几句

我每半年都会给团队成员打绩效,也会参与和 CTO 的绩效校准,所以从管理者的视角,说说这件事 首先,我先把结论告诉你:接受结果,但一定要把原因问清楚。 因为当绩效公布到你这里的时候,结果基本已…

2026/7/8 0:01:17阅读更多 →
A股股指期货:全维度解析(多表格结构化完整版)

A股股指期货:全维度解析(多表格结构化完整版)

一、基础定义与核心本质股指期货全称股票价格指数期货,是中国金融期货交易所(中金所)上市的标准化金融期货合约,交易标的为 A 股大盘指数,约定未来特定时间按约定价格现金交割指数涨跌差价,不交割一篮子股票…

2026/7/8 0:01:17阅读更多 →
iOS越狱新手指南:从困惑到掌控,3天解锁iPhone无限潜能的真实故事

iOS越狱新手指南:从困惑到掌控,3天解锁iPhone无限潜能的真实故事

iOS越狱新手指南:从困惑到掌控,3天解锁iPhone无限潜能的真实故事 【免费下载链接】Jailbreak iOS 26.4 - 26, 17 - 17.7.5 & iOS 18 - 18.7.3 Jailbreak Tools, Cydia/Sileo/Zebra Tweaks & Jailbreak News Updates || AI Jailbreak Finder &…

2026/7/8 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/8 6:59:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/8 13:42:39阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/8 13:42:39阅读更多 →