认识时序数据库OpenTSDB

/ TSDBOpenTSDBHbase技术 / 1 条评论 / 5101浏览

alt 继昨天介绍了Hbase,今天顺便也介绍一下OpenTSDB。

什么是 OpenTSDB

OpenTSDB ,可以认为是一个时系列数据(库),它基于HBase存储数据,充分发挥了HBase的分布式列存储特性,支持数百万每秒的读写,它的特点就是容易扩展,灵活的tag机制。

架构简介

alt 其最主要的部件就是TSD了,这是接收数据并存储到HBase处理的核心所在。而带有C(collector)标志的Server,则是数据采集源,将数据发给 TSD服务。每个TSD都是独立的服务,没有leader。

安装 OpenTSDB

安装GnuPlot

# ubuntu 环境安装gunplot
sudo apt-get install gunplot
# centos 安装 gunplot
sudo yum install -y gunplot

安装Hbase

参考安装Hbase

安装 OpenTSDB

如果build失败,那肯定是缺少Make或者Autotools等东西,用包管理器安装即可

$ git clone git://github.com/OpenTSDB/opentsdb.git
$ cd opentsdb
$ ./build.sh

创建表OpenTSDB所需要的表结构:

env COMPRESSION=NONE ./src/create_table.sh

查看habse shell相关的表创建成功

> list
TABLE
tsdb
tsdb-meta
tsdb-tree
tsdb-uid
4 row(s) in 0.0160 seconds

表创建之后,即可启动tsd服务,只需要运行如下命令:

#!/usr/bin/env bash
source /home/aozhang/Documents/company/env/java-1.8-env
staticroot=/home/aozhang/Documents/company/app/opentsdb/build/staticroot
cachedir=/home/aozhang/Documents/company/app/opentsdb/build/cachedir
/home/aozhang/Documents/company/app/opentsdb/build/tsdb tsd --port=4242 --staticroot=$staticroot --cachedir=$cachedir --zkquorum=192.168.31.111 --auto-metric

注意执行上面脚本时,日志读写的目录可能会没权限,如果遇到加上sudo执行,zkquorum指定zookeeper服务地址,默认端口2181--auto-metric表明如果插入的Data pointsmetrics不存在就自动创建

保存数据到OpenTSDB

最简单的保存数据方式就是使用telnet

$ telnet 192.168.31.111 4242

put sys.cpu.user 1436333416 23 host=web01 user=10001

通过http://192.168.31.111:4242 访问

alt

OpenTSDB中的数据存储结构

我们来看看 OpenTSDB 的重要概念uid,先从HBase中存储的数据开始吧,我们来看一下它都有哪些表,以及这些表都是干什么的。

tsdb:存储数据点

hbase(main):003:0> scan 'tsdb'
ROW                                                 COLUMN+CELL   
 \x00\x00\x03U\x9C\xAEP\x00\x00\x01\x00\x00\x01\x00 column=t:q\x80, timestamp=1533643344526, value=\x17
 \x00\x03\x00\x00\x05                                              
1 row(s) in 0.0100 seconds
hbase(main):004:0>

可以看出,该表只有一条数据,我们先不管rowid,只来看看列,只有一列,值为0x17,即十进制23,即该metric的值。 左面的row key则是 OpenTSDB 的特点之一,其规则为:

metric + timestamp + tagk1 + tagv1… + tagkN + tagvN

以上属性值均为对应名称的uid。

我们上面添加的metric为:

sys.cpu.user 1436333416 23 host=web01 user=10001

一共涉及到5个uid,即名为sys.cpu.user的metric,以及host和user两个tagk及其值web01和10001。 上面数据的row key为:

\x00\x00\x03U\x9C\xAEP\x00\x00\x01\x00\x00\x01\x00\x00\x03\x00\x00\x05

具体这个row key是怎么算出来的,我们来看看tsdb-uid表。

tsdb-uid:存储name和uid的映射关系

tsdb-uid用来保存名字和UID(metric,tagk,tagv)之间互相映射的关系,都是成组出现的,即给定一个name和uid,会保存(name,uid)和(uid,name)两条记录。

hbase(main):004:0> scan 'tsdb-uid'
\x00\x00\x01                                       column=name:tagv, timestamp=1533527119974, value=web01 
\x00\x00\x01                                       column=name:tagk, timestamp=1533527119948, value=host
\x00\x00\x03                                       column=name:metrics, timestamp=1533643343251, value=sys.cpu.user
\x00\x00\x03                                       column=name:tagk, timestamp=1533643343270, value=user
\x00\x00\x05                                       column=name:tagv, timestamp=1533643343283, value=10001

10001                                              column=id:tagv, timestamp=1533643343286, value=\x00\x00\x05
host                                               column=id:tagk, timestamp=1533527119952, value=\x00\x00\x01
sys.cpu.user                                       column=id:metrics, timestamp=1533643343255, value=\x00\x00\x03
user                                               column=id:tagk, timestamp=1533643343273, value=\x00\x00\x03 
web01                                              column=id:tagv, timestamp=1533527119980, value=\x00\x00\x01
\x00\x00\x03  + U +  \x9C\xAE + P +      \x00\x00\x01           +  \x00\x00\x03 + \x00\x00\x05
sys.cpu.user       1436333416           host    =      web01          user         10001

可以看出,这和我们前面说到的row key的构成方式是吻合的。 需要着重说明的是时间戳的存储方式。虽然我们指定的时间是以秒为单位的,但是,row key中用到的却是以一小时为单位的,即:1436333416 – 1436333416 % 3600 = 1436331600 。 1436331600转换为16进制,即0x55 0x9c 0xae 0x50,而0x55即大写字母U,0x50为大写字母P,这就是4个字节的时间戳存储方式。相信下面这张图能帮助各位更好理解这个意思,即一小时只有一个row key,每秒钟的数据都会存为一列,大大提高查询的速度。

alt

重要:我们看到,上面的metric也好,tagk或者tagv也好,uid只有3个字节,这是 OpenTSDB 的默认配置,三个字节,应该能表示1600多万的不同数据,这对metric名或者tagk来说足够长了,对tagv来说就不一定了,比如tagv是ip地址的话,或者电话号码,那么这个字段就不够长了,这时可以通过修改源代码来重新编译 OpenTSDB 就可以了,同时要注意的是,重编以后,老数据就不能直接使用了,需要导出后重新导入。

tsdb-meta:元数据表

我们再看下第三个表tsdb-meta,这是用来存储时间序列索引和元数据的表。这也是一个可选特性,默认是不开启的,可以通过配置文件来启用该特性,这里不做特殊介绍了。

tsdb-tree:树形表

第4个表是tsdb-tree,用来以树状层次关系来表示metric的结构,只有在配置文件开启该特性后,才会使用此表,这里我们不介绍了,可以自己尝试

通过HTTP接口保存数据

假设我们有如下数据,保存为文件mysql.json:

[
    {
        "metric": "mysql.innodb.row_lock_time",
        "timestamp": 1435716527,
        "value": 1234,
        "tags": {
           "host": "web01",
           "dc": "beijing"
        }
    },
    {
        "metric": "mysql.innodb.row_lock_time",
        "timestamp": 1435716529,
        "value": 2345,
        "tags": {
           "host": "web01",
           "dc": "beijing"
        }
    },
    {
        "metric": "mysql.innodb.row_lock_time",
        "timestamp": 1435716627,
        "value": 3456,
        "tags": {
           "host": "web02",
           "dc": "beijing"
        }
    },
    {
        "metric": "mysql.innodb.row_lock_time",
        "timestamp": 1435716727,
        "value": 6789,
        "tags": {
           "host": "web01",
           "dc": "tianjin"
        }
    }
]

之后执行如下命令:

curl -X POST -H "Content-Type: application/json" http://192.168.31.111:4242/api/put -d @data-points1.json

查看数据 http://192.168.31.111:4242/#start=2015/07/01-10:07:04&end=2015/07/01-10:20:01&m=sum:opentsdb.test&o=&m=sum:mysql.innodb.row_lock_time&o=&yrange=%5B0:%5D&key=top%20right%20box&wxh=1420x564&style=linespoint

查询数据

查询数据可以使用query接口,它既可以使用get的query string方式,也可以使用post方式以JSON格式指定查询条件,这里我们以后者为例,对刚才保存的数据进行说明。

首先,保存如下内容为search.json:

{
    "start": 1435716527,
    "queries": [
        {
            "metric": "mysql.innodb.row_lock_time",
            "aggregator": "avg",
            "tags": {
                "host": "*",
                "dc": "beijing"
            }
        }
    ]
}

执行如下命令进行查询:

$ curl -s -X POST -H "Content-Type: application/json" http://localhost:4242/api/query -d @search.json | jq .
[
  {
    "metric": "mysql.innodb.row_lock_time",
    "tags": {
      "host": "web01",
      "dc": "beijing"
    },
    "aggregateTags": [],
    "dps": {
      "1435716527": 1234,
      "1435716529": 2345
    }
  },
  {
    "metric": "mysql.innodb.row_lock_time",
    "tags": {
      "host": "web02",
      "dc": "beijing"
    },
    "aggregateTags": [],
    "dps": {
      "1435716627": 3456
    }
  }
]

可以看出,我们保存了dc=tianjin的数据,但是并没有在此查询中返回,这是因为,我们指定了dc=beijing这一条件。

总结

可以看出来, OpenTSDB 还是非常容易上手的,尤其是单机版,安装也很简单。有HBase作为后盾,查询起来也非常快,很多大公司,类似雅虎等,也都在用此软件。但是,大规模用起来,多个TDB以及多存储节点等,应该都需要专业、细心的运维工作了。

  1. df

    hello~

    回复