下面给你一套 高吞吐、低成本日志系统方案:ClickHouse + Filebeat/Fluentd 的最简可落地架构,含组件分工、部署要点、建表示例和配置模板。
一、整体架构(极简版)
应用日志文件/容器日志
↓
Filebeat / Fluent Bit(采集、轻量过滤)
↓
Kafka(可选,削峰、解耦、重放)
↓
ClickHouse(列式存储、高压缩、高吞吐写入/查询)
↓
Grafana / 自建后台(可视化、检索、告警)
核心优势
- 高吞吐:ClickHouse 批量写入、向量化执行,写入 TPS 远高于 ES
- 低成本:列式 + 高压缩(通常 5--15 倍),磁盘 / 内存成本远低于 ES
- 适合日志:时间序列、结构化 / 半结构化、聚合查询友好
二、组件选型与分工
1. 采集层:Filebeat vs Fluent Bit
- Filebeat
- 优点:Elastic 生态成熟、配置简单、对日志文件 / 多行支持好
- 适合:传统服务、文件日志、Java 应用
- Fluent Bit
- 优点:更轻量、性能更好、K8s / 容器原生、插件丰富
- 适合:K8s、云原生、高密部署
推荐 :非 K8s 用 Filebeat ;K8s 用 Fluent Bit。
2. 缓冲层:Kafka(强烈建议)
- 作用:削峰、解耦、保证不丢、可重放、多下游复用
- 不建议直接从采集器写 ClickHouse:突发流量易写失败、无重试队列
3. 存储层:ClickHouse
- 推荐引擎:
MergeTree家族(MergeTree/ReplacingMergeTree/SummingMergeTree) - 分区:按天 / 小时分区(日志典型)
- 索引:时间戳 + 服务名 + 级别 + traceId 等常用维度
- 压缩:默认
LZ4即可,高压缩用ZSTD
三、ClickHouse 建表示例(通用日志表)
CREATE TABLE IF NOT EXISTS logs (
timestamp DateTime64(3) CODEC(DoubleDelta, LZ4),
service String CODEC(ZSTD),
level String CODEC(ZSTD),
trace_id String CODEC(ZSTD),
span_id String CODEC(ZSTD),
host String CODEC(ZSTD),
path String CODEC(ZSTD),
message String CODEC(ZSTD),
json_fields Map(String, String) CODEC(ZSTD)
) ENGINE = MergeTree()
PARTITION BY toDate(timestamp)
ORDER BY (service, level, toStartOfHour(timestamp), timestamp)
TTL timestamp + INTERVAL 30 DAY DELETE; -- 自动删 30 天日志,按需改
要点:
DateTime64(3):毫秒级时间CODEC:显式指定压缩,提升压缩比PARTITION BY toDate(timestamp):按天分区,删除 / 查询更快TTL:自动过期,降低存储成本
四、Filebeat → Kafka 配置示例(filebeat.yml)
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/myapp/*.log
multiline.type: pattern
multiline.pattern: '^\['
multiline.negate: true
multiline.match: after
fields:
service: my-java-app
fields_under_root: true
output.kafka:
hosts: ["kafka-1:9092", "kafka-2:9092"]
topic: "logs-myapp"
partition.round_robin:
reachable_only: false
required_acks: 1
compression: gzip
max_message_bytes: 1000000
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
Webfunny 全链路监控埋点平台 是一站式前端监控 + 用户行为埋点 + 大数据分析平台,天然适配点位细查、用户行为回溯、批量导出等场景:
一体化架构:监控 + 埋点同一套 SDK,数据互通无壁垒
私有化部署:数据完全本地化,满足企业合规要求
高吞吐支撑:基于 ClickHouse 构建,亿级日志秒级查询
全端覆盖:H5 / 小程序 / APP / 鸿蒙全覆盖,统一导出口径
可定制强:支持接口扩展、分布式锁、限流降级等企业级能力
五、Fluent Bit → Kafka 配置示例(fluent-bit.conf)
[SERVICE]
Flush 1
Log_Level info
Daemon off
[INPUT]
Name tail
Path /var/log/myapp/*.log
Parser json
Tag logs.myapp
Multiline On
Multiline_Format regex
Multiline_Pattern ^\[
DB /var/lib/fluent-bit/pos.db
[OUTPUT]
Name kafka
Match logs.*
Brokers kafka-1:9092,kafka-2:9092
Topics logs-myapp
Compression gzip
六、Kafka → ClickHouse 写入方案
方案 A:ClickHouse Kafka Engine(推荐,最简单)
在 CH 建一张 Kafka 消费表 + 物化视图写入日志表。
1)建 Kafka 引擎表(消费 topic)
CREATE TABLE logs_kafka (
raw String
) ENGINE = Kafka
SETTINGS
kafka_broker_list = 'kafka-1:9092,kafka-2:9092',
kafka_topic_list = 'logs-myapp',
kafka_group_name = 'clickhouse-log-group',
kafka_format = 'JSONAsString',
kafka_skip_broken_messages = 1;
2)建物化视图,解析 JSON 写入 logs 表
CREATE MATERIALIZED VIEW logs_mv TO logs AS
SELECT
toDateTime64(JSONExtractString(raw, 'timestamp'), 3) AS timestamp,
JSONExtractString(raw, 'service') AS service,
JSONExtractString(raw, 'level') AS level,
JSONExtractString(raw, 'trace_id') AS trace_id,
JSONExtractString(raw, 'span_id') AS span_id,
JSONExtractString(raw, 'host') AS host,
JSONExtractString(raw, 'path') AS path,
JSONExtractString(raw, 'message') AS message,
JSONExtract(raw, 'json_fields', 'Map(String, String)') AS json_fields
FROM logs_kafka;
优点:无额外组件,CH 自己消费 Kafka,运维简单。
方案 B:使用 Vector / Logstash(更灵活)
- 适合:需要复杂 ETL、多 sink、路由、 enrichment 场景
- 流程:Kafka → Vector/Logstash(解析 / 清洗)→ ClickHouse
七、关键优化(高吞吐 + 低成本)
1. ClickHouse 写入优化
- 批量写入:Kafka + CH Kafka Engine 天然批量
max_insert_block_size = 1048576async_insert = 1(异步插入,提升吞吐,注意数据安全)- 内存表 / Buffer 表做写入缓冲(可选)
2. 存储与压缩
- 优先
ZSTD压缩,比 LZ4 压缩比更高,CPU 开销可接受 - 按时间分区,TTL 自动清理,避免无限膨胀
- 冷数据可使用 S3 分层存储(CH 支持 S3 磁盘)
3. 采集端优化
- 采集端开启
gzip压缩 - 多行日志正确配置,避免乱序 / 截断
- 采集器资源限制:Filebeat/Fluent Bit 都很轻量
八、典型查询示例
-- 近 1 小时错误日志
SELECT *
FROM logs
WHERE level = 'ERROR'
AND timestamp >= now() - INTERVAL 1 HOUR
ORDER BY timestamp DESC
LIMIT 100;
-- 按服务统计 QPS/错误数
SELECT
toStartOfMinute(timestamp) AS minute,
service,
count() AS total,
countIf(level = 'ERROR') AS errors
FROM logs
WHERE timestamp >= now() - INTERVAL 1 HOUR
GROUP BY minute, service
ORDER BY minute, service;
九、与 ELK 对比(简要)
表格
| 维度 | ELK Stack | ClickHouse + Filebeat/Fluentd |
|---|---|---|
| 写入吞吐 | 中高 | 更高(批量 + 向量化) |
| 存储成本 | 较高(倒排索引) | 低(列式 + 高压缩) |
| 全文检索 | 强 | 一般(n-gram/Token 可做) |
| 聚合 / 统计 | 一般 | 极强 |
| 运维复杂度 | 中(ES 分片 / 集群敏感) | 较低(CH 简单,无分片烦恼) |
| 适合场景 | 全文检索、日志 + 安全分析 | 高吞吐、低成本、统计聚合为主 |
十、落地建议
如果你是 Java 后端,常见场景:
- 应用:Spring Boot + Logback/Log4j2 输出 JSON 日志
- 采集:Filebeat 采集日志文件 → Kafka
- 存储:ClickHouse 用 Kafka Engine 消费
- 可视化:Grafana + ClickHouse 数据源 做面板 / 检索