文档章节

OpenTSDB的全面介绍

莫问viva
 莫问viva
发布于 2014/10/23 15:47
字数 3137
阅读 966
收藏 4

一,OpenTSDB介绍(http://opentsdb.net/)

  OpenTSDB用HBase存储所有的时序(无须采样)来构建一个分布式、可伸缩的时间序列数据库。 它支持秒级数据采集所有metrics,支持永久存储,可以做容量规划,并很容易的接入到现有的报警系统里。OpenTSDB可以从大规模的集群(包括集 群中的网络设备、操作系统、应用程序)中获取相应的metrics并进行存储、索引以及服务,从而使得这些数据更容易让人理解,如web化、图形化等。

      对于运维工程师而言,OpenTSDB可以获取基础设施和服务的实时状态信息,展示集群的各种软硬件错误,性能变化以及性能瓶颈。

      对于管理者而 言,OpenTSDB可以衡量系统的SLA,理解复杂系统间的相互作用,展示资源消耗情况。集群的整体作业情况,可以用以辅助预算和集群资源协调。

      对于开发者而言,OpenTSDB可以展示集群的主要性能瓶颈,经常出现的错误,从而可以着力重点解决重要问题。

二,基本概念


在深入理解OpenTSDB之前,需要了解一些基本概念。

Cardinality。基数,在数学中定义为一个集合中的一些元素,在数据库中定义为一个索引的一些唯一元素,在OpenTSDB定义为:

  • 一个给定指标的一些唯一时间序列

  • 和一个标签名称相关联的一些唯一标签值

在OpenTSDB中拥有高基数的指标在查询过程中返回的值要多于低基数的指标,这样花费的时间也就越多。

Compaction。在OpenTSDB中,会将多列合并到一列之中以减少磁盘占用空间,这和hbase中的Compaction不一样。这个过程会在TSD写数据或者查询过程中不定期的发生。

Data Point。每一个指标可以被记录为某一个时间点的一个数值。Data Point包括以下部分:

  • 一个指标:metric

  • 一个数值

  • 这个数值被记录的时间戳

  • 多个标签

Metric。一个可测量的单位的标称。metric不包括一个数值或一个时间,其仅仅是一个标签,包含数值和时间的叫datapoints,metric是用逗号连接的不允许有空格,例如:

  • hours.worked

  • webserver.downloads

  • accumulation.snow

Tags。一个metric应该描述什么东西被测量,在OpenTSDB中,其不应该定义的太简单。通常,更好的做法是用Tags来描述具有相同维度的metric。Tags由tagk和tagv组成,前者表示一个分组,后者表示一个特定的项。

Time Series。一个metric的带有多个tag的data point集合。

Timestamp。一个绝对时间,用来描述一个数值或者一个给定的metric是在什么时候定义的。

Value。一个Value表示一个metric的实际数值。

UID。在OpenTSDB中,每一个metric、tagk或者tagv在创建的时候被分配一个唯一标识叫做UID,他们组合在一起可以创建一个序列的UID或者TSUID。在OpenTSDB的存储中,对于每一个metric、tagk或者tagv都存在从0开始的计数器,每来一个新的metric、tagk或者tagv,对应的计数器就会加1。当data point写到TSD时,UID是自动分配的,前提是auto metric被 设置为true。你也可以手动分配UID。默认地,UID被编码为3Bytes,每一种UID类型最多可以有16,777,215个UID。你也可以修改源代码改为4Bytes。 UID的展示有几种方式,最常见的方式是通过http api访问时,3 bytes的UID被编码为16进制的字符串。例如,UID为1的写为二进制的形式为000000000000000000000001,最为一个无符号的byte数组,其可以表示为[0,0,1],编码为16进制字符串为000001,其中每一位左边都被补上0,如果其不足两位。故,UID为255的会显示为[0,0,255]和0000FF。

注意:UID "00" 默认用来分别标识当前metric,tagk以及tagv的个数。

关于为什么使用UID而不使用hashes,可以参考:why-uids

TSUID。当一个data point被写到OpenTSDB时,其row key格式为:<metric_UID><timestamp><tagk1_UID><tagv1_UID>[...<tagkN_UID><tagvN_UID>],不考虑时间戳的话,将其余部分都转换为UID,然后拼在一起,就可以组成为TSUID。

Metadata。主要用于记录data point的一些附加的信息,方便搜索和跟踪,分为UIDMeta和TSMeta。

每一个UID都有一个metadata记录保存在tsdb-meta表中,每一个UID包括一些不可变的字段,如uid、type、name和created字段表示什么时候被创建,还可以有一些额外字段,如description、notes、displayName和一些customkey/value对,详细信息,可以查看 /api/uid/uidmeta

同样,每一个TSUID可以对应一个TSMeta,记录在tsdb-meta中,其包括的字段有tsuid、metric、tags、lastReceived和created,可选的字段有description,notes,详细信息,可以查看/api/uid/tsmeta

开启Metadata有以下几个参数:

  • tsd.core.meta.enable_realtime_uid

  • tsd.core.meta.enable_tsuid_tracking

  • tsd.core.meta.enable_tsuid_incrementing

  • tsd.core.meta.enable_realtime_ts

metadata的另外一个形式是Annotations,详细说明,请参考annotations

Tree

三,存储

OpenTSDB使用HBase作为后端存储,在安装OpenTSDB之前,需要先启动一个hbase节点或者集群,然后再执行建表语句src/create_table.sh创建hbase表。建表语句如下:

从上面可以看出一共创建了4张表,并且可以设置是否压缩、是否启用布隆过滤、保存版本号等等,如果追求hbase读写性能,还可以预建分区。

3.1 Data Table Schema


在OpenTSDB中,所有数据存储在一张叫做tsdb的表中,这是为了充分利用hbase有序和region分布式的特点。所有的值都保存在列族t中。

rowkey为<metric_uid><timestamp><tagk1><tagv1>[...<tagkN><tagvN>],UID默认编码为3 Bytes,而时间戳会编码为4 Bytes

OpenTSDB的tsdb启动之后,会监控指定的socket端口(默认为4242),接收到监控数据,包括指标、时间戳、数据、tag标签,tag标签包括tag名称ID和tag值ID。例如:

myservice.latency.avg 1292148123 42 reqtype=foo host=web42

对于指标myservice.latency.avg的ID为:[0, 0, -69],reqtype标签名称的ID为:[0, 0, 1], foo标签值的ID为:[0, 1, 11], 标签名称的ID为:[0, 0, 2] web42标签值的ID为:[0, -7, 42],他们组成rowkey:

[0, 0, -69, 77, 4, -99, 32, 0, 0, 1, 0, 1, 11, 0, 0, 2, 0, -7, 42]
 `-------'  `------------'  `-----'  `------'  `-----'  `-------'
 metric ID  base timestamp  name ID  value ID  name ID  value ID
                            `---------------'  `---------------'
                                first tag         second tag

row表示格式为: 每个数字对应1 byte

  • [0, 0, -69] metric ID

  • [77, 4, -99, 32] base timestamp = 1292148000. timestamps in the row key are rounded down to a 60 minute boundary。也就是说对于同一个小时的metric + tags相同的数据都会存放在一个row下面

  • [0, 0, 1] "reqtype" index

  • [0, 1, 11] "foo" index

  • [0, 0, 2] "host" index

  • [0, -7, 42] "web42" index

NOTE:可以看到,对于metric + tags相同的数据都会连续存放,且metic相同的数据也会连续存放,这样对于scan以及做aggregation都非常有帮助

column qualifier 占用2 bytes或者4 bytes,占用2 bytes时表示以秒为单位的偏移,格式为:

  • 12 bits:相对row表示的小时的delta, 最多2^ 12 = 4096 > 3600因此没有问题

  • 4 bits:format flags

    • 1 bit: an integer or floating point

    • 3 bits: 标明数据的长度,其长度必须是1、2、4、8。000表示1个byte,010表示2byte,011表示4byte,100表示8byte

占用4 bytes时表示以毫秒为单位的偏移,格式为:

  • 4 bits:十六进制的1或者F

  • 22 bits:毫秒偏移

  • 2 bit:保留

  • 4 bits: format flags

    • 1 bit: an integer or floating point,0表示整数,1表示浮点数

    • 3 bits: 标明数据的长度,其长度必须是1、2、4、8。000表示1个byte,010表示2byte,011表示4byte,100表示8byte

举例:

对于时间戳为1292148123的数据点来说,其转换为以小时为单位的基准时间(去掉小时后的秒)为129214800,偏移为123,转换为二进制为1111011,因为该值为整数且长度为8位(对应为2byte,故最后3bit为100),故其对应的列族名为:0000011110110100,将其转换为十六进制为07B4

value 使用8bytes存储,既可以存储long,也可以存储double。

总结一下,tsdb表结构如下:

opentsdb-tsdb-schema


3.2 UID Table Schema



一个单独的较小的表叫做tsdb-uid用来存储UID映射,包括正向的和反向的。存在两列族,一列族叫做name用来将一个UID映射到一个字符串,另一个列族叫做id,用来将字符串映射到UID。列族的每一行都至少有以下三列中的一个:

  • metrics将metric的名称映射到UID

  • tagk将tag名称映射到UID

  • tagv将tag的值映射到UID

如果配置了metadata,则name列族还可以包括额外的metatata列。

  • id 列族

Row Key - 将会是一个分配到UID的字符串,例如,对于一个指标可能有一个值为sys.cpu.user或者对于一个标签其值可能为42

Column Qualifiers - 上面三种列类型中一种。

Column Value - 一个无符号的整数,默认被编码为3个byte,其值为UID。

例如以下几行数据是从tsdb-uid表中查询出来的数据,第一个列为row key,第二列为"列族:列名",第三列为值,对应为UID

proc.stat.cpu id:metrics \x00\x00\x01
host id:tagk \x00\x00\x01
cdh1 id:tagv \x00\x00\x01

  • name 列族

Row Key - 为UID

Column Qualifiers - 上面三种列类型中一种或者为metrics_meta、tagk_meta、tagv_meta

Column Value - 与UID对应的字符串,对于一个*_meta列,其值将会是一个UTF-8编码的JSON格式字符串。不要在OpenTSDB外部去修改该值,其中的字段顺序会影响CAS调用。

例如,以下几行数据是从tsdb-uid表中查询出来的数据,第一个列为row key,第二列为"列族:列名",第三列为值,对应为UID

\x00\x00\x01 name:metrics proc.stat.cpu
\x00\x00\x01 name:tagk host
\x00\x00\x01 name:tagv cdh1
\x00\x00\x01 name:tagk_meta {"uid":"000001","type":"TAGK","name":"host","description":"","notes":"","created":1395213193,"custom":null,"displayName":""}
\x00\x00\x01 name:tagv_meta {"uid":"000001","type":"TAGV","name":"cdh1","description":"","notes":"","created":1395213193,"custom":null,"displayName":""}
\x00\x00\x01 name:metric_meta {"uid":"000001","type":"METRIC","name":"metrics proc.stat.cpu","description":"","notes":"","created":1395213193,"custom":null,"displayName":""}

总结一下,tsdb-uid表结构如下:

opentsdb-tsdb-uid-schema

上图对应的一个datapoint如下:

proc.stat.cpu 1292148123 80 host=cdh1

从上图可以看出tsdb-uid的表结构以及数据存储方式,对于一个data point来说,其被保存到opentsdb之前,会对metrics、tagk、tagv、metric_meta、tagk_meta、tagv_meta生成一个UID(如上图中的000001),然后将其插入hbase表中,rowkey为UID,同时会存储多行记录,分别保存metrics、tagk、tagv、metric_meta、tagk_meta、tagv_meta到UID的映射。


3.3 Meta Table Schema


这个表是OpenTSDB中不同时间序列的一个索引,可以用来存储一些额外的信息。这个表名称叫做tsdb-meta,该表只有一个列族name,两个列,分别为ts_meta、ts_ctr,该表中数据如下:

\x00\x00\x01\x00\x00\x01\x00\x00\x01 name:ts_ctr \x00\x00\x00\x00\x00\x00\x00p
\x00\x00\x01\x00\x00\x01\x00\x00\x01 name:ts_meta {"tsuid":"000001000001000001","displayName":"","description":"","notes":"","created":1395213196,"custom":null,"units":"","dataType":"","retention":0,"max":"NaN","min":"NaN"}

\x00\x00\x02\x00\x00\x01\x00\x00\x01 name:ts_ctr \x00\x00\x00\x00\x00\x00\x00p
\x00\x00\x02\x00\x00\x01\x00\x00\x01 name:ts_meta {"tsuid":"000002000001000001","displayName":"","description":"","notes":"","created":1395213196,"custom":null,"units":"","dataType":"","retention":0,"max":"NaN","min":"NaN"}

Row Key 和tsdb表一样,其中不包含时间戳,<metric_uid><tagk1><tagv1>[...<tagkN><tagvN>]

TSMeta Column 和UIDMeta相似,其为UTF-8编码的JSON格式字符串

ts_ctr Column 计数器,用来记录一个时间序列中存储的数据个数,其列名为ts_ctr,为8位有符号的整数



3.4 Tree Table Schema

索引表,用于展示树状结构的,类似于文件系统,以方便其他系统使用,例如:Graphite

© 著作权归作者所有

共有 人打赏支持
下一篇: JMX介绍
莫问viva
粉丝 41
博文 139
码字总数 115890
作品 0
长沙
高级程序员
私信 提问
OpenTSDB 生产应用与思考

作者:陈杰,欢聚时代YY 基础架构部,数据库技术组,专注于HBase、Kafka,MySQL 等技术。 OpenTSDB 官方介绍 这里就不翻译了。http://opentsdb.net/overview.html How does OpenTSDB work? O...

pursue5956
2018/08/07
0
0
小米正用时序数据库,解决这个“硬核”问题

参加 2019 Python开发者日,请扫码咨询 ↑↑↑ 作者 | 许俊红 来源 | 小米云技术(id:mi-cloud-tech) 时序数据 根据维基百科的定义[1],时间序列是一组按照时间发生先后顺序进行排列的数据...

AI科技大本营
03/21
0
0
OpenTSDB 数据会乱套问题

OpenTSDB运行nohup日志: java.lang.IllegalStateException: id=[0, 0, 0, -9] => name=4029, already mapped to 有线宽带开户 java.lang.IllegalStateException: id=[0, 0, 2, -81] => name......

涛涛已经有人使用
2017/02/15
2
0
MySQL 记一次修改root密码

1、正常关闭MySQL服务 [root@mysqlnode02 opentsdb-2.3.0]# systemctl stop mysqld.service 2、修改配置文件my.cnf增加跳过权限认证 [root@mysqlnode02 opentsdb-2.3.0]# vi /etc/my.cnf [m......

PeakFang-BOK
2018/11/14
0
0
OpenTsdb官方文档-----理解指标和时间序列

  OpenTSDB是一个时间序列数据库。时间序列是一段时间内某个特定指标量的一系列数值数据点。每个时间序列由一个指标量加上一个或多个与此指标量相关联的标签组成(我们会稍微介绍一下标签)...

Lynn_Yuan
2018/08/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Confluence 6 升级中的一些常见问题

升级的时候遇到了问题了吗? 如果你想尝试重新进行升级的话,你需要首先重新恢复老的备份。不要尝试再次对 Confluence 进行升级或者在升级失败后重新启动老的 Confluence。 在升级过程中的一...

honeymoose
今天
2
0
C++随笔(四)Nuget打包

首先把自己编译好的包全部准备到一个文件夹 像这样 接下来新建一个文本文档,后缀名叫.nuspec 填写内容 <?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/201......

Pulsar-V
今天
2
0
再谈使用开源软件搭建数据分析平台

三年前,我写了这篇博客使用开源软件快速搭建数据分析平台, 当时收到了许多的反馈,有50个点赞和300+的收藏。到现在我还能收到一些关于dataplay2的问题。在过去的三年,开源社区和新技术的发...

naughty
今天
3
0
Python3的日期和时间

python 中处理日期时间数据通常使用datetime和time库 因为这两个库中的一些功能有些重复,所以,首先我们来比较一下这两个库的区别,这可以帮助我们在适当的情况下时候合适的库。 在Python文...

编程老陆
今天
2
0
分布式面试整理

并发和并行 并行是两个任务同时进行,而并发呢,则是一会做一个任务一会又切换做另一个任务。 临界区 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用,但是每一次,只能有...

群星纪元
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部