总结:为了解决单节点存储的局限性,我们没有自行实现集群存储。 相反,我们提供了远程读写接口,并允许用户选择合适的时间序列数据库以实现可扩展性。 这实际上根本不关心另一端是什么样的时间序列数据库,如果您愿意,您可以创建自己的数据库。
概述
Prometheus提供本地存储,即tsdb时序数据库。 本地存储为Prometheus提供了简单高效的使用体验。 从prometheus 2.0开始,数据压缩功能也有了显着的提升。 单个节点即可满足大部分用户的监控需求。
但是本地存储也限制了Prometheus的扩展性,并引入了数据持久化等一系列问题。 为了解决单节点存储的局限性,prometheus本身并没有实现集群存储。 相反,它提供了远程读写接口,并允许用户选择合适的时序数据库来实现Prometheus的可扩展性。
Prometheus 1.x 版本的 TSDB(V2 存储引擎)基于 LevelDB,并使用与 Facebook Gorilla 相同的压缩算法,可以将 16 字节数据点压缩到平均 1.37 字节。
Prometheus 2.x版本引入了新的V3存储引擎,提高了写入和查询性能。
以下所有内容基于prometheus2.7版本
本地存储存储原理
Prometheus 2.按时间分块保存。 每个块由一个目录组成,该目录包含一个或多个块文件(用于存储时间序列数据)、元数据文件和索引文件(用于通过度量名称和标签在块文件中定位时间序列数据)。
最后写入的数据存储在内存块中,并在2小时后写入磁盘。 为了防止程序崩溃导致数据丢失,WAL(write[k一旦启动,4]ahead-log)机制通过写入日志(WAL)来恢复数据来实现重放。
当数据被删除时,删除的条目会记录在单独的逻辑删除文件中,而不是立即从块文件中删除。
将所有样本数据以时间窗口的形式存储,大大提高了Prometheus的查询效率。 如果要查询某个时间段内的所有样本数据,只需选择属于该范围内的块即可。 查询一下数据就可以了。
这些两小时的块在后台被压缩成更大的块。 数据被压缩并合并到上层块文件中,然后删除下层块文件。 这与leveldb、rocksdb等LSM树的思想是一致的。
这些设计与Gorilla非常相似,所以Prometheus大致相当于一个缓存的TSDB。 本地存储的特点决定了它不能用于长期数据存储,只能用于短期窗口内的时序数据存储和查询,且可用性不高(有可能因宕机而导致历史数据丢失) )。 有)。 难以辨认)。
当内存中的块数据没有写入磁盘时,wal文件主要存储在块目录中:
./data/01BKGV7JBM69T2G1BGBGM6KB12./data/01BKGV7JBM69T2G1BGBGM6KB12/meta.json。 /data /01BKGV7JBM69T2G1BGBGM6KB12/wal/000002./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000001
删除持久块目录下的wal文件,时间序列数据保存在chunk文件中。 Index 用于索引 wal 文件中时间序列的位置。
./data/01BKGV7JC0RY8A6MACW02A2PJD./data/01BKGV7JC0RY8A6MA0RY 8A6MACW02A2PJD/tombstones
存储配置
对于本地存储,prometheus主要提供了几个配置项:
--storage.tsdb.path:保存数据的目录。 默认为数据/。 如果要挂载外部存储,可以指定此目录。
--storage.tsdb.retention.time:数据过期清理时间。 默认值为 15 天。
--storage.tsdb .retention.size:实验性的,声明不包括wal文件的数据块最大大小,如512MB
-- storage.tsdb .retention:已被放弃。 使用存储代替。 tsdb.retention.time
Prometheus 将所有当前使用的块保留在内存中。 此外,最近使用的块保存在内存中,并且可以通过 storage.local.memory-chunks 标志设置最大内存。
监控当前使用的内存量:
prometheus_local_storage_memory_chunks
process_resident_memory_bytes
监控当前使用的存储指标:
监控当前使用的存储指标。 p>
prometheus_local_storage_memory_series:当前时间序列持有的内存块数量
prometheus_local_storage_memory_chunks:内存中当前持久化块的数量
prometheus_local_storage_chunks_to_persist:当前仍需要持久化到磁盘的内存块的数量
prometheus_local_storage_persistence_urgency_score:紧急程度评分
存储prometheus 2.0 升级
Prometheus 2.0 于 2017 年-11-08 发布,主要是由于存储引擎的优化。
整体性能提升:
20% - CPU 使用率相比 Prometheus 1.8 降低了 40%
Prometheus 1.8 与磁盘空间使用率相比有所降低到 33% - 50%
查询较少,平均负载磁盘 I/O 为 <1%
在 Kubernetes 集群等动态环境中,prometheus 数据平面通常看起来像这样
垂直维度代表所有存储的序列
水平维度代表样本传播的时间。
示例:
requests_total{path=“/status”,method=“GET”,instance=“10.0.0.1:80”}requests_total{path=“/status”,method=“POST”,instance=“10.0 .0.3:80”} requests_total{path="/", method="GET", instance="10.0.0.2:80"}
Prometheus 定期收集所有系列的新数据点。 意味着它必须垂直书写在时间线的右端。 然而,在查询时,您可能想要访问平面上的任意区域。矩形(各种标签条件)
因此需要索引来高效地从大量数据中找到查询序列。
Prometheus 1.x 存储层可以很好地处理垂直写入模式,但随着扩展,索引可能会出现问题,因此 2.0 版本重新设计了存储引擎和索引。 主要改进是:
样本压缩
现有存储层的样本压缩特性在Prometheus早期版本中发挥了重要作用。 单个原始数据点占用16字节的存储空间。 但是,当 Prometheus 每秒收集数十万个数据点时,您的硬盘很快就会被填满。
但是,同一系列的样本非常相似,因此使用此类样本(相同标签)可以进行有效的压缩。 批量压缩内存中许多样本的一系列块,将每个数据点压缩到平均 1.37 字节的存储空间。
这种压缩方案效果很好,并且在新的版本 2 存储层设计中得到了维护。 具体压缩算法请参见:Facebook的“Gorilla”论文
分时
新的存储层对块进行分割。 每个块都包含一切。 一段时间内的序列。 每个块充当一个独立的数据库。
这样,对于每个查询,只检查请求时间范围内的块子集,自然减少了查询执行时间。
这种布局还使得删除旧数据变得非常容易(这在 1.x 存储设计中是一项耗时的操作)。 然而,在2.x中,如果一个块的时间范围完全低于设定的保留边界,则该块可能会被永久丢弃。
索引
典型的 Prometheus 查询使用指标和标签作为关键字,非常全面且完整。 由于自定义字符,您无法使用常规 SQL 数据库。 Prometheus的存储层使用倒排索引的概念进行全文搜索,将每个时间序列视为一个小文档。 以及公制和实验室el 对应文档中的一个单词。
例如,requests_total{path="/status",method="GET",instance="10.0.0.1:80"} 是一个包含以下单词的文档:
__name__= "requests_total"
path="/status"
method="GET"
instance="10.0.0.1 :80"
基准测试
与 1.x 版本相比,CPU、内存和查询效率有了显着改进。
具体测试结果参考:https://dzone.com/articles/pr...
灾难恢复
数据库损坏是问题所在如果您认为是这个原因,你可以配置你的数据库存储。 .local.dirtyflag 设置。 启动服务器并强制其从崩溃中恢复。
如果问题仍然存在,或者您想删除现有数据库,您可以通过删除存储目录的内容来轻松启动数据库。
1.停止服务:停止prometheus。
p>
2.删除数据目录:rm -r /*
3.启动服务:start prometheus
Remote存储
Prometheus默认有自己的存储,保留期为15天。 但本地存储也意味着Prometheus无法持久化数据、无法存储大量历史数据、无法弹性伸缩。
为了保证Prometheus的简单性,Prometheus并没有从自己的集群角度来解决这些问题。 相反,定义了两个接口:remote_write/remote_read来抛出数据并自行处理。
Prometheus中的Remote_storage实际上是一个适配器。 关于适配器您根本不关心 r 的另一端有什么样的时间序列数据库,如果您愿意,您可以编写自己的适配器。
示例:存储方式为:Prometheus —- 发送数据 —- > Remote_storage_adapter —- 存储数据 —-> influxdb。
Prometheus通过两种方式实现与其他远程存储系统的对接:
Prometheus 以标准格式将指标写入远程存储。
Prometheus 使用标准格式的远程 URL
远程读取
远程读取过程在用户发起时使用远程 URL查询请求,Promthues向配置了remote_read的URL发起查询请求(matchers、ranges),适配器根据请求条件从第三方存储服务中检索响应数据。 同时将数据转化为Prometheus原始样本数据返回到Prometheus Server。
获取样本数据后,Promthues 使用 PromQL 在本地处理样本数据。
远程写入
用户可以在Promtheus配置文件中指定远程写入URL地址。 设置此配置项后,Prometheus 通过 HTTP 发送样本数据。 到适配器。 用户可以连接到适配器内的任何外部服务。 外部服务可以采取任何形式,例如实际的存储系统、公共云存储服务或消息队列。
配置
配置非常简单。 只需设置相应的地址即可。
remote_write: - url: "http://localhost:9201 /write"remote_read: - URL: "http://localhost:9201/read"
社区支持
社区目前正在实施以下远程存储解决方案:
AppOptics:写入
Chronix:写入
Cortex:读写
CrateDB:读写
Elasticsearch:写入
Gnocchi:写入
Graphite:写入
InfluxDB:读取和写入
OpenTSDB:写入
PostgreSQL/TimescaleDB:读取和写入
SignalFx:写入
可以使用InfluxDB进行全读写。使用多个prometheus服务器同时远程读写,为InfluxDB创建完整的速度生态系统
容量规划
正常情况下,Prometheus中存储的每个样本大约为1-2字节,如果需要规划Prometheus Server的本地磁盘空间,可以使用以下公式计算:
磁盘大小 = 保留时间 * 每秒采集的样本数 * 样本大小
保留时间(retention_time_seconds)和样本大小(bytes_per_sample)保持不变,以减少本地磁盘空间需求。减少每秒采集的样本数 (ingested_samples_per_second)。
有两种方法可以实现此目的:减少时间序列的数量,或增加采集的样本数的时间间隔。
当考虑到 Prometheus 压缩时间序列时,减少时间序列数量的效果变得更加明显。b>
远程读写解决Promtheus中的数据持久化问题。 使其具有弹性可扩展性。 此外,它还支持联邦集群模式,解决了水平扩展和网络分区的问题(例如将A+B+C区域的监控数据整合到D区域)。 以下 Promthues 高可用性文章详细介绍了配置联合集群: 。
附件:kubecon2018上谈论Prometheus 2.0的帅哥
还有专门介绍Prometheus的书籍:Prometheus: Up & Running(等等) 600页....)
我在中国找不到有卖的,但我确实找到了一份英文PDF。 今天它仍然被翻译和理解。 新内容将在本系列博客中持续同步。
。 。 。 我找到了另一本书:https://www.prometheusbook.com/
参考文献:
https://prometheus.io/docs/pr。 ..
https://coreos.com/blog/prome...
https://dzone.com/articles/pr...
https://www.linuxidc.com/Linu...
http://ylzheng.com/2018/03/06...
https://www .cnblogs.com/vovli...
https://files-cdn.cnblogs.com...
https://www.bookstack.cn/ 阅读...
本文是关于容器监控实践的系列文章。 请参阅container-monitor-book
了解完整内容。
评论前必须登录!
注册