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 的链路追踪数据,充当其界面和存储端。