opentsdb探索之路——部分设计与实现
基于opentsdb-2.4.0版本,本篇开启opentsdb探索之路(主要涉及读写特性以及一些其他细节),下一篇将开启opentsdb优化之路——性能优化思路与建议(总结当前痛点问题、优化思路和解决方案,同时也欢迎朋友提出更好的思路与方案)。
注意:阅读本篇文章应该要对HBase有基本的认识,比如rowkey、region、store、 ColumnFamily、ColumnQualifier等概念以及HBase逻辑结构、物理存储结构有大致的认知。
opentsdb 概览(overview)#
上图取自官方http://opentsdb.net/overview.html。其中的TSD(对应实际进程名是TSDMain)就是opentsdb组件。每个实例TSD都是独立的。没有master,没有共享状态(shared state),因此实际生产部署可能会通过nginx+Consul运行多个TSD实例以实现负载均衡。
Each TSD uses the open source database HBase or hosted Google Bigtable service to store and retrieve time-series data
我们大多应该还是用HBase作为数据存储。
安装部署一文中提到过在HBase中创建表结构,这里先简单介绍一下这4张表(table),随着探究的深入会对tsdb和tsdb-uid这两张表有更深刻的认识,至于tsdb-meta、tsdb-tree两张表不是这里讨论的重点,简单了解一下即可。相关文档:http://opentsdb.net/docs/build/html/user_guide/backends/index.html
- tsdb:
opentsdb全部的时序数据都存在这张表中,该表只有一个名为"t"的列族(ColumnFamily)。所以这张表的数据非常大,大多情况下读写性能瓶颈也就与这张表密切相关,进而优化也可能与它相关。
rowkey的设计为an optional salt, the metric UID, a base timestamp and the UID for tagk/v pairs,即[可选的salt位+metric的UID+小时级别的时间戳+依次有序的tagk、tagv组成的UID键值对],如下:
[salt]<metric_uid><timestamp><tagk1><tagv1>[...<tagkN><tagvN>]
暂不考虑salt位,关于加salt下面有章节单独拿出来看它的设计与实现。来看一个不加salt且含有两个tag的时序数据的rowkey组成:
00000150E22700000001000001000002000004
'----''------''----''----''----''----'
metric time tagk tagv tagk tagv
至于rowkey为什么要这样设计以及具体实现,后面详细介绍,这里先有个基本认知。
- tsdb-uid: 为了减少
rowkey的长度,opentsdb会将metric、tagk、tagv都映射成UID,映射是双向的,比如说既可以根据tagk找到对应的UID,也可以根据UID直接找到相应的tagk。而这些映射关系就记录在tsdb-uid表中。该表有两个ColumnFamily,分别是name和id,另外这两个ColumnFamily下都有三列,分别是metric、tagk、tagv。如下图所示:
| RowKey | id:metric | id:tagk | id:tagv | name:metric | name:tagk | name:tagv |
|---|---|---|---|---|---|---|
| metric01 | 0x01 | |||||
| metric02 | 0x02 | |||||
| tagk01 | 0x01 | |||||
| tagv01 | 0x01 | |||||
| tagv02 | 0x02 | |||||
| 0x01 | metric01 | |||||
| 0x01 | tagk01 | |||||
| 0x01 | tagv01 | |||||
| 0x02 | metric02 | |||||
| 0x02 | tagv02 | |||||
从上面可以看出,metric、tagk、tagv三种类型的UID映射互不干扰,这也就使得0x01这个UID在不同类型中有着不同的含义。后面会从源码角度讲一下uid大致的分配。 |
相关文章