嘉宾 | 霍秉杰 整理 | 西京刀客 出品 | CSDN 云原生
Prometheus 作为云原生时代崛起的标志性项目,已经成为可观测领域的事实标准。Prometheus 是单实例不可扩展的,那么如果用户需要采集更多的数据并且保存更长时间该选择怎样的长期存储方案呢?
2022 年 8 月 9 日,在 CSDN 云原生系列在线峰会第 15 期“Prometheus 峰会”上,青云科技可观测与函数计算负责⼈霍秉杰分享了《Prometheus Long-Term Storage:海纳百川,有容乃大》。

云原生时代崛起的 Prometheus 已经在可观测领域得到了广泛应用,其影响力远远超出了云原生的范畴,具有两个显著特点。
Prometheus 的作者及社区核心开发者都秉承一个理念:Prometheus 只聚焦核心的功能,扩展性的功能留给社区解决,所以 Prometheus 自诞生至今都是单实例不可扩展的。
这对于很多从大数据时代走过来的工程师而言有点不可思议,大数据领域的很多开源项目比如 Elasticsearch、HBase、Cassandra 等无一不是多节点多角色的设计。
Prometheus 的核心开发者曾这样解释,Prometheus 结合 Go 语言的特性和优势,使得 Prometheus 能够以更小的代价抓取并存储更多数据,而 Elasticsearch 或 Cassandra 等 Java 实现的大数据项目处理同样的数据量会消耗更多的资源。也就是说,单实例、不可扩展的 Prometheus 已强大到可以满足大部分用户的需求。
Prometheus 倡导用 Pull 模式获取数据,即 Prometheus 主动地去数据源拉取数据。对于不便于 Pull 的数据源,Prometheus 提供了 PushGateway 进行处理,但 PushGateway 在部分应用场景上存在限制。
尽管单实例的 Prometheus 已经足够强大,但还是存在部分需求是其无法满足的,如跨集群聚合、更长时间的存储等。为了扩展 Prometheus,社区给出了多种方案。

在 Prometheus 长期存储出现之前,用户若需要跨集群聚合计算数据时,社区提供 Federation 方式实现。
在多个 Prometheus 实例的上一层有一个 Global Prometheus,它负责在各个实例中抓取数据并进行计算,以此解决跨集群聚合计算的问题。但如果各个集群的数据量较大,单实例的 GlobalPrometheus 也会遇到瓶颈。

2017 年,Prometheus 加⼊ Remote Read/Write API,自此之后社区涌现出大量长期存储的方案,如 Thanos、Grafana Cortex/Mimir、VictoriaMetrics、Wavefront、Splunk、Sysdig、SignalFx、InfluxDB、Graphite 等。
接下来我们将挑选几个主流的 Prometheus 长期存储方案进行对比分析。

M3 是 Uber 开源的一个 Prometheus 长期存储的方案,它的组件主要包括 M3 Coordinate、M3 Queries、M3 Aggregator 及 M3DB。
M3 的工作原理是 Prometheus 将数据通过 M3 Coordinate Remote 写入至 M3DB 中,M3 Queries 可直接对接 M3DB 进行查询。M3Aggregator 对接收数据进行实时聚合,降采样后存入 M3DB。
M3 是 Uber 为了满足自身海量数据需求所开发的 Prometheus 长期存储的方案,其缺点是部署麻烦,且社区也不活跃、文档欠佳。
VictoriaMetrics 是一个开源的 Prometheus 长期存储项目,除开源项目外,还有商业化的产品和服务。VictoriaMetrics 的采用者包括知乎、Grammarly、fly.io、CERN 等。

VictoriaMetrics 主要由三个组件构成:接入数据的 vminsert、存储数据的 vmstorage 以及查询数据的 vmselect。
vminsert 和 vmselect 都是无状态的,可以通过增加副本的方式进行扩展。
vmstorage 虽然是有状态的,但也可以扩展,当数据量超过一个副本的存储量时,可以通过增加另外一个副本对其进行扩展。

VictoriaMetrics 的 Agent 功能较为强大,主要体现在以下几方面:

VictoriaMetrics 还有一个单独的用于告警的组件——VictoriaMetrics Alert,它具备两个功能:

另一个组件是 VictoriaMetrics Gateway,它主要有两个功能:
VictoriaMetrics 还有其他的组件比如 vmauth、vmbackup/vmrestore、vmbackupmanager、vmanomaly 等。
值得一提的是,VictoriaMetrics 并不是所有功能都是开源的,未开源的企业版功能包括:
Thanos 由 Improbable 开源,是社区最先出现的 Prometheus 长期存储方案,采用者包括 Adobe、字节、eBay、腾讯等。
Thanos 在架构上较为创新,具有诸多较为独特的功能:
Thanos 有两种模式,Sidecar 模式和 Receive 模式。
Thanos Sidecar 模式

ThanosSidecar 模式是 Thanos 最早支持的模式,其原理是:
Thanos Receive 模式

Thanos Receive 模式是 Thanos 响应社区用户 Remote Write 的需求新增的模式,其原理是:
Cortex 由 Grafana 开源,Loki、Tempo、Grafana Cloud 等产品或项目都采用了 Cortex 的技术。采用者包括 AWS、Digital Ocean、Grafana Labs、MayaData、Weaveworks 等。
Cortex 最初是基于 Chunk Storage 的版本,因部署运维起来较为复杂且依赖 Cassandra 或 DynamoDB 存储元数据,已经确定被弃用,改为基于 Block Storage 的版本。

受 Thanos 的启发,Cortex 新架构采用 Block Storage。我们可以看到,Cortex 新架构的 distributor、ingester、querier、ruler、store-gateway、compactor 都与 Thanos 类似,其中 ruler、store-gateway、compactor 都借鉴自 Thanos。

Grafana Mimir 是 Grafana Lab 于 2022 年 3 月底以 AGPL v3 协议新发布的开源项目。
从 Mimir 发布的 Blog Announcing Grafana Mimir 可以看出,Grafana Mimir 在 Fork 了 Cortex 项目之后增加了许多企业级功能,被用于 Grafana Cloud 及服务 Grafana 的企业客户的产品 Grafana Enterprise Metrics(GEM)。这么做的主要原因是 Grafana Lab 认为 Cortex 被一些 ISV 或云厂商用于给自己的客户提供服务,却没有像 Grafana Lab 一样贡献代码,于是将越来越多的功能放到了 Cortex 的 Fork Mimir 中。
作为 Cortex 的增强版,之前很长一段时间 Mimir 是未开源的状态,但这与 Grafana Lab 的开源文化相悖,于是为了兼顾开源和自己的商业利益,Grafana Lab 将 Mimir 在 AGPL v3 下开源。

由于 Grafana Mimir Fork 了 Cortex,所以其架构和 Cortex 及 Thanos 非常相似。
虽然 Grafana Mimir 同样借鉴了 Thanos 的 store-gateway、compactor 和 ruler,但与 Cortex 不同之处在于 querier 和 query frontend 之间加了一个额外的组件 query scheduler,更好地满足了查询组件的可扩展性。
Mimir 各组件(包括 compactor、store-gateway、query、ruler 等)的水平可扩展性较好,值得一提的是 Mimir 对 Alertmanage 做了多租户和水平扩展的支持。


我们可以基于多维度对上述介绍的 Prometheus 长期存储方案进行横向对比:
综上,我们可以得出以下结论。
本文由博客一文多发平台 OpenWrite 发布!
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.
我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于
我正在关注Hartl的railstutorial.org并已到达11.4.4:Imageuploadinproduction.我做了什么:注册亚马逊网络服务在AmazonIdentityandAccessManagement中,我创建了一个用户。用户创建成功。在AmazonS3中,我创建了一个新存储桶。设置新存储桶的权限:权限:本教程指示“授予上一步创建的用户读写权限”。但是,在存储桶的“权限”下,未提及新用户名。我只能在每个人、经过身份验证的用户、日志传送、我和亚马逊似乎根据我的名字+数字创建的用户名之间进行选择。我已经通过选择经过身份验证的用户并选中了上传/删除和查看权限的框(而不
我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject
我有一个应用程序正在从Ruby迁移到JRuby(由于需要通过Java提供更好的Web服务安全支持)。我使用的gem之一是daemons创建后台作业。问题在于它使用fork+exec来创建后台进程,但这对JRuby来说是禁忌。那么-是否有用于创建后台作业的替代gem/wrapper?我目前的想法是只从shell脚本调用rake并让rake任务永远运行......提前致谢,克里斯。更新我们目前正在使用几个与Java线程相关的包装器,即https://github.com/jmettraux/rufus-scheduler和https://github.com/philostler/acts
我以为它们存储在cookie中-但不,检查cookie没有任何结果。session也不存储它们。那么,我在哪里可以找到它们?我需要这个来直接设置它们(而不是通过flashhash)。 最佳答案 它们存储在inyoursessionstore.自rails2.0以来的默认设置是cookie存储,但请检查config/initializers/session_store.rb以检查您是否使用默认设置以外的东西。 关于ruby-on-rails-闪存消息存储在哪里?,我们在StackOverf
对于我正在编写的Rails3应用程序,我正在考虑从本地文件系统上的XML、YAML或JSON文件中读取一些配置数据。重点是:我应该把这些文件放在哪里?Rails应用程序中是否有用于存储此类内容的默认位置?附带说明一下,我的应用程序部署在Heroku上。 最佳答案 我经常做的是:如果文件是通用配置文件:我在目录/config中创建一个YAML文件,每个环境有一个上层key如果我为每个环境(大项目)创建一个文件:我为每个环境创建一个YAML并将它们存储在/config/environments/然后我在加载YAML的地方创建了一个初始化
有没有办法将RubyVM::InstructionSequence存储到文件中并稍后读取?我尝试了Marshal.dump但没有成功。我收到以下错误:`dump':no_dump_dataisdefinedforclassRubyVM::InstructionSequence(TypeError) 最佳答案 是的,有办法。首先,您需要使InstructionSequence的load方法可访问,默认情况下该方法是禁用的:require'fiddle'classRubyVM::InstructionSequence#RetrieveR