diff --git a/Observability/logging.md b/Observability/logging.md index 51ebcd12..4cd8ba58 100644 --- a/Observability/logging.md +++ b/Observability/logging.md @@ -1,46 +1,42 @@ # 9.3.2 日志的存储与索引 -处理日志本来是件稀松平常的事情,但数据规模的影响下,量变引发质变,日志处理成为典型的大数据场景之一:高吞吐写入(GB/s)、低成本海量存储(PB 级别)、亿级数据量实时检索(1s 内)。 +处理日志本来是件稀松平常的事情,但随着数据规模的增长,量变引发质变,高吞吐写入(GB/s)、低成本海量存储(PB 级别)以及亿级数据的实时检索(1 秒内),已成为软件工程领域最具挑战性的难题之一。 -本节,笔者将从日志存储与分析的角度,介绍三种各具特色的日志系统方案:Elastic Stack(全文索引)、Loki(仅索引元数据)和 ClickHouse(列式数据库)。 -## 1. 全文索引方案 Elastic Stack +本节将从日志存储与分析的角度出发,介绍业内三种主流的日志处理解决方案。 -讨论如何实现一套完整的日志系统时,工程师们或多或少都听说过这几个名词:ELK、ELKB 或 Elastic Stack。 +## 1. 全文索引方案 Elastic Stack -实际上,它们指向的是同一套用于日志处理的开源组件。Elastic Stack(为明确统一,本文统称 Elastic Stack)是由 Elastic 公司开发的一组开源工具,专门用于数据海量的收集、搜索、分析和可视化处理。 +在讨论如何实现完整的日志系统时,ELK、ELKB 或 Elastic Stack 是工程师们耳熟能详的名词。它们实际上指代同一套由 Elastic 公司[^1]开发的开源工具,用于海量数据的收集、搜索、分析和可视化处理。 图 9-6 展示了一套基于 Elastic Stack 的日志处理方案: -- **数据收集**:Beats 组件部署在日志生成节点,负责收集原始数据。 -- **数据缓冲**:使用消息队列(RabbitMQ)缓冲数据,以提高数据吞吐量。 -- **数据清洗**:数据发送到 Logstash 清洗。 -- **数据存储**:清洗后的数据存储在 Elasticsearch 集群,并生成索引。 -- **数据可视化**:Kibana 负责数据检索、分析、可视化处理。如果需要,还可以再部署一套 Nginx 实现访问控制。 +- **数据收集**:Beats 组件部署在业务所在节点,负责收集原始的日志数据。 +- **数据缓冲**:使用 RabbitMQ 消息队列缓冲数据,提高数据吞吐量。 +- **数据清洗**:数据通过 Logstash 进行清洗。 +- **数据存储**:清洗后的数据存储在 Elasticsearch 集群中,它负责索引日志数据、查询聚合等核心功能。 +- **数据可视化**:Kibana 负责数据检索、分析与可视化,必要时可部署 Nginx 实现访问控制。 :::center ![](../assets/ELK.png)
- 图 9-6 整合了消息队列和 Nginx 的 Elastic 日志系统 + 图 9-6 整合了消息队列、Nginx 的 Elastic Stack 日志系统 ::: -:::tip 额外知识 -Elastic 公司的发展始于创始人 Shay Banon 的个人兴趣,从开源、聚人、成立公司,到走向纽交所,再到股价一路狂飙(截止 2024 年 7 月 11 日,最新市值 $107 亿),几乎是最理想的工程师创业故事。 -::: +Elastic Stack 中最核心的组件是 Elasticsearch —— 基于 Apache Lucene 构建的开源的搜索与分析引擎。值得一提的是,Lucene 的作者就是大名鼎鼎的 Doug Cutting,如果你不知道他是谁是?那你一定听过他儿子玩具的名字 —— Hadoop。 -Elastic Stack 套件中,最核心的组件是 Elasticsearch —— 一个基于 Apache Lucene 构建的开源的搜索与分析引擎。值得一提的是,Lucene 的作者就是大名鼎鼎的 Doug Cutting,如果你不知道他是谁是?那你一定听过他儿子玩具的名字 —— Hadoop。 +Elasticsearch 能够在海量数据中迅速检索关键词,其关键技术之一就是 Lucene 提供的“反向索引”(Inverted Index)。与反向索引相对的是正向索引,二者的区别如下: -Elasticsearch 能够在海量数据中快速检索关键词,其关键技术之一是 Lucene 中的“反向索引”(Inverted Index)。与反向索引相对的是正向索引,两者的区别是: +- **正向索引**(Forward Index):传统的索引方法,将文档集合中的每个单词作为键,值为包含该单词的文档列表。正向索引适用于快速检索特定标识符的文档,常见于数据库中的主键索引。 +- **反向索引**(Inverted Index):反向索引通过将文本分割成词条并构建“<词条->文档编号>”的映射,快速定位某个词出现在什么文档中。值得注意的是,反向索引常被译为“倒排索引”,但“倒排”容易让人误以为与排序有关,实际上它与排序无关。 -- **正向索引(Forward Index)**:正向索引是一种传统的索引方法,它将文档集合中的每个单词作为键,将包含该单词的文档列表作为值。正向索引适用于快速检索特定标识符的文档,常用于数据库管理系统中的主键索引。 -- **反向索引(Inverted Index)**:反向索引通常被译为“倒排索引”,但“倒排”容易让人误以为与排序有关,实际上它与排序无关。反向索引的工作原理是将文本分割成词条,并构建“<词条->文档编号>”的索引,以便快速定位某个词出现在哪些文档中。 - -以下面三段要被索引的英文为例: +举一个具体的例子,以下是三个待索引的英文句子: - T~0~ = "it is what it is" - T~1~ = "what is it" - T~2~ = "it is a banana" -通过反向索引,得到下面的匹配关系。 +通过反向索引,可以得到以下匹配关系: + ``` "a": {2} "banana": {2} @@ -48,40 +44,34 @@ Elasticsearch 能够在海量数据中快速检索关键词,其关键技术之 "it": {0, 1, 2} "what": {0, 1} ``` -检索时,条件“what”, “is” 和 “it” 将对应这个集合:$\{0, 1\}\cap\{0,1,2\}\cap\{0,1,2\} = \{0,1\}$。可以看出,反向索引使得搜索操作能够快速定位包含特定关键词的文档,而无需逐一扫描所有文档。 +在检索时,条件“what”、“is” 和 “it” 将对应集合:$\{0, 1\}\cap\{0,1,2\}\cap\{0,1,2\} = \{0,1\}$。可以看出,反向索引能够快速定位包含特定关键词的文档,而无需逐个扫描所有文档。 -Elasticsearch 另一项关键技术是“分片”(sharding),每个分片相当于一个独立的 Lucene 实例,类似于一个完整的数据库。 +Elasticsearch 的另一项关键技术是“分片”(sharding)。每个分片相当于一个独立的 Lucene 实例,类似于一个完整的数据库。在文档写入时,Elasticsearch 会根据哈希函数(通常基于文档 ID)计算出文档所属的分片,从而将文档均匀分配到不同的分片;查询时,Elasticsearch 会并行地在多个分片上执行计算,并将结果聚合后返回给客户端,从而提高查询吞吐量。 -- 文档写入时,Elasticsearch 通过哈希函数(通常基于文档 ID)计算该文档应存储的分片,从而将文档有序地分配到不同的分片中。 -- 查询文档时,查询请求并行地在多个分片上执行计算,最终将结果聚合后返回给客户端,这显著提升了查询的吞吐量。 - -追求极致查询性能的背后,Elasticsearch 也付出了相应的代价: - -- **写入吞吐量下降**:文档写入过程中需要进行分词和构建排序表等 CPU 和内存密集型操作,导致写入性能下降。 -- **存储空间占用高**:Elasticsearch 存储原始数据和反向索引,为了加速分析,可能还需要额外存储一份列式数据。 -- **冗余副本**:为避免分片的单点故障,Elasticsearch 默认为每个分片提供一个冗余副本。 +为了追求极致的查询性能,Elasticsearch 也付出了以下代价: +- **写入吞吐量下降**:文档写入需要进行分词和构建排序表等操作,这些都是 CPU 和内存密集型的,会导致写入性能下降。 +- **存储空间占用高**:Elasticsearch 不仅存储原始数据和反向索引,为了加速分析能力,可能还额外存储一份列式数据(Column-oriented Data);其次,为了避免单点故障,Elasticsearch 会为每个分片创建一个或多个副本副本(Replica),这导致 Elasticsearch 会占用极大的存储空间。 ## 2. 轻量化处理方案 Loki -Grafana Loki(简称 Loki)是由 Grafana Labs 开发的一款日志聚合系统。其设计灵感来源于 Prometheus,旨在成为“日志领域的 Prometheus”,并具有轻量、低成本以及与 Kubernetes 高度集成的特点。 +Grafana Loki 是由 Grafana Labs 开发的一款日志聚合系统,其设计灵感来源于 Prometheus,目标是成为“日志领域的 Prometheus”。与 Elastic Stack 相比,Loki 具有轻量、低成本和与 Kubernetes 高度集成等特点。 -Loki 的主要组件包括 Promtail(日志代理)、Distributor(分发器)、Ingester(写入器)、Querier(查询器)、Query Frontend(查询前端)和 Ruler(规则处理器)。其中,Promtail 负责从各种来源收集日志,Distributor 验证并分发日志,Ingester 负责存储和索引日志,Querier 用于执行日志查询,Query Frontend 优化查询请求,而 Ruler 负责监控和告警规则的执行。 +Loki 的架构如图 9-7所示,主要组件有 Promtail(日志代理)、Distributor(分发器)、Ingester(写入器)、Querier(查询器)、Query Frontend(查询前端)和 Ruler(规则处理器)。其中,Promtail 负责从多种来源收集日志;Distributor 验证并分发日志;Ingester 负责存储和索引日志;Querier 执行日志查询;Query Frontend 优化查询请求;Ruler 处理监控和告警规则的执行。 :::center ![](../assets/loki_architecture_components.svg)
图 9-7 Loki 架构 ::: -Loki 最大的特点是,不对原始日志数据、仅对日志的元数据(如标签和时间戳)建立索引。在 Loki 的存储模型中,有两种数据类型:块(Chunks)和索引(Indexes)。 - -- **索引(Indexes)**:索引存储每个日志流的标签集,并将其与相应的块关联。索引的作用是快速定位到特定的日志块,从而提高查询效率。索引通常存储在高读写性能的数据库中,如 Amazon DynamoDB、Google Bigtable 或 Apache Cassandra。 -- **块(Chunks)**:块是 Loki 存储日志数据的主要方式,包含原始日志内容。当日志条目到达 Loki 时,它们被压缩并存储为块,保存在对象存储(如 Amazon S3 或 Google Cloud Storage)或本地文件系统中。 +Loki 的主要特点是,只对日志的元数据(如标签、时间戳)建立索引,而不对原始日志数据进行索引。在 Loki 的存储模型中,数据有以下两种类型: -用户发起日志查询时,查询请求根据“时间范围”和“标签”在索引中查找对应的块。然后,Loki 根据索引返回的块元数据,从块存储中读取并解压缩原始日志数据,返回给用户。 +- **索引**(Indexes):Loki 的索引仅包含日志流的标签(如日志的来源、应用名、主机名等)和时间戳,并将其与相应的块关联。 +- **块**(Chunks):块是 Loki 用来存储实际日志数据的基本单元。每个日志条目都会被压缩成一个块,并存储在持久化存储介质中,如对象存储(例如 Amazon S3、GCP、MinIO)或本地文件系统。 -仅索引元数据、索引和块的分离存储的设计,让 Loki 处理大规模日志数据时具有明显的成本优势。 +当用户发起日志查询时,Loki 根据时间范围和标签等查询条件,首先在索引中查找与条件匹配的块。然后,Loki 使用这些索引信息找到对应的日志块,从块存储中读取日志数据,并将其解压缩后返回给用户。 +不难看出,Loki 通过仅索引元数据、以及索引和块的分离存储设计,让其在处理大规模日志数据时具有明显的成本优势。 ## 3. 列式存储数据库 ClickHouse @@ -158,7 +148,6 @@ ClickHouse 支持“分片”(Sharding)技术,也就是支持分布式并 图 9-9 ClickHouse 性能测试 [图片来源](http://clickhouse.yandex/benchmark.html) ::: - - +[^1]: Elastic 公司的发展始于创始人 Shay Banon 的个人兴趣,从开源、聚人、成立公司,到走向纽交所,再到股价一路狂飙(截止 2024 年 7 月 11 日,最新市值 $107 亿),几乎是最理想的工程师创业故事。 [^1]: 以运营俄罗斯最受欢迎的搜索引擎闻名,被称为俄罗斯的 Google [^2]: 参见 https://mp.weixin.qq.com/s/dUs7WUKUDOf9lLG6tzdk0g \ No newline at end of file diff --git a/Observability/tracing.md b/Observability/tracing.md index a5889d2e..d4ebcad3 100644 --- a/Observability/tracing.md +++ b/Observability/tracing.md @@ -49,8 +49,8 @@ Dapper 论文的发布,让治理复杂分布式系统迎来了转机,链路 以 SkyWalking 的 Java 追踪探针为例,它实现的原理是将需要注入的类文件(追踪逻辑代码)转换成字节码,然后通过拦截器注入到正在运行的应用程序中。比起基于日志实现的追踪,基于服务的追踪在资源消耗和侵入性(但对业务工程师基本无感知)上有所增加,但其精确性和稳定性更高。现在,基于服务的追踪是目前最为常见的实现方式,被 Zipkin、Pinpoint、SkyWalking 等主流链路追踪系统广泛采用。 - **基于边车代理的追踪**:这是服务网格中的专属方案,基于边车代理的模式无需修改业务代码,也没有额外的开销,是最理想的分布式追踪模型。总结它的特点如下: - - **对应用完全透明**:有自己独立数据通道,追踪数据通过控制平面上报,不会有任何依赖或干扰; - - **与编程语言无关**:无论应用采用什么编程语言,只要它通过网络(如 HTTP 或 gRPC)访问服务,就可以被追踪到。 + - 对应用完全透明:有自己独立数据通道,追踪数据通过控制平面上报,不会有任何依赖或干扰; + - 与编程语言无关:无论应用采用什么编程语言,只要它通过网络(如 HTTP 或 gRPC)访问服务,就可以被追踪到。 目前,市场占有率最高的边车代理 Envoy 就提供了链路追踪数据采集功能,但 Envoy 没有自己的界面端和存储端,需要配合专门的 UI 与存储系统来使用。不过,Zipkin、SkyWalking、Jaeger 和 LightStep Tracing 等等系统都能够接收来自 Envoy 的链路追踪数据,充当其界面和存储端。