[OpenTSDB技术]OpenTSDB简介与使用技巧

  • 参考文章

  • OpenTSDB简介

    • 数据库Schema
      它主要有两个表:tsdb-uid和tsdb,
      • tsdb-uid:描述指标(metrics)相关的元数据
      • tsdb:存储时间序列数据
    • 主要概念

      • metrics:需要收集的一个指标
        • 监控项如cpu_io,可以将metrics写作
          1
          2
          * tag:用于区分每个指标中数据
          * 对于监控项```bmc.stat.cpu```,要区分不同机器,可以设置tag:```host=hostname
    • 说明

      • metrics和tag的关系
        • metrics和tag之间并没有必然的从属关系
        • 但对于一条数据来说,应该含有一个metrics和N>1个tag,这样的数据才是有意义的
      • metrics与tag的存储结构
        • metrics和tag统一放在了tsdb-uid表中存储
        • 格式为:RowKey(自增ID,3字节数组):name:metrics,name:tagk,name:tagv
        • 同时对它们之间的反向关联关系也作了展开存储:把表间关联关系展开,以JOIN的结果为RowKey存储数据
    • 数据存储
      • 栗子A:
        • 2个metrics:proc.stat.cpu和proc.stat.mem,
        • 1条记录: proc.stat.cpu 1297574486 54.2 host=foo type=user
        • 数据表结构:
          • tsdb-uid:
            tsdb-uid
            tsdb-uid
            保存了metric、tagk、tagv的映射关系
            • 第一条记录:
              • rowkey为\x00,含3个qualifier:id:metrics,id:tagk,id:tagv,其值分别是已经添加的所有指标、标签名和标签值的数量
              • 第一条记录是系统生成和维护的
              • 在OpenTSDB的存储中,对于每一个metric、tagk或者tagv都存在从0开始的计数器,每来一个新的metric、tagk或者tagv,对应的计数器就会加1
              • 这里有两个metrics:cpu、mem,两个key:host、type,两个value:foo、user,所以 rowkey为\x00的三个数据的value都是2
            • 其他记录:
              • 每一个metric、tagk、tagv…键值对组合({metrics:proc.stat.mem,tagk:type,tagv:user}),当新增的组合创建的时候,原来没有的metric或tag会被分配一个唯一标识叫做UID,这个UID会根据现有表的(一个条件)决定是复用还是新增
              • 不同的键值对组合在一起可以创建一个序列的UID,即TSUID
              • 当data point写到TSD时,UID是自动分配的。你也可以手动分配UID,前提是auto metric被设置为true
          • tsdb:
            tsdb
            tsdb
            • Rowkey(TSUID):
              • 指标UID(三字节整数)
              • + 数据生成时间(取整点时间)
              • + 标签1-Key的UID(三字节整数)
              • + 标签1-Vlaue的UID(三字节整数)
              • +…
              • + 标签N-Key的UID
              • + 标签N-Vlaue的UID
            • 时间处理:
              • 数据时间戳:
                • 2011-02-13 13:21:26 = 1297574486
              • Rowkey 包含信息:
                • MWeP = 01001101 01010111 01100101 01010000 = 1297573200 = 2011-02-13 13:00:00 (截取整点小时位)
              • CF:Q 包含信息:
                • PK = 01010000 01101011 = 1286 (从整点小时到记录时间的秒偏差,1286秒正是21分钟26秒)
              • 结合Rowkey与CF:Q:
                • 1297573200+1286=1297574486
            • 一行数据:
              为了方便后期更进一步的节省空间。OpenTSDB将一个小时的数据,保存在一行里面,即一小时,一个统计项相同标签组合的数据,只有一个Rowkey,每秒钟的数据都会存为一列,大大提高查询的速度:
              • Rowkey
                • 统计项 + 整点时间段 + 标签组合
              • Column
                • 时刻
              • TS
                • 同一时刻统计数据的版本
              • Value
                • 统计值
          • tsdb-meta:元数据
            用来存储时间序列索引和元数据的表。这也是一个可选特性,默认是不开启的,可以通过配置文件来启用该特性,
          • tsdb-tree:树形表
            以树状层次关系来表示metric的结构,只有在配置文件开启该特性后,才会使用此表
    • 存取数据

      • 写入数据

        $ curl -X POST -H “Content-Type: application/json” http://localhost:4242/api/put -d @test.json
        $ vim test.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"
                }
            }
        ]
        
      • 查询数据
        查询数据可以使用query接口,它既可以使用get的query string方式,也可以使用post方式以JSON格式指定查询条件,这里使用post接口,对刚才保存的数据进行说明

        $ curl -s -X POST -H "Content-Type: application/json" http://localhost:4242/api/query -d @search.json
        $ vim search.json
        {
            "start": 1435716527,
            "queries": [
                {
                    "metric": "mysql.innodb.row_lock_time",
                    "aggregator": "avg",
                    "filiters": {
                        "host": "*",
                        "dc": "beijing"
                    }
                }
            ]
        }
        
    • 使用技巧

      • 针对Hot Spot的应对策略
        • rowkey开始位置挑选了自身的一个理想的业务字段“metrics”来作为打破Hot Spot的“哈希”字段
      • 三字节存储带来的问题
        metric也好,tagk或者tagv也好,uid只有3个字节,这是 OpenTSDB 的默认配置,三个字节,应该能表示1600多万的不同数据,这对metric名或者tagk来说足够长了,对tagv来说就不一定了,比如tagv是ip地址的话,或者电话号码,那么这个字段就不够长了,这时可以通过修改源代码来重新编译 OpenTSDB 就可以了,同时要注意的是,重编以后,老数据就不能直接使用了,需要导出后重新导入
      • 采集程序:
        OpenTSDB已经自带了收集监控数据的一些脚本。主要由2个部分组成,TCollector和一些具体的collectors。
        • TCollector是1个客户端进程,它主要是收集具体的collectors收集到的监控数据,然后负责将数据推送到TSDB;
        • TCollector会处理和TSD的连接和协议处理,具体的collectors负责收集数据即可
        • 目前OpenTSDB提供了一些已实现的collectors
          tcollector
        • 在一个服务器上部署1个TCollector之后,它会把这些collectors启动起来,collectors收集到监控数据之后,输出到stdout,TCollector接收后推送到OpenTSDB