10倍性能提升-SLS Prometheus 时序存储技术演进

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
可观测监控 Prometheus 版,每月50GB免费额度
简介: 本文将介绍近期SLS Prometheus存储引擎的技术更新,在兼容 PromQL 的基础上实现 10 倍以上的性能提升。同时技术升级带来的成本红利也将回馈给使用SLS 时序引擎的上万内外部客户。

可观测近年来一直是非常火热的话题,围绕着可观测国内外诞生了非常多的创业公司,包括老牌的监控、APM、日志厂商也纷纷进入,追求在一个产品上同时支持日志、监控、Trace等多种可观测能力。


回归到可观测概念的本质,是针对各类海量数据(Log/Trace/Metric...)进行的业务创新。而支撑数据创新的核心是一套稳定、强大、普惠的存储计算引擎。


相比业界使用多套方案(例如日志用ES、Trace用ClickHouse、Metric用Prometheus)实现统一的可观测上层能力,SLS则从数据引擎层开始针对所有可观测数据进行统一的架构设计。因此,我们在2018年在Log模型的基础上,发布第一版的PromQL语法支持,验证了PromQL的可行性。随后对存储引擎进行重新设计,能够在一套架构、一个进程内实现对Log/Trace/Metric的统一存储。

image.png

SLS时序引擎正式对外收费3年多来,我们对时序的整体架构进行了多次升级,本文将介绍近期SLS Prometheus存储引擎的技术更新,在兼容 PromQL 的基础上实现 10 倍以上的性能提升。同时技术升级带来的成本红利也将回馈给使用SLS 时序引擎的上万内外部客户。


技术挑战

在上篇的文章《拥抱云原生-SLS支持Prometheus协议》中,我们介绍了SLS针对Prometheus时序场景的一些技术方案,包括:

  1. 存储层针对时序场景优化格式,减少IO数量和压缩率
  2. 在SLS集群Hold Prometheus计算引擎,用户不需要自己准备计算资源
  3. 存储和计算层使用时序格式进行数据传输,提升传输效率

同时借助SLS纯分布式、存储计算分离架构的能力,Prometheus计算性能相比原生Prometheus能够支撑更大的数据规模,包括对于时间线膨胀问题也可以完美解决。

但随着越来越多的客户和大规模场景应用(例如超大规模K8s集群监控、高QPS业务平台告警、大规模指标训练等),众多业务方的整体写入、查询量级越来越大,对SLS 时序存储的整体性能和资源消耗提出了更高的要求:

  1. 快:数据规模超大的情况下,也能让点查的QPS足够高,同时范围查询的延迟进一步降低;
  2. 简:使用上更加简单,不需要过多的手动优化,例如HashKey聚合写入、手动降采样、跨Store数据汇总等;
  3. 省:降本增效同时进行,希望成本能够进一步下降,快的同时能够再省省;

为此我们近一年来对Prometheus时序引擎的整体方案进行了多轮优化,实现查询十倍性能提升的同时,还能让整体成本更低。


SLS 时序引擎技术升级

更智能的聚合写入

image.png

由于时序数据具有高度的聚合特性,同一时间线的数据存储在一起会具备超高的压缩效率,因此在写入时,如果能够将相同时间线的数据放到同一Shard存储,无论是存储效率还是读取效率都会有较大提升。


最开始阶段,我们要求用户使用SLS的Producer在客户端按照时间线进行聚合,再指定Shard Hash Key写入到特定的Shard,这种方式对于客户端的计算和内存要求较高,对于RemoteWrite、iLogtail等方式不具备使用条件。而当前线上使用iLogtail、RemoteWrite、数据分发场景比例越来越高,导致SLS集群整体的资源效率变低。


为此我们在SLS网关侧实现了一个可以针对所有MetricStore的聚合写入方案,客户端无需使用SDK聚合(当然不影响当前SDK侧聚合写入的场景),数据随机写入到一个SLS的网关节点,网关内部会进行自动聚合,保证一条时间线的数据存储在一个Shard上。相比客户端的SDK聚合写入,优劣比较如下:


image.png

从上表可以看出,SLS网关侧聚合写入只有在特定查询策略下,相比客户端SDK控制会有一定的劣势,但此种情况只有少数对QPS要求超高(例如每秒上万查询QPS)的用户有效,绝大部分场景全局查询并不影响性能。


盯屏救星:全局Cache


image.png


时序场景的一个重要应用,同时也是对查询压力最大的场景是Dashboard,尤其是压测、大促、故障排查场景,顺时会有多位同学同时发起针对某个Dashboard的访问。多人访问热点的问题,大家想到的第一点一定是Cache,但在PromQL中,每次发起请求都有可能精确到秒或毫秒,而且PromQL的逻辑也会使每一个Step的计算都会从请求的精确时间进行数据查找,如果直接缓存计算结果,即使1秒内同时发起的请求也很难直接命中。


为此我们尝试使用Step对齐的方式,把PromQL查询的Range按照Step进行对齐,这样内部的结果每个Step都可以复用,可以大大提高缓存的命中效果。整体策略如下:

  1. 用户请求进入到任意一个计算节点时,若启动了Cache Feature,会根据Step进行Range修正;
  2. 以修正后的Range访问SLS Cache Server,获取命中的Cache Range;
  3. 对于没有命中的Range,向SLS后端查询数据并进行计算;
  4. 拼接结果返回给客户端,同时将增量的计算结果更新到Cache中;
  • 需要注意的是,这种方式相比标准的PromQL行为有一定的修改(只是会做Range对齐,其他计算逻辑没有修改),实际测试中Range是否对齐对于结果趋势几乎没有影响。我们在MetricStore的配置中,同时支持按照MetricStore开启或按需开启(请求的URL Param控制,例如)。


PromQL也可以分布式并行计算


image.png

在开源的Prometheus中,对于PromQL的计算是完全单机、单协程的,这种方式在一些小型企业场景中较为试用。当集群变大时,参与计算的时间线会剧烈膨胀,这时单机、单协程的计算完全无法满足需求(通常对于一个几十万的时间线,查询几小时都会有十多秒的延迟)。


为此我们在PromQL的计算逻辑上,引入了一层并行计算架构,将大部分的计算量分布到Worker节点,Master节点只做最终的结果聚合,同时计算并发数和Shard数解耦,存储和计算都可以独立缩扩容。整体的计算逻辑如下:

  1. 用户请求进入到任意一个计算节点时,会根据一些策略(例如Query是否支持、用户指定开起、历史查询时间线较多等)决定是否使用并行计算;
  2. 若判断使用并行计算,则这个计算节点升级为Master(虚拟角色),将Query进行并行拆分;
  3. Master节点将子Query发送到其他Worker节点(虚拟角色)执行;
  4. Worker节点执行子Query并将结果返回给Master;
  5. Master最终汇总所有结果并进行最终的结果计算;
  • 受限于PromQL的特性,并不是所有的Query都支持并行计算,也并不是所有支持并行计算的Query都能得到很好的效果。但我们分析了实际线上的请求,90%以上都能支持且得到加速。


极致性能:计算下推

image.png

上述并行方案解决了计算并发度的问题,但对于存储节点而言,无论是单机还是并行,发送到计算节点的数据量并没有变化,序列化、网络传输、反序列化的开销并没有消失,反而并行计算方案还会稍多了一些开销,因此对于整体集群的资源消耗并没有本质上的变化。同时,我们针对当前SLS存储计算分离架构下的Prometheus性能进行分析,其中绝大部分的开销都在PromQL计算、Golang GC和反序列化处。


为此我们开始尝试,能否把部分的PromQL下推到SLS的Shard上去做计算,将Shard当做是Prometheus Worker。下推计算部分的选择也有两种:

  1. 使用标准的Prometheus Golang计算引擎,支持的Query最丰富,但还是避免不了序列化、反序列化开销;
  2. 使用C++实现Prometheus的部分算子,直接在C++侧执行,避免序列化/反序列化的同时,还可以减少GC开销;

相比之下,方案2可以得到更优的效果,但可能工作量较大。为此我们再次分析了线上所有用户的Query,发现80%+场景下使用的都是有限的几种常见Query,相对实现代价很低。因此最终我们选择方案2:手写一个支持常见算子的C++  PromQL Engine(性能对比参见后文)。

  • 需要注意的是,计算下推的前提是同一时间线的数据必须存储在一个Shard上,即需要开启聚合写入的功能或者使用SDK手动写入。


计算下推和并行计算方式的优劣对比如下:

image.png


万众期待的内置降采样

image.png


在时序场景下,通常长期的指标存储都是为了看整体趋势,如果还是保存全量的高精度指标,相对会有较多的成本开销,因此通常都会将指标数据进行降采样(降低指标精度)存储。SLS之前的方案还是偏手动方式:

  1. 用户使用ScheduledSQL功能,定期查询原始指标库,保留最新的/平均值作为降采样的值,存储在新的MetricStore;
  2. 查询时,判断查询区间适合的MetricStore,如果是降采样的MetricStore,在查询前还需进行一定的Query改写;
  1. 例如降采样的精度是10min,查询是 avg(cpu_util),由于默认是3分钟的LookBackDelta,10分钟的精度可能查询不出来,因此需要改成 avg(last_over_time(cpu_util[15m]));


这种方式无论从配置还是使用来讲,门槛非常高,需要有专业的研发来参与才有可能完整。因此我们在SLS后端支持了内置降采样的能力:

  1. 用户对降采样库,只需要配置降采样的间隔和指标存储时间即可;
  2. 内部SLS会定期将数据按照配置进行降采样(保留降采样范围内最新的点,相当于last_over_time)并存储到新的指标库;
  3. 查询时,会根据查询的Step和时间范围,自动选择适配的指标库;
  1. 例如指标精度分别为1m、10m、1h,Step为30m则会选择10m的库;
  2. 例如原始指标库只存3天,降采样存30天,查询7天则会选择降采样库;
  1. 如果查询降采样库,SLS计算引擎会自动对Query进行改写或对数据进行拟合计算,无需手动修改Query;


UnionMetricStore

image.png

SLS的众多内外部客户业务遍及全国各地,通常数据都会本地存储,而在做全局性的大盘、查询时,往往需要到多个地方手动查询或者自己开发网关进行多Project、Store的查询、聚合。得益于SLS分布式计算、计算下推等能力的技术实现,我们能够在引擎层支持高性能、低资源消耗的跨Project甚至跨Region的查询能力----Union MetricStore:

  1. Union MetricStore 支持关联同一账号下多个Project、MetricStore;
  2. Union MetricStore 支持完整的PromQL;
  • 注意:由于合规问题,UnionStore并不支持跨国的Project。


用户体感

image.png

  • 上述是在4万条左右时间线下,SLS不同计算模式的性能对比;
  • 受限于本地浏览器->Grafana后端 -> SLS后端的网络延迟,带cache的功能看起来还是有略微延迟,实际如果命中缓存时后端延迟在微秒级别;


image.png

  • 上述是在最高200万+时间线下,SLS不同计算模式的性能对比;
  • 200万+时间线情况下,SLS 普通模式报错原因:防止一个Query直接把标准Prometheus计算节点打OOM;


和开源Prometheus的性能对比

我们针对市面上流行的一些PromQL引擎,进行了一次综合的性能对比,参赛的选手主要有:开源标准的Prometheus、分布式方案Thanos、号称市面上最快的PromQL引擎VictoriaMetrics

  • 注意:测试时,我们并没有打开全局Cache和降采样的功能,主要是这两个场景在命中时的性能提升过于巨大,放到同一象限进行对比意义不大。
  • 注意:上述SLS的并行计算和计算下推的PromQL还是完全兼容PromQL语法,兼容性测试通过率为100%,下述是市面上开源、商业版Prometheus的兼容性结果


image.png

测试负载:

  • 开源数据源:Prometheus Benchmark

测试环境:

  • Prometheus:单机部署在一台32C128G ECS,存储PL1 ESSD
  • Thanos:相关组件部署在5台32C128G ECS,存储PL1 ESSD + OSS
  • VictoriaMetrics:相关组件部署在5台32C128G ECS,存储PL1 ESSD
  • SLS:三个不同场景,分别为4、16、64个Shard

测试场景:

  • 100 Target:同一时刻时间线上限 2.56W,汰换率 1%(每10分钟更新一次)
  • 1000 Target:同一时刻时间线上限:25.6W,汰换率 40%(每10分钟更新一次)
  • 5000 Target:同一时刻时间线上线:128W,汰换率 80%(每10分钟更新一次)
  • 注意:汰换率用于表示指标更新速度,在传统场景通常变化不大,但在微服务、云原生、机器学习等场景,由于Pod、服务、Job 等生命周期短且会动态变化(每次生成一个新的 ID,也即新的时间线),指标汰换速度都会特别快(相关概念和时间线膨胀基本一致)

下述主要测试了SLS三个版本的性能:

  • sls-normal:SLS Prometheus引擎基础版本,即完全使用开源Prometheus的计算引擎,存储用SLS;
  • sls-parallel-32:SLS Prometheus并行计算版本,32个并发度的并行计算(计算引擎还是开源Prometheus);
  • sls-pushdown:SLS 计算下推版本,常见Query使用C++实现的Prometheus计算引擎;


image.png


上表主要展示在3个不同场景下,常见查询的平均延迟情况(单位ms),可以看到:

  1. 得益于使用自有逻辑实现了PromQL(兼容性较低),VictoriaMetrics整体的性能都还不错,尤其是时间线少的情况下,延迟很低;
  2. sls-normal版本由于和开源Prometheus使用相同计算引擎且都是单协程计算,两者性能基本一致;
  3. thanos相对更关注在分布式的解决方案,PromQL计算性能较一般,大Query会超时或者OOM掉;
  4. sls-pushdown在超大规模时间线下提升较为明显,整体相比sls-normal版本都有10倍以上的提升(完全下推场景下实际会有百倍的性能提升);
  • 后续会有详细的测试报告发出,本文就不多占篇幅


本文介绍的技术点钟,有两个在成本上有巨大提升:

  1. 聚合写入:通过聚合写入,大大节省了SLS后端存储、计算资源,单位数据下的成本更低;
  2. 降采样:通过降采样配置,高精度时序数据无需长期保存,整体成本下降明显;


单GB价格下降

聚合写入后,SLS会把单位数据成本下降的红利释放给客户,最直观的体现是SLS的时序售卖价格变低:

  • 注意:价格调整相关工作正在进行中,敬请期待~


降采样成本优化

降采样对于成本的优化主要体现在SLS存储量的下降,下面以一个常见场景来作为示例:


image.png


总结

从上述表格中可以看出,使用场景相同的情况下,降采样在存储时长越高时带来的成本优化效果更好。上述的技术升级已经在SLS部分集群上线,后续会逐步升级到所有集群,为保证整体稳定性,会有一定时间,请大家耐心等待。有迫切需求的可以先联系作者。后续关于这些功能的方案介绍、使用手册、最佳实践、性能测试等会逐步发出,敬请期待。性能、成本、稳定性、安全的提升永无止境,这方面SLS会持续优化,为大家提供靠谱的可观测存储引擎。

联系我们

如果大家有SLS相关的使用需求和问题,可以联系我们,后台回复【SLS】进钉群。

参考:


来源|阿里云开发者公众号

作者 | 元乙

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
相关文章
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
323 3
|
3月前
|
缓存 监控 算法
分析慢日志文件来优化 PHP 脚本的性能
分析慢日志文件来优化 PHP 脚本的性能
|
5月前
|
SQL JSON 数据处理
5% 消耗,6 倍性能:揭秘新一代 iLogtail SPL 日志处理引擎与 Logstash 的 PK
在本文中,我们将深入探讨为何选择 iLogtail,以及它在 SPL 数据处理方面相较于 Logstash 有何独特优势。通过对比这两款工具的架构、性能以及功能,我们希望能够揭示 iLogtail 如何在日益复杂的日志处理需求中脱颖而出,帮助您做出明智的技术选择。
40455 25
|
5月前
|
弹性计算 Prometheus Cloud Native
SLS Prometheus存储问题之Union MetricStore在性能测试中是如何设置测试环境的
SLS Prometheus存储问题之Union MetricStore在性能测试中是如何设置测试环境的
|
5月前
|
存储 Prometheus Cloud Native
SLS Prometheus存储问题之为什么SLS时序引擎最终选择了使用C++实现PromQL的部分算子
SLS Prometheus存储问题之为什么SLS时序引擎最终选择了使用C++实现PromQL的部分算子
|
5月前
|
测试技术 UED 存储
SLS Prometheus存储问题之在使用内置降采样时,SLS自动选择适配的指标库该如何解决
SLS Prometheus存储问题之在使用内置降采样时,SLS自动选择适配的指标库该如何解决
|
5月前
|
存储 并行计算 开发工具
SLS Prometheus存储问题之相比客户端SDK聚合写入,SLS网关侧聚合写入有什么优势
SLS Prometheus存储问题之相比客户端SDK聚合写入,SLS网关侧聚合写入有什么优势
|
5月前
|
运维 中间件 数据库
浅析JAVA日志中的性能实践与原理解释问题之元信息打印会导致性能急剧下降问题如何解决
浅析JAVA日志中的性能实践与原理解释问题之元信息打印会导致性能急剧下降问题如何解决
|
5月前
|
开发框架 缓存 Java
浅析JAVA日志中的性能实践与原理解释问题之"Garbage Free"技术的实现方式问题如何解决
浅析JAVA日志中的性能实践与原理解释问题之"Garbage Free"技术的实现方式问题如何解决
|
5月前
|
缓存 自然语言处理 Java
浅析JAVA日志中的性能实践与原理解释问题之减少看得见的业务开销问题如何解决
浅析JAVA日志中的性能实践与原理解释问题之减少看得见的业务开销问题如何解决