Skip to content

Commit

Permalink
更新可观测内容
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Sep 8, 2024
1 parent ef04750 commit 1050c94
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 50 deletions.
95 changes: 72 additions & 23 deletions Observability/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
图 9-10 整合了消息队列和 Nginx 的 Elastic 日志系统
:::

Elastic 套件中最核心组件是 Elasticsearch,这是一个提供一种“准实时”搜索服务(生产环境中可以做到上报 10 秒后可搜,不惜成本万亿级日志秒级响应)的分布式搜索分析引擎
Elastic 套件中最核心组件是 Elasticsearch,这是一个提供一种“准实时”搜索服务的分布式搜索分析引擎。准实时的意思是,生产环境中可以做到数据上报 10 秒后可搜,不惜成本的情况下,万亿级规模下日志查询秒级响应

:::tip 额外知识
说起 Elasticsearch 不得不提及背后的 Lucene。Lucene 的作者就是大名鼎鼎的 Doug Cutting,如果你不知道他是谁是?那你一定听过他儿子玩具的名字 —— Hadoop。
Expand All @@ -24,20 +24,39 @@ Lucene 是一个全文检索引擎,离直接使用还有部分集成工作,

:::

Elasticsearch 在**日志场景中的优势在于全文检索能力,快速从海量的数据中检索出关键词匹配的日志**其底层核心技术就是 Lucene 中的反向索引(Inverted index)。
Elasticsearch 在**日志场景中的优势在于全文检索能力,快速从海量的数据中检索出关键词匹配的日志**其底层核心是 Lucene 中的反向索引(Inverted index)技术

:::tip 什么是反向索引
索引有两种形式,分为正向索引和反向索引:

反向索引(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}
"is": {0, 1, 2}
"it": {0, 1, 2}
"what": {0, 1}
```

进行检索时,条件“what”, “is” 和 “it” 将对应这个集合:$\{0, 1\}\cap\{0,1,2\}\cap\{0,1,2\} = \{0,1\}$。

因此,Elasticsearch 搜索时不需要逐个扫描所有文档,而是能通过关键词快速定位包含这些词的文档。同时,每个索引(Index)可以被分成多个分片(shards),分片是独立的 Lucene 实例。当文档写入时,Elasticsearch 会通过哈希函数(通常是基于文档ID)计算出文档应该存储在哪个主分片中,从而将文档有序分配到不同分片。分片机制允许索引数据在集群中分布式存储,查询可以并行地在多个分片上执行,然后将结果聚合返回,这极大地提高了查询速度。

Elasticsearch 极致查询的背后,也付出了写入吞出率低和存储占用高的代价:

反向索引为 Elasticsearch 带来快速检索能力的同时,也付出了写入吞出率低和存储占用高的代价:
- **数据写入时需要进行分词、词典排序、构建排序表等 CPU/内存密集操作**,导致写入吞出率大幅下降;
- 文档写入时需要进行分词、词典排序、构建排序表等 CPU/内存密集操作,导致写入吞出率大幅下降;
- **Elasticsearch 会存储原始数据和反向索引,为了加速分析可能还需要存储一份列式数据(DocValue)**,3 份冗余数据在观测场景下导致极高的存储成本。

如果目的只是把日志集中起来,使用只是近期范围内查询和一些简单的条件(如匹配 host、service 等),那不妨看看下面介绍的 Loki。
如果目的只是把日志集中起来,使用只是近期范围内查询和一些简单的条件匹配(如匹配 host、service 等),那不妨看看下面介绍的 Loki。

## 2. 日志处理新贵 Loki

Expand Down Expand Up @@ -67,23 +86,54 @@ Loki 另外一个特点是对以 Kubernetes 为基座的系统十分友好。如

## 3. 凶猛彪悍的 ClickHouse

最近几年, ClickHouse 是一个用于 OLAP(On-Line Analytical Processing,在线分析处理)领域的列式列式数据库管理系统

ClickHouse 的关键特点有列式存储、向量化查询执行、高效压缩、高性能、实时数据处理、水平扩展、复杂查询(支持 SQL 语法)。

这些特点使 ClickHouse 大规模数据分析、实时流式数据查询以及业务数据分析的理想选择。

一个流行的观点认为:“提升查询速度的最简单有效方法是减少数据扫描范围和数据传输量”。

普通数据库中的数据是按照如图 9-13 所示的结构进行组织的。换句话说,一行内的所有数据都彼此依次存储,像这样的行式数据库包括 MySQL、Postgres、MS SQL-Server 等。

:::center
![](../assets/row-database.png)<br/>
图 9-13 行式数据库存储结构
:::
针对分析类的查询,通常只需要读取表的一小部分列。

与行式相对的是列式数据库,它们的数据是这样存储组织的,图 9-14 所示。

:::center
![](../assets/column-database.png)<br/>
图 9-14 列式存储的组织结构
:::
传统的行式数据库系统中,如 MySQL、Postgres,数据按如下顺序存储。

数据压缩的本质是通过一定的步长对数据进行匹配扫描,发现重复部分后进行编码转换。因此,数据中重复项越多,压缩率越高。在列式数据库中,由于同一列字段的数据具有相同的数据类型和语义,重复项的可能性自然更高。
<center >表 9-13 行式数据库存储结构</center>

|Row |WatchID |JavaEnable |Title| GoodEvent |EventTime|
|:--|:--|:--|:--|:--|:--|
| #0 | 89354350662 |1 |Investor Relations| 1 |2016-05-18 05:19:20|
| #1 | 90329509958 | 0| Contact us | 1 | 2016-05-18 08:10:20|
| #2 | 89953706054 | 1 | Mission| 1 | 2016-05-18 07:38:00| |
| #N | ...| ...| ...| ... | ...


行式数据库一张表中的一行内的所有数据在物理介质内是彼此相邻存储的。如果要进行查询,

```
SELECT sum(数量) FROM 表 WHERE product_id=1000
```

首先需要将所有行从磁盘加载到内存中,然后进行扫描和过滤(检查是否符合 where 条件),过滤出目标行之后,再判断是否有聚合函数,如有则执行相应的计算和排序,最终输出结果。整个流程可能需要非常长的时间。


在列式数据库系统中,数据按如下的顺序存储:

|Row:| #0 | #1 | #2 | #N|
|:--|:--|:--|:--|:--|
|WatchID:| 89354350662 |90329509958 |89953706054 |...|
|JavaEnable: |1 |0| 1 |...|
|Title: | Investor Relations | Contact us | Mission |...|
|GoodEvent: | 1| 1| 1| ...|
|EventTime: | 2016-05-18 05:19:20 |2016-05-18 08:10:20 |2016-05-18 07:38:00 |...|

可以看到,列式存储不是讲一行中的所有值存储在一起,而是将每列中的所有值存储在一起

在列式数据库中你可以只读取你需要的数据。例如,如果只需要读取100列中的5列,这将帮助你最少减少20倍的I/O消耗。

此外,列式存储和数据压缩通常是伴生的,数据压缩的本质是通过一定的步长对数据进行匹配扫描,发现重复部分后进行编码转换。因此,数据中重复项越多,压缩率越高。面向列式存储,同一列字段的数据具有相同的数据类型和语义,重复项的可能性自然更高。

近几年来,经常能在国内各个技术公众号看到关于列式数据库的实践分享,图 9-15 中的数据来源技术文章《B站基于Clickhouse的下一代日志体系建设实践》,文章中的数据表明 B 站使用 ClickHouse 降低了 60%+ 的存储成本[^2]

Expand All @@ -98,14 +148,13 @@ Loki 另外一个特点是对以 Kubernetes 为基座的系统十分友好。如
ClickHouse® is an open-source **column-oriented** database management system that allows generating analytical data reports in **real-time**.
:::

ClickHouse 另外一个特点是极致的向量化查询性能,从它的跑分结果来看(图 9-16),ClickHouse 比 Vertia(一款商业的 MPP 分析软件)快约 5 倍、比 Hive 快 279 倍、比 MySQL 快 801 倍。
根据 Yandex 的内部测试结果,ClickHouse 表现出了惊人的查询性能,从它的跑分结果来看(图 9-16),ClickHouse 比 Vertia(一款商业的 MPP 分析软件)快约 5 倍、比 Hive 快 279 倍、比 MySQL 快 801 倍。当之无愧阐述 ClickHouse 介绍中“实时”(real-time)二字含义,正如 ClickHouse 的宣传所言,其他的开源系统太慢、商用太贵,只有 ClickHouse 在成本与性能之间做到了良好平衡,又快还开源。


:::center
![](../assets/ClickHouse-benchmark.jpeg)<br/>
图 9-16 ClickHouse 性能测试 [图片来源](http://clickhouse.yandex/benchmark.html)
:::

ClickHouse 的查询速度当之无愧阐述“**real-time**”二字含义,正如 ClickHouse 的宣传所言,其他的开源系统太慢、商用太贵,只有 ClickHouse 在成本与性能之间做到了良好平衡,又快还开源。

[^1]: Elastic 的发展始于 Shay Banon 的个人兴趣,从开源、聚人、成立公司,到走向纽交所,再到股价一路狂飙(最新市值 $107 亿),几乎是最理想的工程师创业故事。
[^2]: 参见 https://mp.weixin.qq.com/s/dUs7WUKUDOf9lLG6tzdk0g
55 changes: 33 additions & 22 deletions Observability/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ Google 的 Borg 系统孕育出了 Kubernetes,Prometheus 的前身 —— Goog

## 1. 定义指标的类型

了方便用户使用和理解不同指标之间的差异,Prometheus 定义了四种不同的指标类型(Metrics Type)
为方便用户使用和理解不同指标之间的差异,Prometheus 定义了四种不同的指标类型:

- **Counter(计数器**: Counter 类型的指标其工作方式和计数器一样,初始为 0,只增不减(除非系统发生重置)。常见的监控指标如 http_requests_total、node_cpu 等都是 Counter 类型的监控指标。
- 计数器(Counter): Counter 类型的指标其工作方式和计数器一样,初始为 0,只增不减(除非系统发生重置)。常见的监控指标如 http_requests_total、node_cpu 等都是 Counter 类型的监控指标。
- **Gauge(仪表盘)**:与 Counter 不同,Gauge 类型的指标侧重于反应系统的当前状态,因此这类指标的样本数据可增可减。常见指标如 node_memory_MemFree(主机当前空闲的内容大小)、node_memory_MemAvailable(可用内存大小)都是 Gauge 类型的监控指标。
- **Histogram(直方图)**:观测采样统计分类数据,观测数据放入有数值上界的桶中,并记录各桶中数据的个数。典型的如延时在 `0~50ms` 的请求数,500ms 以上慢查询数,大 Key 数等。
- **Summary(摘要)**:聚合统计的多变量,跟 Histogram 有点像,但更有聚合总数的概念。典型的有有成功率、总体时延、总带宽量等。
Expand All @@ -38,13 +38,6 @@ Google 的 Borg 系统孕育出了 Kubernetes,Prometheus 的前身 —— Goog
图 9-5 Prometheus 定义的四种不同的指标类型
:::

如下,从一个 metrics 接口获取类型指标为 Counter 样本。
```bash
$ curl http://127.0.0.1:8080/metrics | grep http_request_total
# HELP http_request_total The total number of processed http requests
# TYPE http_request_total counter // 指标类型 类型为 Counter
http_request_total 5
```

## 2. 通过 Exporter 收集指标

Expand All @@ -64,6 +57,15 @@ http_request_total 5
Exporter 一个相对开放的概念,可以是一个独立运行的程序独立于监控目标以外,也可以是直接内置在监控目标中,只要能够向 Prometheus 提供标准格式的监控样本数据即可。
:::

如下,从一个 metrics 接口获取类型指标为 Counter 样本。
```bash
$ curl http://127.0.0.1:8080/metrics | grep http_request_total
# HELP http_request_total The total number of processed http requests
# TYPE http_request_total counter // 指标类型 类型为 Counter
http_request_total 5
```


Prometheus 相比 zabbix 这类传统监控系统,最大的特点是对指标全方位的收集:

- **宿主机监控数据**:Node Exporter 以 DaemonSet 的方式运行在宿主机,收集节点的负载、CPU、内存、磁盘以及网络这样的常规机器的数据。
Expand Down Expand Up @@ -92,15 +94,14 @@ Prometheus 相比 zabbix 这类传统监控系统,最大的特点是对指标

## 3. 存储指标

存储本来是一种司空见惯的操作,但如果是指标类型的数据,你需要换个思路来解决存储的问题。

举个例子,假设你负责一个小型的集群(只有 10 个节点),集群中运行一套微服务系统(30 个服务),每个节点要采集 CPU、内存、磁盘以及网络,每个服务要采集业务相关、中间件相关指标。这些累加在一起总共算 20 个指标,如果按 5 秒的频率采集,那么一天的数据规模是:
存储本来是一种司空见惯的操作,但如果是指标类型的数据,你需要换个思路来解决存储的问题。举个例子,假设你负责一个小型的集群(只有 10 个节点),集群中运行一套微服务系统(30 个服务),每个节点要采集 CPU、内存、磁盘以及网络,每个服务要采集业务相关、中间件相关指标。这些累加在一起总共算 20 个指标,如果按 5 秒的频率采集,那么一天的数据规模是:

```
10(节点)* 30(服务)* 20 (指标) * (86400/5) (秒) = 103,680,000(记录)
```

对于一个规模仅有 10 个节点的业务而言,一天的业务数据肯定远远达不到 1 亿条。构建监控系统,不可能让辅助性的数据称为成本负担。因为,指标数据不能再常规的思路/普通的数据库存储。
对于一个规模仅有 10 个节点的业务而言,`7*24` 小时不间断地生成数据,有时一天的数据量就超过 1 TB。虽然,你也可以用关系数据库或 NoSQL 数据库来处理时序数据,但这类数据库并没有充分利用时序数据的特点,需要源源不断投入更多的计算资源和存储资源来处理,系统的运营维护成本急剧上升。


回顾指标数据有什么特征?

Expand All @@ -116,24 +117,34 @@ Prometheus 相比 zabbix 这类传统监控系统,最大的特点是对指标
},
```

纯数字、具有时间属性,它们肯定也有关系嵌套、不用考虑主键/外键、不用考虑事务处理。
纯数字、具有时间属性,它们肯定也有关系嵌套、不用考虑主键/外键、不用考虑事务处理。对于这类基于时间,揭示其趋势性、规律性的数据,业界也发展出了专门优化的数据库类型 —— 时序数据库(Time-Series Database)。

时序数据库其实并不是一个新鲜的概念,追溯其历史,1999 年问世的 RRDtool 应该是最早的专用时序数据库。2015 年起,时序数据库逐步开始流行。现在,在排行网站 DB-engines 上面,时序数据库已成为流行度最高的数据库。与常规的关系数据库SQL相比,最大的区别在于,时序数据库是以时间为索引的规律性时间间隔记录的数据库。

- 时序数据库使用 LSM-Tree 来代替常规数据库中的 B+Tree。所有的写入操作,写入内存存储区(MemTable,通常是跳表或平衡树)。当 MemTable 满时,数据被批量写入磁盘文件中,虽然写磁盘文件延迟较高,但磁盘写入操作是批量进行的。


如图所示为一个时序数据库的显示形式,其索引为timestamp,后面不同的列记录了在当前时间戳下的属性值。随着时间增长,这种记录会周期性地增加。

:::center
![](../assets/tsdb.svg)<br/>
图 9-7 时序数据库结构
:::

其中 metric 表示为度量,也就是关系型数据库中的 table。data point 是数据点,也就是关系型数据库的 row,timestamp 为产生数据点的时间。而 field 是度量下会随着时间戳变化的属性值,tags 是附加信息,一般是跟时间戳关系不大的属性信息。

对于这类基于时间,揭示其趋势性、规律性的数据,业界也发展出了专门优化的数据库类型 —— 时序数据库(TSDB)。

:::tip 时序数据库
时序数据库具备秒级写入百万级时序数据的性能,提供高压缩比低成本存储、预降采样、插值、多维聚合计算、可视化查询结果等功能,解决由设备采集点数量巨大、数据采集频率高造成的存储成本高、写入和查询分析效率低的问题。
:::

默认情况下,Prometheus 将数据存储在本地 TSDB 中,并设定了默认的存储时限(15天),这种设计的理念基于“指标数据通常反映短期内的系统行为假设,而非长期/可靠分布式存储”。

Prometheus 也考虑了长期存储的场景,你可以通过它的远端存储扩展(Remote Read/Write API)将数据存储到任意第三方存储上。目前,社区已经涌现出大量适用于长期时序数据存储的解决方案,如 Thanos、VictoriaMetrics、SignalFx、InfluxDB 和 Graphite 等。

图 9-61 展示了 Prometheus 长期存储方案各个维度对比,读者可以根据对比,选择最适合自己的存储方案。

:::center
![](../assets/prometheus-storage.jpeg)<br/>
图 9-6 长期存储方案对比
:::

默认情况下,Prometheus 将数据存储在本地 TSDB 中,并设定了默认的存储时限(15天),这种设计的理念基于“指标数据通常反映短期内的系统行为假设,而非长期/可靠分布式存储”。

Prometheus 也考虑了长期存储的场景,你可以通过它的远端存储扩展(Remote Read/Write API)将数据存储到任意第三方存储上。目前,社区已经涌现出大量适用于长期时序数据存储的解决方案,如 Thanos、VictoriaMetrics、SignalFx、InfluxDB 和 Graphite 等。这些时序数据库一般具有更高的可用性、可扩展能力,笔者就不再一一介绍了。

## 4. 展示分析/预警

Expand Down
4 changes: 1 addition & 3 deletions architecture/ServiceMesh.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ ServiceMesh 之所以称为服务网格,是因为每台节点同时运行着
图 1-25 Kubernetes Pod 中 Sidecar 容器收集应用日志,并转发至日志后端
:::

相信你已经清楚服务网格不是什么黑科技,也没有什么耀眼的新技术。

服务网格本质是通过 iptables 劫持发送到应用容器的流量,将原本在业务层要处理的分布式技术问题,下沉到具有流控能力的 Sidecar 中处理,实现业务与非业务逻辑解耦的目的。
至此,相信你已经清楚服务网格不是什么黑科技,也没有什么耀眼的新技术。服务网格本质是通过 iptables 劫持发送到应用容器的流量,将原本在业务层处理的分布式通信治理相关的技术问题,下沉到具有流控能力的 Sidecar 中处理,实现业务与非业务逻辑解耦的目的。


[^1]: 参见 https://www.infoq.cn/news/2017/11/WHAT-SERVICE-MESH-WHY-NEED/
1 change: 1 addition & 0 deletions assets/tsdb.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"build": "vuepress build ."
},
"devDependencies": {

"katex": "^0.16.11",
"vuepress": "2.0.0-rc.0",
"vuepress-plugin-comment2": "2.0.0-rc.4",
"vuepress-plugin-md-enhance": "2.0.0-rc.4",
Expand All @@ -18,4 +18,4 @@
"dependencies": {
"vue-github-button": "3.1.0"
}
}
}

0 comments on commit 1050c94

Please sign in to comment.