【万字干货】OpenMetric与时序数据库存储模型分析
摘要:解读OpenMetric规范和指标的模型定义基础上,结合当下主流的时序数据库核心存储及处理技术,尝试让用户(架构师、开发者或使用者)结合自身业务场景选择合适的产品,消除技术选型的困惑。本文分享自华为云社区《【万字干货】OpenMetric与时序数据库存储模型分析》,作者: 敏捷的小智。
摘要 近些年时序数据库发展突飞猛进,IT系统的监控指标就是一种典型的时序数据。由于云计算、容器、微服务和Serverless的普遍采用和业务系统的大型化、复杂化;加之IoT的蓬勃发展,海量时序数据的采集、存储、处理与分析,面临着全新的需求与挑战。在解读OpenMetric规范和指标的模型定义基础上,结合当下主流的时序数据库核心存储及处理技术,尝试让用户(架构师、开发者或使用者)结合自身业务场景选择合适的产品,消除技术选型的困惑。结合云服务商的最新动态,为用户提供开箱即用的、高可靠的多种可选方案,加速应用构建及可运维能力的完善,聚焦核心业务,促进业务成功。
背景 参考DB-ENGINES网站[1]关于各大数据库排名,是数据库产品选型的一个重要参考指标。尤其是针对不同业务场景和诉求,在垂直细分领域中关注那些评分和排名靠前的数据库产品。比如,根据DB-Engines按数据库类别的调查统计和评分图表(如下图1)显示:在最近的2年里,时序数据库(TSDB)位居增长最快的数据库类型榜首,尤其是最近一年时间里,更是一骑绝尘!
文章图片
图1
从DB-Engines关于TSDB的评分趋势图(如下图2)来看,主流的TSDB包括了InfluxDB、Prometheus、TimescaleDB、Apache Druid、OpenTSDB等等。
文章图片
图2
事实上,业界流行的ClickHouse、Apache IoTDB等也属于时序数据库范畴。本文从应用运维场景,对众多的TSDB做个初步分析和筛选出典型代表产品,方便后面进行针对性的对比分析。
- InfluxDB:排名第一,社区火热和国内外采用厂商比较多。
- Prometheus:属于CNCF基金会第二个毕业的项目,在社区中比较火爆,甚至在容器领域形成事实的监控缺省方案。在国内外被普遍采用。
- TimescaleDB: 基于优秀的PostgreSQL构建出的时序数据库。长远考虑,专业的TSDB必须是从底层存储面向时序数据的特征进行针对性设计和优化的。因此它不在本文中进一步分析。
- Apache Druid:非常有名的实时OLAP分析平台,面向时序数据设计的,在极致性能和数据schema的灵活性方面有一定的平衡。类似的产品还有Pinot、Kylin等。
- OpenTSDB:基于HBase构建的时序数据库,依赖Hadoop生态太重,早期和InfluxDB并驾齐驱;近年来在社区中的热度已经远远落后于InfluxDB了。它还不支持多维查询。因此,它也排除在外。
- ClickHouse:俄罗斯Yandex开发的数据分析数据库(OLAP),但它可以充当TSDB来使用。本文不做深入分析。
- IoTDB:国内清华大学开源的时序数据库,面向工业IoT场景;性能出众,社区活跃。
运维域的时序数据的特性:
? 不可变性(Immutable)
? 实时性(realtime),历史越久远的数据,其潜在价值越小。一方面是流式写入,一方面是近实时查询或即时分析。
? 海量(Volumne)某直播平台,高速实时写入2000万/s; 需要结构化的数据多达200TB/d。如果考虑云服务厂商的某些逻辑多租的时序数据库应用,对峰值写入和峰值查询有更高的要求。
? 高压缩率:数据量太大直接影响到存储成本,所以高性能数据压缩是必备特性。
时序数据模型 在本文展开之前,先罗列出一些专业术语,以方便统一认知。说实话,就是数据库或者运维领域的专业人士,也经常被各种中文翻译搞得一头雾水。为了减少歧义性,本文习惯性地在一些关键词后面备注一下对应的原英文术语,以方便大家理解。
基本概念 Time series(时间序列,简称时序或者时序数据):根据wiki百科[2],其数学定义是这样:In mathematics, a time series is a series of data points indexed (or listed or graphed) in time order. Most commonly, a time series is a sequence taken at successive equally spaced points in time. Thus it is a sequence of discrete-time data. 翻译过来的要点就是 1)源于数学学科; 2)是按时间顺序索引的一系列数据点。因此也多翻译为“时序数据”。3)最常见的是在连续的相等间隔时间点上获取的序列。4)是一个离散时间的数据序列。
Metric(指标):在软件领域,Metric是对软件或其规格的某些属性的度量。在wiki百科中有这样的阐述:software metric[3]是衡量软件系统或过程具有某种属性的程度的标准。尽管学术界最初认为Metric是函数(function),Measurement是通过应用metric获得的数值;但随着计算机学科和传统学科的借鉴融合,这两个术语通常也用作同义词,泛指同一个东西了。
二者的关系:简单地讲,带有时间戳的很多metric放在一起就构成了一个Time series。
时序数据一般有以下几个显著特点:
? 每条数据必然自带时间戳,数据以时间排序
? 不可变性(immutable):一旦写入,基本不做修改或单条删除。(因为老化过期可以做删除)
? 数据量大,一般要求支持PB级别。同时也要求高吞吐能力。
? 高效的存储压缩效率,降低成本
? 时序最核心的用途在于数据分析,包括降采样、数据插值和空间聚合计算等
? 时序的唯一性:某一个时刻的某个指标只有一条数据(或点),即时出现多条数据也会被认为是同一条数据(或点)
? 单条数据并不重要
OpenMetrics规范 OpenMetrics[4]:一种云原生、高度可扩展的指标协议。它定义了大规模上报云原生指标的事实标准,同时支持文本表示协议和Protocol Buffers协议。虽然时间序列可以支持任意字符串或二进制数据,但RFC只针对和包括数字数据。得益于Prometheus的流行,作为Prometheus的监控数据采集方案,OpenMetrics可能很快会成为未来监控的业界标准。
目前绝大部分热门开源服务均有官方或非官方的exporter可供使用。实施者必须以 OpenMetrics 文本格式公开指标,以响应对给定进程或设备的文档化 URL 的简单 HTTP GET 请求。这个端点应该被称为“/metrics”。实施者还可以通过其他方式公开 OpenMetrics 格式的指标,例如通过 HTTP 定期将指标集推送到操作员配置的端点。
备注:事件(Event)与指标相反,单一事件发生在特定时刻;而指标是个时间序列。这个概念在运维域非常重要。
数据模型
? OpenMetrics对数据模型[5]有如下的定义:
? 度量值(value):它必须是浮点数或整数。
? 时间戳(timestamp):必须是以秒为单位的 Unix Epoch。
? 字符串(string):必须仅由有效的 UTF-8 字符组成
? 标签(Label):由字符串组成的键值对。以下划线开头的标签名称是保留的,一般不得使用。
? 标签集(LabelSet):它必须由标签组成并且可以为空。标签名称在标签集中必须是唯一的。
? 指标点(MetricPoint):每个MetricPoint 由一组值组成,具体取决于 MetricFamily 类型。MetricPoints 不应该有明确的时间戳。
? 指标(metric):由 MetricFamily 中的唯一 LabelSet 定义。Metrics 必须包含一个或多个 MetricPoints 的列表。给定 MetricFamily 具有相同名称的度量标准应该在它们的 LabelSet 中具有相同的标签名称集。如果为一个 Metric 公开了多个 MetricPoint,则其 MetricPoint 必须具有单调递增的时间戳。
? 指标家族(又译作“指标系列”, MetricFamily):一个 MetricFamily 可以有零个或多个指标。MetricFamily 必须具有名称、HELP、TYPE 和 UNIT 元数据。MetricFamily 中的每个 Metric 都必须有一个唯一的 LabelSet。
MetricFamily 名称是一个字符串,并且在 MetricSet 中必须是唯一的。
后缀:OpenMetrics定义了文本格式样例度量名称使用的后缀(不同数据类型的后缀有所不同)有:
计数器Counter:'_total','_created'
摘要Summary:'_count'、'_sum'、'_created'
直方图Histogram:'_count'、'_sum'、'_bucket'、'_created'
GaugeHistogram: '_gcount', '_gsum', '_bucket'
信息Info:'_info'
类型指定 MetricFamily 类型。有效值有8种指标类型(参考后文)。
? 指标集(MetricSet):是 OpenMetrics 公开的顶级对象。它必须由 MetricFamilies 组成。每个 MetricFamily 名称必须是唯一的。相同的标签名称和值不应出现在 MetricSet 中的每个 Metric 上。MetricSet 中不需要特定的 MetricFamilies 排序。
尽管OpenMetric对一些概念定义得比较琐碎和细致,甚至晦涩难懂;但从大逻辑思路上看,它仍然包括了时间戳、指标、标签以及基础数据类型几个方面,基本符合大家的日常思路。
指标类型(Metric Type)
OpenMetrics规范定义了8种指标类型:
Gauge(仪表读数,中文翻译不准确):它是当前的测量值,例如当前CPU的利用率或者内存字节数大小。对于Gauge,用户(我们)感兴趣的是其绝对值。通俗地讲,Gauge类型的指标就像我们汽车仪表盘中的指针所对应的当前数值(有增有减或者不动,因此是可变的;数值是大于零的)。Metric 中类型为 Gauge 的 MetricPoint 必须是单个值(相对于仪表盘指针不可能同时指到多个刻度位置)。
Counter(计数器):它是计量离散事件的。MetricPoint 必须具有一个称为 Total 的值。Total必须从 0 开始随时间单调非递减。一般而言,用户感兴趣的主要是Counter随时间增加的速度。
StateSet(状态集):StateSet 表示一系列相关的布尔值,也称为位集。StateSet 度量的一个点可能包含多个状态,并且每个状态必须包含一个布尔值。状态有一个字符串名称。
Info(信息指标):信息指标用于公开在流程生命周期内不应更改的文本信息。常见示例是应用程序的版本、修订控制提交和编译器的版本。信息可用于编码其值不随时间变化的 ENUM,例如网络接口的类型。
Histogram(直方图):直方图测量离散事件的分布。常见示例是 HTTP 请求的延迟、函数运行时或 I/O 请求大小。直方图 MetricPoint 必须至少包含一个桶,并且应该包含 Sum 和 Created 值。每个桶必须有一个阈值和一个值。
GaugeHistogram(仪表直方图):测量当前分布。常见的例子是项目在队列中等待的时间,或者队列中请求的大小。
Summary(摘要):Summary测量离散事件的分布,并且可以在直方图计算过于昂贵或平均事件大小足够时使用。包含 Count 或 Sum 值的类型为 Summary 的 Metric 中的 MetricPoint 应该具有名为 Created 的 Timestamp 值。这可以帮助摄取者区分新的指标和之前没有看到的长期运行的指标。
Unknown(未知):当无法确定来自 3rd 方系统的单个指标的类型时,可以使用未知。一般情况下不能使用。
通俗地讲,histogram用于表示一段时间内对数据的采样,按照指定的时间间隔及总数进行统计。它是需要按照统计区间进行计算的。而Summary用于表示一段时间内数据采样结果,直接存储分位数(quantile)数据,不需要计算。本质上Summary是与histogram类似的。更多详细情况可以参考官方文档[6]。
基于标签(tag-value)的时序数据模型 当前主流TSDB的时序数据模型都是以标签(tag,也称label)为主来唯一确定一个时间序列(一般也附加上指标名称、时间戳等)。
Prometheus时序数据模型
本文从CNCF社区最流行的Prometheus监控系统来分析时序数据的建模。Prometheus采用了多维数据模型,包含指标名称(metric name)、一个或多个标签(labels,与tags意义相同)以及指标数值(metric value)。
时序数据模型包括了metric name、一个或多个labels(同tags)以及metric value。metric name加一组labels作为唯一标识,来定义time series,也就是时间线。
Prometheus的指标模型定义如下: