分布式日志指标系统设计

本文介绍了生产级可观测平台的端到端设计,处理大规模实时日志、指标以及结构化/非结构化事件,满足现代大型系统对可靠日志和指标的需求。原文:Design a Distributed Logging and Metrics Platform

可观测性在现代大型系统中(无论是电商、社交平台还是物联网云)至关重要,开发者、SRE 和数据团队依赖可靠的日志、指标和事件流来理解应用行为、解决事故并做出数据驱动的决策。本文将介绍生产级可观测平台的端到端设计,处理大规模实时日志、指标以及结构化/非结构化事件。

🎯 系统需求

✅ 功能性需求

为满足工程师、分析师和系统团队的实际需求,平台必须:

  • 近实时的接受来自多个源(如服务、SDK、代理、物联网设备)的日志、指标和事件。
  • 支持结构化、半结构化和非结构化文本数据的输入。
  • 允许解析、转换并丰富日志和事件,并包含元数据(如 user_id、环境、版本)。
  • 提供全文搜索日志,并带有时间戳、服务或错误级别等筛选条件。
  • 支持跨时间范围和聚合窗口查询指标。
  • 支持类似SQL的查询,并通过 Presto、Trino 或 Spark SQL 等引擎通过事件数据集连接。
  • 处理基于标签(如 org_id、区域、event_type)到不同处理路径或汇聚点的消息路由。
  • 提供阈值警报和异常检测(例如通过 Grafana 或 Prometheus)。
  • 公开 API 和仪表盘,供日志和指标使用。
  • 允许历史日志和事件存档于冷存储中,以支持合规或审计。
🔒 非功能性需求

在性能和可靠性方面,系统必须:

  • 每秒接收数百万事件,端到端延迟 < 100ms。
  • 实现跨数据中心和区域的容错,确保无单点故障。
  • 每个层级(输入、流处理、存储和查询)支持横向扩展。
  • 利用 TLS 和 KMS 加密静态和实时敏感数据。
  • 启用细粒度访问控制(RBAC),并通过审计日志跟踪访问。
  • 提供自修复、自动扩展和平台本身的可观测性。
  • 将存储分为热存储(快速访问)和冷存储(成本效益高)两个层级。
  • 支持模版升级、数据验证和模版注册表集成。
  • 实现云中立或兼容混合云,适用于全球工作负载。

📈 容量估算

输入量
  • 峰值输入速率:200万次事件/秒
  • 日处理量:~1500亿事件/天
日志大小
  • 平均日志/事件大小:1.2 KB
  • 每日总输入量:~180 TB/天
存储需求
  • 热存储(7天保留):~1.2 PB
  • 冷存储(90天):~16 PB(假设 Parquet 压缩为2:1)
⚙️ Kafka 容量与对齐

Kafka 作为将输入与下游处理分离的骨干。

为什么是卡夫卡?

Kafka 因其高吞吐量、耐用性、内置复制和生态系统集成而被选中,支持至少一次传输、水平分区和细粒度重放功能。

配置详情

  • 主题分区:约 15,000
  • 为了安全处理每秒 2M 事件(≈2,400 MB/秒),保持分区负载 < 10MB/s
  • 因此,2400 / 10 = 240 分区的最小分区 → 可扩展到 15,000 分区,以支持多租户、重试和并行处理
  • 代理数量:约 150
  • 每个分区处理约 100 个活动分区,日志段使用 NVMe SSD
  • 复制因子:3(跨机架的 HA)
  • 保留时间:热日志保留 3 天,之后进行下游 ETL 或冷归档
  • 背压:Kafka 提供有界队列和通过消费者延迟监控的流量控制
🔄 流处理(Apache Flink)

Apache Flink 用于实时、高通量的流处理,如修饰、转换、窗口聚合、异常检测和路由。

为什么是Flink?

  • 原生事件时支持(带水印)处理乱序数据
  • 低延迟流式传输,高吞吐量,并实现细粒度检查点
  • 使用 RocksDB 状态后端实现容错且保证一次的准确性
  • 支持丰富的CEP(复杂事件处理)、异步I/O和广播状态

配置

  • 操作符:基于 CPU/内存使用率,可并行 20--50 个
  • 事件时间支持:用于乱序窗口的水印
  • 检查点设置:RocksDB 状态后端 + S3 检查点(约 100 TB 总状态)
  • 恢复 SLA:任务管理器 < 2分钟,否则作业失败
  • 使用场景:多租户路由、异常检测、装饰连接
🔍 弹性搜索集群

由 Elasticsearch 驱动日志全文搜索和结构化字段查询。

为什么选择Elasticsearch?

  • 成熟且经过生产验证的全文搜索引擎
  • 嵌套 JSON 文档的实时索引与查询
  • 与 Kibana 集成用于可视化仪表盘

配置

  • 原始日志导入:约 100+ TB/天(未压缩)
  • 索引:文本 + JSON 字段映射
  • 集群布局:300 个热节点,100 个热节点
  • 保留:
    • 热数据(7 天):快速 SSD 支持型
    • 温数据 (30 天): 较慢的 EBS
    • 冷数据(快照到 S3 或 GCS)
  • 分片:按租户或服务分片,带有每日轮转指数
🏞️ 对象存储(S3 / GCS)上的数据湖

批处理分析、长期保留和临时探索均通过数据湖处理。

为什么选择对象存储+湖屋引擎?

  • 便宜、耐用、无限扩展
  • 兼容所有主要引擎(Spark、Trino、Presto、Hive)
  • 通过解耦计算和存储以节省成本

配置

  • 每日输入量:约 30 TB/天(Snappy Parquet)
  • 分区方式:按 org_idevent_typedt 分区
  • 查询引擎:Presto、Trino、Athena、BigQuery
  • 生命周期政策:
    • 90天有效
    • 冷数据/归档层
    • 一年后删除(合规受控)
📉 时间序列数据库(指标)

兼容Prometheus(如 Mimir、Cortex、VictoriaMetrics)支持低延迟的指标输入和提醒。

为什么选择时间序列数据库?

  • 内置支持聚合、压缩和降采样
  • 设计用于高基数和维度标记
  • 与 Grafana 和 PromQL 紧密集成

配置

  • 采样率:800 万采样率/秒
  • 基数:500万唯一时间序列(通过维标签)
  • 保留:30天原始素材 → 降采样层级(1m、5m、1h)
  • 存储估算:压缩后每月 100 TB
  • 使用场景:SLO、Grafana 仪表盘、异常检测

🧠 设计权衡

Kafka vs. Kinesis / Pulsar
  • 选择卡夫卡是因为成熟度、更强的社区和更优越的回放控制。
  • Pulsar 原生支持分层存储,但 Kafka + S3 汇聚连接器实现了类似的效果。
Elasticsearch vs. OpenSearch vs. Loki
  • 选择 Elasticsearch 是因为更高的成熟度和生态系统支持(例如Kibana)。
  • Loki 仅在日志工作负载中更具成本效益,但缺乏全文搜索功能。
  • OpenSearch 是一个开源可选项,但在某些版本中缺乏商业支持和稳定性。
  • Flink 提供原生事件处理、更好的有状态计算扩展性和高吞吐量。
  • Spark 是批处理优化的,Kafka Streams 对于多阶段流水线来说过于简单。
数据湖与传统数据库的区别
  • 数据湖更具规模效益,支持读前模式(schema-on-read),能够处理庞大且多样化的格式。
  • Iceberg/Hudi/Delta 等湖屋(Lakehouse)能为原生数据湖带来更好的索引和稳定性。
时间序列数据库与 InfluxDB / OLAP
  • Prometheus 兼容的后端更适合 Kubernetes 原生工作负载。
  • 像 Druid/ClickHouse 这样的OLAP引擎可以补充长期聚合。
mTLS, RBAC & KMS
  • mTLS:确保内部微服务之间的相互认证。
  • RBAC:基于角色的 API 和 UI 访问策略。
  • KMS 集成:S3、Elasticsearch 和数据库的加密密钥管理。

🔁 数据流解释

1. 客户端/应用层:
  • 服务、SDK和代理会向输入端点发送日志/指标/事件。
2. Kafka 层:
  • 消息落在分区的 Kafka 主题上(基于 org_id、env 等标签)。
  • Kafka 缓冲流量,支持重试,并启用扇出功能。
  • 读取 Kafka 数据,丰富事件、筛选,并路由到 Elasticsearch、S3 或指标数据库。
  • 数据转换(例如扁平化、JSON 模式修复、异常检测)。
4. Elasticsearch:
  • 获取富日志,索引结构化/非结构化字段。
  • 通过 Kibana 暴露 API 和仪表盘。
5. 数据湖:
  • Flink/Spark 批处理作业会将原始/聚合日志推送到 Parquet 的 S3。
  • 可以通过 Trino/Presto/Athena 进行分区修剪查询。
6. 时间序列数据库:
  • 兼容 Prometheus 的系统指标抓取或接收数据 exporter 的推送。
  • 支持实时仪表盘和提醒。
7. 冷存储/归档:
  • 保留窗口结束后,数据会归档到冷存储(Glacier)或深度归档(Deep Archive)层级。
8. 访问层:
  • API、仪表盘和 SQL 引擎向用户和系统提供数据。

🧪 深度问答

问题 1. 如何将 Kafka 扩展到超过 15,000 个分区?

  • 使用多个按组织/环境分片的 Kafka 集群。
  • 对旧消息采用分层存储。
  • 使用 Kafka Raft(KRaft)模式以提升控制器的可扩展性。

问题 2. 如果 Flink 作业检查点失败会发生什么?如何恢复?

  • Flink 会回到最后一个成功的检查点。
  • 恢复方法:修复问题根源(例如磁盘/满载状态、损坏状态),并在启用 HA 的状态下重启作业。

问题 3. 如何确保 Kafka 与下游消费者之间的幂等性?

  • 使用 Kafka 消息键进行查重。
  • 应用一致的唯一 event_id,并在下游汇聚点(如 ES 或 DB)中跟踪。

问题 4. 为什么在这种设计中选择 Elasticsearch 而不是 OpenSearch?

  • 更稳定的生态系统,更好的可观测集成。
  • 商业支持(如有需要),但 OpenSearch 更受青睐,因为许可证灵活性更高。

问题 5. 如何划分 Kafka 主题以实现多租户隔离?

  • 主题名称如 log.org_<org_id>.env_<env>
  • 每个租户使用不同的主题,并应用 ACL 来执行访问控制。

问题 6. Kafka → Flink → ES 的背压处理机制是什么?

  • 启用 Flink 缓冲区超时调优和异步检查点。
  • Kafka 消费者延迟监控 + Flink 操作指标。
  • 调整 ES 的批量和重试策略。

问题 7. 如何在 Elasticsearch 和 S3 中实现符合 GDPR 的删除功能?

  • 在 ES + 生命周期策略中使用文档级 TTL 或标签。
  • 对于 S3:按组织/日期划分,使用 Lambda 根据请求日志进行删除。

问题 8. 如果日志峰值飙升至 5M/秒,最先出现的瓶颈是什么?怎么修复?

  • Kafka 磁盘/网络 I/O 使用 SSD 支持的代理 → 增加分区。
  • Flink 反压 → 扩展作业管理器/任务管理器。
  • ES 批量索引队列饱和 → 扩展 ES 数据节点,调优 JVM 堆和队列设置。
运维与基础设施重点

问题 1. 如何在服务之间启用 mTLS?用什么工具来轮换认证?

  • 使用 Istio 或 Consul Connect 实现自动 mTLS。
  • 证书管理器(带 Vault 或 ACM)用于签发/轮换 TLS 证书。

问题 2. 日志输入和搜索延迟的 SLO 是多少?

  • 导入时间:日志为 p95 < 2s,指标为 < 1s。
  • 搜索延迟:最近日志为 p95 < 1s,30 天保留日志为 64s 秒。

问题 3. 如何根据流量量自动调整 Flink 作业?

  • 监控 Kafka 延迟 + Flink 操作使用率。
  • 使用 Flink 的反应式缩放模式 + Kubernetes HPA。

问题 4. 如何进行基准测试,并选择 NVMe 还是 EBS 作为 ES 集群?

  • 为各种查询/写工作负载运行一次拉力基准测试。
  • NVMe 提供更好的 IOPS,可用于高 QPS 集群,成本敏感工作负载则回退到 EBS。
高级分析

问题 1. 如何将 Kafka 中的日志与数据库中的元数据(例如用户信息)连接起来?

  • 使用 Flink 异步 I/O 操作实时丰富日志。
  • 缓存频繁查询或使用侧输入(side-inputs)。

问题 2. 如何近实时的检测系统日志中的异常?

  • Flink + 滑动窗口聚合 + z 分数/异常值检测。
  • 使用部署在 Flink 上的机器学习模型,或发送丰富的日志给异常检测服务。

问题 3. 如何防止 Prometheus 中的高基数问题?

  • 限制动态标签的使用(例如 user_id、IP)。
  • 使用录制规则 + 在刮取时下采样。

🚦 总结

该日志与可观测性平台设计具备以下功能:

  • 处理 PB 级日志流
  • 支持实时指标仪表盘
  • 实现跨多层的高效连接和分析查询
  • 通过低延迟、高可用性架构来保证SLA

以 Kafka、Flink、Elasticsearch 和 S3 为核心构建模块,该系统已具备生产准备,适合初创企业和企业。添加托管解决方案(如MSK、OpenSearch、Dataflow)以简化操作。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

相关推荐
策策策lv112 小时前
杂记-@Transactional使用的一点记录
后端
code_std2 小时前
保存文件到指定位置,读取/删除指定文件夹中文件
java·spring boot·后端
汤姆yu2 小时前
基于springboot的热门文创内容推荐分享系统
java·spring boot·后端
武昌库里写JAVA2 小时前
在iview中使用upload组件上传文件之前先做其他的处理
java·vue.js·spring boot·后端·sql
嘻哈baby3 小时前
AI让我变强了还是变弱了?一个后端开发的年终自省
后端
舒一笑3 小时前
2025:从“代码搬运”到“意图编织”,我在 AI 浪潮中找回了开发的“爽感”
后端·程序员·产品
用户4099322502123 小时前
Vue3中v-if与v-for为何不能在同一元素上混用?优先级规则与改进方案是什么?
前端·vue.js·后端
blurblurblun3 小时前
Go语言特性
开发语言·后端·golang
Y.O.U..3 小时前
Go 语言 IO 基石:Reader 与 Writer 接口的 “最小设计” 与实战落地
开发语言·后端·golang