普罗米修斯存储监控
1 Prometheus储存瓶颈
1.1 本地存储的优势
使用本地存储可以降低Prometheus部署和管理的复杂度同时减少高可用(HA)带来的复杂性。在默认情况下,用户只需要部署多套Prometheus,采集相同的Targets即可实现基本的HA。同时由于Promethus高效的数据处理能力,单个Prometheus Server基本上能够应对大部分用户监控规模的需求。
1.2 本地存储的缺点
当然本地存储也带来了一些不好的地方,首先就是 数据持久化 的问题,特别是在像Kubernetes这样的动态集群环境下,如果Promthues的实例被重新调度,那所有历史监控数据都会丢失。 其次本地存储也意味着Prometheus不适合保存大量历史数据(一般Prometheus推荐只保留几周或者几个月的数据)。
本地存储也导致Prometheus无法进行弹性扩展。为了适应这方面的需求,Prometheus提供了 remote_write 和 remote_read 的特性,支持将数据存储到远端和从远端读取数据。通过将监控与数据分离,Prometheus能够更好地进行弹性扩展。
除了本地存储方面的问题,由于Prometheus基于Pull模型,当有大量的Target需要采样本时,单一Prometheus实例在数据抓取时可能会出现一些性能问题,联邦集群的特性可以让Prometheus将样本采集任务划分到不同的Prometheus实例中,并且通过一个统一的中心节点进行聚合,从而可以使Prometheuse可以根据规模进行扩展。
2 Prometheus本地存储
2.1 Prometheus本地存储简介
Prometheus的本地存储被称为Prometheus TSDB,目前是V3版本,根据官方介绍其有着非常高效的时间序列数据存储方法,每个采样数据仅占3.5byte左右空间,上百万条时间序列,30s间隔,保存60天,仅占200多G空间
默认情况下,Prometheus将采集到的数据保存在本地的TSDB数据库中,默认目录为Prometheus安装目录下的data目录。数据写入过程为先把数据写入wal日志并放在内存中,然后2个小时后将内存数据放入一个新的block块,同时再把新的数据写入内存并在2小时后再保存至一个新的block块,依次类推
这里涉及到两个组成部分:block和wal
2.2 block
Prometheus TSD将存储的监控数据按时间分割为block,block的大小并不固定,默认最小的block保存2h的数据,随着数据量的不断增加,TSDB会将小的block合并为大的block,例如将3个2h的block合并为一个6h的block,这样不仅可以减少数据存储,还可以减少block个数,便于对数据进行检索。
在实际存储中,block就是Prometheus TSDB数据目录下那些以01开头的存储目录,如下图:
block主要包含4个部分:chunks、index、meta.josn、tombstones,如下图:
1、chunks
chunks主要用于保存压缩后的时序数据。每个chunk的大小为512M,如果超过,则会被分割为多个chunk保存,且以数字编号命名
2、index
index是为了对时序数据进行快速检索和查询而设计,主要用来记录chunk中时序的偏移位置
3、meta.json
meta.json记录block的元数据信息,主要包括一个数据块记录样本的起始时间、截至时间、样本数、时序数和数据源等信息,这些元数据信息在后期对block进行维护(删除过期block、合并block等)时会用到。
4、tombstones
tombstones用于对数据进行软删除。TSDB在删除block数据块时会将整个目录删除,但如果只删除一部分数据块的内容,则可以通过 tombstones进行软删除
这些block按照时间顺序被分割为一个个block,其中第一个block被称为head-block,它被存储在内存中并且允许修改,而后面的block以只读的方式存储在硬盘中。如下图:
head-block和后面的block都被初始设定为保存2h的数据,当head-block超过1.5倍大小(3h)的时候,它将被重新分割成2h和1h两部分,前面一部分变为只读块被保存到硬盘中。
2.3 WAL
WAL(write-ahead logging,预写日志)是关系型数据库中利用日志来实现事务性和持久性的一种技术,即在进行某个操作之前先将这件事情记录下来,以便之后对数据进行回滚、重试等操作并保证数据可靠性。
Prometheus为了防止丢失暂存在内存中的还未被写入磁盘的监控数据’、引入了WAL机制。WAL被分割为默认大小为128M的文件段,文件段以数字命名,例如00000001、00000002等,以此类推。
按照每种对象设定的采集周期,Prometheus会将周期性采集的监控数据先写入head-block中,但这些数据没有被持久化,TSDB通过WAL将提交的数据先保存到磁盘中,在TSDB宕机重启后,会首先启动多协程读取WAL,从而恢复之前的状态。
另外从Prometheus v2.19.0开始,Prometheus引入了内存映射,将head-block中已填充的完整的chunk,刷新到磁盘(即保存在chunks_head目录下的数据)并从磁盘进行内存映射,同时仅将引用存储在内存中。通过内存映射,可以在需要时使用该引用将chunk动态加载到内存中。这是操作系统提供的功能。通过引入内存映射,减少了Prometheus的内存消耗,虽然填充完毕的chunk会被刷到磁盘上,但是对于该部分的操作预写入日志不会被删除,直到该chunk所属的block完整落盘
2.4 本地存储配置参数
--storage.tsdb.path #指定数据保存位置
--storage.tsdb.retention.time #指定数据保存时间,默认15d
--storage.tsdb.retention.size #指定block可以保存的数据大小
--query.timeout #最大查询超时时间,默认2m
--query.max-concurrency #最大查询并发数,默认20
3 Prometheus远端存储
Prometheus的本地存储设计可以减少其自身运维和管理的复杂度,同时能够满足大部分用户监控规模的需求。但是本地存储也意味着Prometheus无法持久化数据,无法存储大量历史数据,同时也无法灵活扩展和迁移。
为了保持Prometheus的简单性,Prometheus并没有尝试在自身中解决以上问题,而是通过定义两个标准接口(remote_write/remote_read),让用户可以基于这两个接口对接将数据保存到任意第三方的存储服务中,这种方式在Promthues中称为Remote Storage。
3.1 Remote Write
在Prometheus配置文件中指定Remote Write(远程写)的URL地址,一旦设置了该配置项,Prometheus将采集到的样本数据通过HTTP的形式发送给适配器(Adaptor)。而用户则可以在适配器中对接外部任意的服务。外部服务可以是真正的存储系统,公有云的存储服务,也可以是消息队列等任意形式。
3.2 Remote Read
如下图所示,Promthues的Remote Read(远程读)也通过了一个适配器实现。在远程读的流程当中,当用户发起查询请求后,Promthues将向remote_read中配置的URL发起查询请求(matchers,ranges),Adaptor根据请求条件从第三方存储服务中获取响应的数据。同时将数据转换为Promthues的原始样本数据返回给Prometheus Server。
当获取到样本数据后,Promthues在本地使用PromQL对样本数据进行二次处理。
注意:启用远程读设置后,只在数据查询时有效,对于规则文件的处理,以及Metadata API的处理都只基于Prometheus本地存储完成。
3.3 配置文件
Prometheus配置文件中添加 remote_write 和 remote_read 配置,其中url用于指定远程读/写的HTTP服务地址。如果该URL启动了认证则可以通过 basic_auth 进行安全认证配置。对于https的支持需要设定 tls_concig。proxy_url 主要用于Prometheus无法直接访问适配器服务的情况下。
3.4 官网支持的存储方式
上一篇: 数据结构 - 堆栈和队列实现(完整代码)
下一篇: LARA:多语言多轮对话意图分类的新突破