OpenTsdb Row_Key的计算方法
最近笔者公司开始使用TSDB,但很多同事反馈看不懂row_key怎么计算出来的,不方便调试核对,因此特写本文供同事调试使用。由于只是讲解如何计算,因此不涉及TSDB理论及为什么会这样,有兴趣的同学可以自行google
TSDB RowKey设计规则介绍
TSDB作为基于HBase的时序数据库,其最大的特点就在于其row_key的设计上。row_key的规则方式如下:metric +timestamp+tagk1+tagv1+...tagkN+tagvN。所谓的metric指的是采集的指标项,如sys.cpu.user。timestamp指的是采集数据的具体时间;tagk,tagv是一对key-value值,主要值与该指标项相关的属性如host,ip等信息。如果有多组这样的信息就依次填入,但是需要留意的是其中的顺序。
TSDB 的主要构成
TSDB 主要由4个表构成,分别是tsdb(存储元数据)、tsdb-uid(存储元数据的id),tsdb-meta,tsdb-tree其中后面2个表主要是存储对应关系优化所用,可以暂时不考虑。
注意:由于公司的缘故,后面实际使用的库名有所变化,但是功能是完全一致的,如果需要修改连接的库的名字,直接在tsdb.conf中修改连接的库名即可。
写入一个新的采集数据记录
这里先写入一条从来没有的metric记录,以便查看举例。
写入的主要内容为:
{
"metric": "dev.net.app.collect.rate",
"timestamp": 1506652821,
"value": "70",
"tags": {
"host_name":"collect_node_1",
"host_ip":"192.168.10.2"
}
}
TSDB 提供了完善的读写操作,只需要发送http request PUT请求即可,如发送的http://tsdb_ip:14242/api/put。
这里说明一下,此处的timestamp时间为unxi北京时间(2017/9/29 10:40:21),单位是秒,如果是毫秒的话,略有区别。
写完数据以后,我们先查看wishdb-uid表。
可以看到这个metric已经写入,其对应的值是“\x00\x00\x13”,这个值是根据顺序自动生成的,由于wishdb-uid是双向的,也就是可以根据这个值(作为row-key)+metric(作为列名)查看其对应的值:
其他的tag和tagv 也和metric一样都能找到对应的双向值。
在查看的过程中发现每行一定是3列,metric,tagk,tagv如果有一行缺失某一个值的话,后面讲递增补上前面的列,以便保持整个hbase的数据均衡。、
看完了widb-uid表,接着看wish-db表。
这表的内容完全看不懂啊。没办法,row_key在hbase中采用二进制的方式存储,提高了性能,在可视化方面就只能妥协了。由于我们是预知存入的数据的,所以我们先根据存入的数据来倒找是哪一条记录,然后在说明这条记录的row_key是怎么来的。
由于今天笔者的环境只插入了这一条记录,所以用时间过滤的方式很容易找到:
果然只有一条记录,但是这里的值怎么是“F”,我们传入的值不是70吗,是不是错了?没有错,F就是70。在这里的F是显示表示的,F是ASCII码,我们一查ASCII码,F对应的十进制数就恰好是:70,所以没错就是这条记录。
Row_key解读
Row_Key :\x00\x00\x13 Y\xCD\xA9\x00 \x00\x0F\x00 \x00-\x00\x00\x10\x00\x00
根据Row_key的设计规范:前面3个字节代表的metric。本例就是:0x00,0x00,0x13将其放入wishdb-uid中查询可以得知其代表的是“dev.net.app.collect.rate”;往后4个字节代表时间戳,本例后面4个字节为:Y \XCD \xA9 。(A9后面是空格),首先将Y这个ASCII码转化为十六进制数:0x59,空格的十六进制数是0x20。将其转换为10进制后数据变为:1506650400,北京时间就是“2017/9/29 10:00:00”。这里变成整点而不是当时传递的10点40多分,是因为TSDB设计的原则就是row_key中存储的是整点,而列名才代表多少秒所导致,至于具体的原因由于这里只讲述操作,就不再累述了。
看完了时间戳,再看tagk和tagv。tag都是3个字节的,因此tagk1就是\x00\x00\x0F,tagv1是\x00\x00-;tagk2的值是\x00\x00\x10,tagv2的值是\x00\x00.。
查询db-uid的对应关系可以得出以下关系:
tagk的对应关系:
tagv的对应关系:
tag1(\x00\x00\x0F)代表的是:host_ip,其对应的值tagv的值(\x00\x00-)代表的是:192.168.10.2。同理tag2(\x00\x00\x10)代表的是host_name 其值tagv(\x00\x00.)代表的是:collect_node_1 。
这样row_key中的tagk,tagv值就完全和我们最开始发送的值对应上了。
列名解读
前面讲完了row-key的计算方法,现在继续描述列。前面提到row-key中只存储整点小时,而列名存储的是与整点的相对时间,这里我们以秒为单位,1个小时3600秒,理论上说一行最多可以有3600列。
根据上面的截图,我们可以看到只有一个列,列名叫\x97P。老规矩先把P这个ASCII码转换了再说,转换后列名变成了\x97\x50。列名这里的转换对应和前面的tag时间戳有所不同,因为3600用不到2个字节来存储。因此,在转换的时候,我们只取12位即可。我们先建值全部转化为2进制数(1001 0111 0101 0000)。去掉后面的4位,变成(100101110101)换算成十进制就是2421秒。我们在看真实的数据:
传入的时间戳和row-key中的时间的相对时间是2421秒,二进制就是(1001 0111 0101)完全和列名一致。也就是10点40分21秒