解密OpenTSDB的表存储优化

本文涉及的产品
对象存储 OSS,20GB 3个月
阿里云盘企业版 CDE,企业版用户数5人 500GB空间
文件存储 NAS,50GB 3个月
简介: 本篇文章会详细讲解OpenTSDB的表结构设计,在理解它的表结构设计的同时,分析其采取该设计的深层次原因以及优缺点。它的表结构设计完全贴合HBase的存储模型,而表格存储(TableStore、原OTS)与HBase有类似的存储模型,理解透OpenTSDB的表结构设计后,我们也能够对这类数据库的存储

摘要 

OpenTSDB是一个分布式的、可伸缩的时间序列数据库,在DB-engines的时间序列数据库排行榜上排名第五。它的特点是能够提供最高毫秒级精度的时间序列数据存储,能够长久保存原始数据并且不失精度。它拥有很强的数据写入能力,支持大并发的数据写入,并且拥有可无限水平扩展的存储容量。

        它的强大的数据写入能力与存储能力得益于它底层依赖的HBase数据库,也得益于它在表结构设计上做的大量的存储优化。

        本篇文章会详细讲解其表结构设计,在理解它的表结构设计的同时,分析其采取该设计的深层次原因以及优缺点。它的表结构设计完全贴合HBase的存储模型,而表格存储(TableStore、原OTS)与HBase有类似的存储模型,理解透OpenTSDB的表结构设计后,我们也能够对这类数据库的存储模型有一个更深的理解。


存储模型

在解析OpenTSDB的表结构设计前,我们需要先对其底层的HBase的存储模型有一个理解。

表分区

HBase会按Rowkey的范围,将一张大表切成多个region,每个region会由一个region server加载并提供服务。Rowkey的切分与表格存储的分区类似,一个良好设计的表,需要保证读写压力能够均匀的分散到表的各个region,这样才能充分发挥分布式集群的能力。


存储结构



如图所示为表结构以及对应的存储结构示例,在HBase或表格存储这类底层采用LSM-tree的数据库中,表数据会按列存储。每行中的每一列在存储文件中都会以Key-value的形式存在于文件中。其中Key的结构为:行主键 + 列名,Value为列的值。该种存储结构的特点是:
        a. 每行主键会重复存储,取决于列的个数
        b. 列名会重复存储,每一列的存储都会携带列名
        c. 存储数据按row-key排序,相邻的row-key会存储在相邻的块中


OpenTSDB的基本概念

OpenTSDB定义每个时间序列数据需要包含以下属性:

1. 指标名称(metric name)

2. 时间戳(UNIX timestamp,毫秒或者秒精度)

3. 值(64位整数或者单精度浮点数)

4. 一组标签(tags,用于描述数据属性,至少包含一个或多个标签,每个标签由tagKey和tagValue组成,tagKey和tagValue均为字符串)


举个例子,在监控场景中,我们可以这样定义一个监控指标:

指标名称:
    sys.cpu.user
标签:
    host = 10.101.168.111
    cpu = 0
指标值:
    0.5
指标名称代表这个监控指标是对用户态CPU的使用监控,引入了两个标签,分别标识该监控位于哪台机器的哪个核。

OpenTSDB支持的查询场景为:指定指标名称和时间范围,给定一个或多个标签名称和标签的值作为条件,查询出所有的数据。

以上面那个例子举例,我们可以查询:

    a. sys.cpu.user (host=*,cpu=*)(1465920000 <= timestamp < 1465923600):查询凌晨0点到1点之间,所有机器的所有CPU核上的用户态CPU消耗。

    b. sys.cpu.user (host=10.101.168.111,cpu=*)(1465920000 <= timestamp < 1465923600):查询凌晨0点到1点之间,某台机器的所有CPU核上的用户态CPU消耗。

    c. sys.cpu.user (host=10.101.168.111,cpu=0)(1465920000 <= timestamp < 1465923600):查询凌晨0点到1点之间,某台机器的第0个CPU核上的用户态CPU消耗。


OpenTSDB的存储优化

了解了OpenTSDB的基本概念后,我们来尝试设计一下表结构。


如上图是一个简单的表结构设计,rowkey采用metric name + timestamp + tags的组合,因为这几个元素才能唯一确定一个指标值。

这张表已经能满足我们的写入和查询的业务需求,但是OpenTSDB采用的表结构设计远没有这么简单,我们接下来一项一项看它对表结构做的一些优化。

优化一:缩短row key

观察这张表内存储的数据,在rowkey的组成部分内,其实有很大一部分的重复数据,重复的指标名称,重复的标签。以上图为例,如果每秒采集一次监控指标,cpu为2核,host规模为100台,则一天时间内sys.cpu.user这个监控指标就会产生17280000行数据,而这些行中,监控指标名称均是重复的。如果能将这部分重复数据的长度尽可能的缩短,则能带来非常大的存储空间的节省。


OpenTSDB采用的策略是,为每个metric、tag key和tag value都分配一个UID,UID为固定长度三个字节。


上图为优化后的存储结构,可以看出,rowkey的长度大大的缩短了。rowkey的缩短,带来了很多好处:

    a. 节省存储空间

    b. 提高查询效率:减少key匹配查找的时间

    c. 提高传输效率:不光节省了从文件系统读取的带宽,也节省了数据返回占用的带宽,提高了数据写入和读取的速度。

    d. 缓解Java程序内存压力:Java程序,GC是老大难的问题,能节省内存的地方尽量节省。原先用String存储的metric name、tag key或tag value,现在均可以用3个字节的byte array替换,大大节省了内存占用。


优化二:减少Key-Value数

优化一是OpenTSDB做的最核心的一个优化,很直观的可以看到存储的数据量被大大的节省了。原理也很简单,将长的变短。但是是否还可以进一步优化呢?

在上面的存储模型章节中,我们了解到。HBase在底层存储结构中,每一列都会以Key-Value的形式存储,每一列都会包含一个rowkey。如果要进一步缩短存储量,那就得想办法减少Key-Value的个数。

OpenTSDB分了几个步骤来减少Key-Value的个数:

1. 将多行合并为一行,多行单列变为单行多列。

2. 将多列合并为一列,单行多列变为单行单列。

多行单列合并为单行单列


OpenTSDB将同属于一个时间周期内的具有相同TSUID(相同的metric name,以及相同的tags)的数据合并为一行存储。OpenTSDB内默认的时间周期是一个小时,也就是说同属于这一个小时的所有数据点,会合并到一行内存储,如图上所示。合并为一行后,该行的rowkey中的timestamp会指定为该小时的起始时间(所属时间周期的base时间),而每一列的列名,则记录真实数据点的时间戳与该时间周期起始时间(base)的差值。

这里列名采用差值而不是真实值也是一个有特殊考虑的设计,如存储模型章节所述,列名也是会存在于每个Key-Value中,占用一定的存储空间。如果是秒精度的时间戳,需要4个字节,如果是毫秒精度的时间戳,则需要8个字节。但是如果列名只存差值且时间周期为一个小时的话,则如果是秒精度,则差值取值范围是0-3600,只需要2个字节;如果是毫秒精度,则差值取值范围是0-360000,只需要4个字节;所以相比存真实时间戳,这个设计是能节省不少空间的。

单行多列合并为单行单列

多行合并为单行后,并不能真实的减少Key-Value个数,因为总的列数并没有减少。所以要达到真实的节省存储的目的,还需要将一行的列变少,才能真正的将Key-Value数变少。

OpenTSDB采取的做法是,会在后台定期的将一行的多列合并为一列,称之为『compaction』,合并完之后效果如下。


同一行中的所有列被合并为一列,如果是秒精度的数据,则一行中的3600列会合并为1列,Key-Value数从3600个降低到只有1个。

优化三:并发写优化

上面两个优化主要是OpenTSDB对存储的优化,存储量下降以及Key-Value个数下降后,除了直观的存储量上的缩减,对读和写的效率都是有一定提升的。

时间序列数据的写入,有一个不可规避的问题是写热点问题,当某一个metric下数据点很多时,则该metric很容易造成写入热点。OpenTSDB采取了和这篇文章中介绍的一样的方法,允许将metric预分桶,可通过『tsd.storage.salt.buckets』配置项来配置。

如上图所示,预分桶后的变化就是在rowkey前会拼上一个桶编号(bucket index)。预分桶后,可将某个热点metric的写压力分散到多个桶中,避免了写热点的产生。

总结

OpenTSDB作为一个应用广泛的时间序列数据库,在存储上做了大量的优化,优化的选择也是完全契合其底层依赖的HBase数据库的存储模型。表格存储拥有和HBase一样的存储模型,这部分优化经验可以直接借鉴使用到表格存储的应用场景中,值得我们好好学习。有问题欢迎大家一起探讨。

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5月前
|
SQL 分布式计算 关系型数据库
实时数仓 Hologres产品使用合集之分区表创建冷热分层后,查询语法会与原先有区别吗
实时数仓Hologres的基本概念和特点:1.一站式实时数仓引擎:Hologres集成了数据仓库、在线分析处理(OLAP)和在线服务(Serving)能力于一体,适合实时数据分析和决策支持场景。2.兼容PostgreSQL协议:Hologres支持标准SQL(兼容PostgreSQL协议和语法),使得迁移和集成变得简单。3.海量数据处理能力:能够处理PB级数据的多维分析和即席查询,支持高并发低延迟查询。4.实时性:支持数据的实时写入、实时更新和实时分析,满足对数据新鲜度要求高的业务场景。5.与大数据生态集成:与MaxCompute、Flink、DataWorks等阿里云产品深度融合,提供离在线
|
1月前
|
存储 算法 NoSQL
大数据-138 - ClickHouse 集群 表引擎详解3 - MergeTree 存储结构 数据标记 分区 索引 标记 压缩协同
大数据-138 - ClickHouse 集群 表引擎详解3 - MergeTree 存储结构 数据标记 分区 索引 标记 压缩协同
34 0
|
6月前
|
存储 数据挖掘 数据库
InfluxDB的连续查询与数据聚合技术详解
【4月更文挑战第30天】InfluxDB的连续查询(CQ)功能用于自动定时聚合时间序列数据,适用于数据降采样、实时分析和告警通知等场景。CQ使用InfluxQL编写,例如,每1小时对`cpu_usage`测量值计算主机的平均CPU使用率并存入`cpu_usage_hourly`。InfluxDB提供多种聚合函数如`MEAN()`, `MAX()`, 支持滑动窗口聚合等复杂操作,助力时间序列数据分析和趋势预测。通过CQ,用户能高效管理和利用时间序列数据信息。
|
存储 索引
67.【clickhouse】ClickHouse从入门到放弃-对于分区、索引、标记和压缩数据的协同总结
【clickhouse】ClickHouse从入门到放弃-对于分区、索引、标记和压缩数据的协同总结
67.【clickhouse】ClickHouse从入门到放弃-对于分区、索引、标记和压缩数据的协同总结
|
存储 并行计算 Cloud Native
PolarDB 开源版通过 brin 实现千分之一的存储空间, 高效率检索时序数据
PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的 价值产出, 将数据变成生产力. 本文将介绍PolarDB 开源版通过 brin 实现千分之一的存储空间, 高效率检索时序数据
208 0
|
6月前
|
存储 SQL 监控
Lindorm:时序数据“存、算、管、用”的最佳实践
本文档介绍Lindorm时序引擎在时序数据的存储、计算、管理、应用上的最佳实践。
299 0
Lindorm:时序数据“存、算、管、用”的最佳实践
|
6月前
|
关系型数据库 分布式数据库 PolarDB
PolarDB 开源版通过 brin 实现千分之一的存储空间, 高效率检索时序数据
背景PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的 价值产出, 将数据变成生产力.本文将介绍PolarDB 开源版通过 brin 实现千分之一的存储空间, 高效率检...
133 0
|
存储 SQL NoSQL
海量结构化数据存储技术揭秘:Tablestore存储和索引引擎详解
海量结构化数据存储技术揭秘:Tablestore存储和索引引擎详解
422 0
海量结构化数据存储技术揭秘:Tablestore存储和索引引擎详解
|
SQL 存储 NoSQL
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-SQL 查询和分析
前言前面我们介绍了基于 MySQL + Tablestore 分层架构的订单系统。订单数据储存进入 Tablestore 后,用户可以使用 SDK 中的 API 访问数据,也可以继续使用 SQL 访问 Tablestore 中的数据。Tablestore 提供了多种 SQL 的接入方式,客户可以通过 DLA 访问 Tablestore,也可以利用 Tablestore 自身对 SQL 的支持能力,
977 0
基于 MySQL + Tablestore 分层存储架构的大规模订单系统实践-SQL 查询和分析
下一篇
无影云桌面