写在前面
这是有关于OpenTSDB支持的有关配置,和预先设置聚合,不过这方面的应用还是太少,有待补充。
原地址:http://opentsdb.net/docs/build/html/user_guide/rollups.html
预聚集
虽然汇总有助于进行广泛的时间跨度查询,但如果度量标准具有高基数(即给定度量标准的唯一时间序列数),则仍会遇到小范围的查询性能问题。在上面的示例中,我们有4个Web服务器。但是我们说我们有10,000台服务器。获取接口流量的总和或平均值可能相当慢。如果用户经常取由大型成套这样的组(或有些人认为它作为空间集合)的话很有道理存储汇总和查询代替,取多少数据较少。
与汇总不同,预聚合只需要一条额外的信息:
-
聚合函数 - 对基础值执行了哪些算术以获得新值。例如
sum
,添加所有时间序列或max
存储最大的时间序列。
在OpenTSDB中,预聚合与具有特殊标记的其他时间序列不同。默认标记键是_aggregate
(可配置通过tsd.rollups.agg_tag_key
)。然后,用于生成数据的聚合函数以大写形式存储在标记值中。让我们看一个例子:
预聚合示例
鉴于示例设置在顶部,我们可能希望按colo(数据中心)查看总接口流量。在这种情况下,我们可以汇总SUM
和COUNT
汇总类似。结果将是四个新的时间序列与元数据,如:
Series ID | Metric | Tag 1 | Tag 2 |
---|---|---|---|
ts1' | system.if.bytes.out | colo=lga | _aggregate=SUM |
ts2' | system.if.bytes.out | colo=lga | _aggregate=COUNT |
ts3' | system.if.bytes.out | colo=sjc | _aggregate=SUM |
ts4' | system.if.bytes.out | colo=sjc | _aggregate=SUM |
请注意,这些时间序列已删除了host
和的标记interface
。这是因为,聚集过程中,取得了多个不同的值,host
并且interface
已经结束了到这个新的系列,使其不再有意义,让他们为标签。另请注意,我们_aggregate
在存储的数据中注入了新标记。查询现在可以通过指定_aggregate
值来访问此数据。
注意
启用汇总后,如果您计划使用预聚合,则可能希望通过TSDB自动注入来帮助区分原始数据和预聚合_aggregate=RAW
。只需将tsd.rollups.tag_raw
设置配置为true即可。
现在为结果数据:
Series ID | 12:00 | 12:15 | 12:30 | 12:45 | 13:00 | 13:15 | 13:30 | 13:45 |
---|---|---|---|---|---|---|---|---|
ts1' | 8 | 6 | 5 | -1 | 6 | -4 | 6 | 3 |
ts2' | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 |
ts3' | 9 | 5 | 3 | 1 | 14 | 8 | 4 | 9 |
ts4' | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
由于我们通过聚合(分组colo
)执行组,因此我们从原始数据集中获取每个时间戳的值。在这种情况下,我们不会进行下采样或执行汇总。
警告
与汇总一样,在编写预聚合时,最好避免使用平均值,中值或偏差等函数。只需存储金额和计数
累积预聚合
虽然预聚合肯定有助于高基数指标,但用户可能仍然想要求广泛的时间跨度但遇到慢查询。值得庆幸的是,您可以像原始数据一样汇总预聚合。只需生成预聚合,然后使用上面的信息将其汇总。
生成汇总和预聚合
目前,TSD不会为您生成汇总或预先汇总的数据。其主要原因是OpenTSDB旨在处理大量的时间序列数据,因此各个TSD专注于尽可能快地将数据存入存储。
问题
由于TSD的(基本上)无状态特性,它们可能不具有可用于执行预聚合的全套数据。例如,我们的样本ts1
数据可能会在写入TSD_A
时ts2
写入TSD_B
。如果不从存储中读取数据,也不能执行适当的分组。我们也不知道我们应该在什么时候进行预聚合。我们可以等待1分钟并预先汇总数据,但会错过那一分钟后发生的任何事情。或者我们可以等待一个小时,对预聚合的查询将不会包含最后一小时的数据。如果数据进入后期会发生什么?
此外,对于汇总,根据用户如何将数据写入TSD,ts1
我们可能会收到12:15
数据点,TSD_A
但12:30
值会到达,TSD_B
因此整个小时都不需要数据。时间窗口约束也适用于汇总。
解决方案
使用汇总和预聚合需要进行一些分析并在各种权衡之间进行选择。由于一些OpenTSDB用户已经有了计算此类数据的方法,我们只需提供API来存储和查询。但是,这里有一些关于如何自己计算这些的技巧。
批量处理
其他时间序列数据库通常使用的一种方法是在延迟一段时间后从数据库中读取数据,计算pre-aggs和汇总,然后编写它们。这是解决问题的最简单方法,适用于小规模。但是仍然存在一些问题:
-
随着数据的增长,生成汇总的查询也会增长到查询负载影响写入和用户查询性能的程度。在HBase下启用数据压缩时,OpenTSDB会遇到同样的问题。
-
此外,随着数据的增长,更多数据意味着批处理时间更长,必须在多个工作人员之间进行分片,这可能会很难协调和排除故障。
-
除非采用某种跟踪方法来触发旧数据的新批处理,否则可能无法汇总延迟或历史数据。
一些改进批处理的方法包括:
-
从复制系统读取,例如,如果您设置HBase复制,您可以让用户查询主系统和从复制存储读取的聚合。
-
从备用商店阅读。一个示例是将所有数据镜像到另一个存储(例如HDFS),并针对该数据运行批处理作业。
排队TSD
某些数据库使用的另一个选项是将进程内存中的所有数据排队,并在经过配置的时间窗口后写入结果。但由于TSD是无状态的,并且通常用户在其TSD之前放置负载平衡器,因此单个TSD可能无法获得要计算的汇总或预聚合的全貌(如上所述)。要使此方法起作用,上游收集器必须将计算所需的所有数据路由到特定TSD。这不是一项艰巨的任务,但面临的问题包括:
-
有足够的RAM或磁盘空间来为每个TSD本地假脱机数据。
-
如果TSD进程终止,您将丢失聚合的数据,或者必须从存储中引导。
-
无论何时进行聚合计算,原始数据的总写入吞吐量都会受到影响。
-
您仍然有迟到/历史数据问题。
-
由于TSDB是基于JVM的,因此将所有数据保存在RAM中然后运行GC会受到影响。很多。(假脱机到磁盘更好,但是你会遇到IO问题)
一般来说,排在作家身上是一个坏主意。避免疼痛。
流处理
处理汇总和预聚合的更好方法是将数据路由到流处理系统,在该处理系统中可以近乎实时地处理数据并将其写入TSD。它类似于TSD上的排队选项,但使用无数流处理框架之一(Storm,Flink,Spark等)来处理消息路由和内存存储。然后,您只需编写一些代码来计算聚合,并在窗口通过后将数据吐出。
这是许多下一代监控解决方案所使用的解决方案,例如雅虎的解决方案。雅虎正致力于为需要大规模监控的其他人开源他们的流处理系统,并将其整齐地插入TSDB。
虽然流处理更好,但仍然有问题需要处理,例如:
-
足够的资源让流工人完成他们的工作。
-
死流工作者需要从存储启动。
-
必须处理延迟/历史数据。
分享
如果您有用于计算聚合的工作代码,请与OpenTSDB组共享。如果您的解决方案是开源的,我们可以将其合并到OpenTSDB生态系统中。
组态
对于Opentsdb 2.4,汇总配置由opentsdb.conf密钥引用tsd.rollups.config
。此键的值必须是除了换行符的报价转义JSON字符串,或者最好是包含配置的JSON文件的路径。文件名必须以.json
in 结尾rollup_config.json
。
JSON配置应如下所示:
{ “aggregationIds” : { “sum” : 0 , “count” : 1 , “min” : 2 , “max” : 3 }, “interval” : [{ “table” : “tsdb” , “preAggregationTable” : “ tsdb-preagg“ , ”interval“ : ”1m“ , ”rowSpan“ : ”1h“ , ”defaultInterval“ : true }, { ”table“ : ”tsdb-rollup-1h“ , ”preAggregationTable“: “tsdb-rollup-preagg-1h” , “interval” : “1h” , “rowSpan” : “1d” }] }
两个顶级字段包括:
-
aggregationIds - OpenTSDB聚合函数名称到用于压缩存储的数字标识符的映射。
-
interval - 包含表名和区间定义的一个或多个区间定义的列表。
aggregationIds
聚合ID映射用于通过使用数字ID预先填充每种类型的汇总数据而不是拼写出完整聚合函数来减少存储。例如,如果我们COUNT:
为每个值(或压缩列)的每个值加上6个字节的前缀,我们可以使用ID进行保存。
ID必须是0到127之间的整数。这意味着我们每个时间间隔最多可以存储128个不同的汇总。在映射中可以仅提供每个数值的一个ID,并且可以仅给出每种类型的一个聚合函数。如果函数名称未映射到OpenTSDB支持的聚合函数,则启动时将抛出异常。同样,必须至少给出一个聚合才能启动TSD。
警告
一旦开始写入数据,就无法更改聚合ID。如果更改映射,则可能会返回不正确的数据,或者查询和写入可能会失败。您总是可以在将来添加函数,但永远不会更改映射。
间隔
每个区间对象都定义了表路由,以便汇总和查询汇总和预聚合数据。间隔有两种类型:
-
默认 - 这是由定义的默认原始数据OpenTSDB表
"defaultInterval":true
。对于现有安装,这将是tsdb
表或其中定义的任何内容tsd.storage.hbase.data_table
。间隔和跨度被忽略,默认为OpenTSDB 1小时行宽,并以给定的分辨率和时间戳存储数据。每个TSD和配置一次只能配置一个默认值。 -
汇总间隔 -
"defaultInterval":false
未设置或未设置默认间隔的任何间隔。这些是汇总表,其中值被捕捉到间隔边界。
应定义以下字段:
名称 | 数据类型 | 是否必须 | 描述 | 例 |
---|---|---|---|---|
table | String | 是 | 非预先聚合数据的基础或汇总表。对于默认表,应该是tsdb 或者写入现有原始数据表。对于汇总数据,它必须是与原始数据不同的表。 | tsdb-rollup-1h |
preAggregationTable | String | 是 | 应该写入预聚合和(可选)汇总数据的表。这可能与table 值相同。 | tsdb-rollup-preagg-1h |
interval | String | 是 | 格式中数据点之间的预期间隔<interval><units> 。例如,如果每小时计算汇总,则间隔应为1h 。如果每10分钟计算一次,请将其设置为10m 。对于默认表,将忽略此值。 | 1H |
ROWSPAN | String | 是 | 存储中每行的宽度。此值必须大于更大interval 和界定的数量和是那么我们将不得不每行24个值。interval``s that will fit in each row. E.g. if the interval is ``1h``rowSpan``1d | 1D |
defaultInterval | bool | 否 | 配置的时间间隔是否为原始 non-rolled 数据的默认值。 | true |
在存储中,汇总的写入类似于原始数据,因为每行都有一个基本时间戳,每个数据点都是该基准时间的偏移量。每个偏移量都是基准时间的增量,而不是实际偏移量。例如,如果一行存储1天的1小时数据,则最多可存在24个偏移。偏移0
将映射到行的午夜,偏移5将映射到上午6点。因为汇总偏移量是以14位编码的,如果一行中存储的间隔太多而无法容纳在14位内,则在启动TSD时会引发错误。
警告
将数据写入TSD后,请勿更改间隔宽度或行间距以进行汇总间隔。这将导致垃圾数据和可能的查询失败。
OpenTSDB系列
总结目录https://blog.csdn.net/jyj1100/article/details/83450282