TSDB写入与查询讲解,聚合(aggregator)与采样(downsample)讲解—以opentsdb为例

1.时序数据库与时序数据概论

      时序数据库是非关系型数据库的一种,其全称为时间序列数据库(Time Series Database)。时序数据库主要用于存取具有时间特征的数据。

      时序数据是随时间产生的数据,其有着产生频率快、依赖时间、数据量庞大的特点。由于时序数据的数据量非常庞大,传统的关系型数据库在底层数据结构(可参见笔者文章)上导致了其无法对该类数据进行有效的存储和管理。数据数据库通过时序数据的特性,对时序数据采用特殊的存储方式,这使时序大数据得到了有效的管理。

      例如,基于HBase的opentsdb,其采用“数据便是索引”的存储方式(关于HBase数据结构,可参加笔者相关文章),使得主键索引的利用更加高效,在大量、高并发的查询时,极大地降低了系统的I/O。

2.数据写入与查询(http接口形式)

以opentsdb为例:

1)数据写入:

官方文档地址:http://opentsdb.net/docs/build/html/api_http/put.html

数据写入数据结构:

[
    {
        "metric":"city.temperature",
        "value":"24.7",
        "timestamp":1572331517,
        "tags":
            {
                "city":"beijing"
            }
    }
]

以上示例便为各大TSDB常见的数据结构。metric为指标,value为该指标在该时刻的值,timestamp为时间戳,tags便为该指标的标记。

如上图所示,我们这条数据上报成功了。

2)数据查询

官方文档地址:http://opentsdb.net/docs/build/html/api_http/query/index.html

数据查询常用数据结构:

{
    "start": 1572331507,
    "end": 1572331527,
    "queries": [
        {
            "aggregator": "",
            "metric": "city.temperature",
            "downsample": "",
            "rate": true,
            "filters": [
                {
                    "type": "literal_or",
                    "tagk": "city",
                    "filter": "beijing",
                    "groupBy": false
                }
            ]
        }
    ]
}

字段说明:start查询开始时间,end查询结束时间,queries为查询的基本操作,aggregator为聚合方式(如avg、max、min、last、sum等),metric为查询的指标,downsample为采样方式(如1min-avg-null、1h-max-zero等,形式为采样时间-采样方式-补值策略),rate为是否求速率(根据需要决定),filters为根据tag进行过滤查询,type常用的为literal_or(查询的tag值之间为或的关系)和wildcard(使用通配符),groupBy为是否分组,将在下面进一步说明。

3.关于aggregator与downsample

时序数据是以时间线(TS)的形式存储在TSDB中的,现在,我们再上报1个城市的数据,并且对城市北京补充一些温度值:

[
    {
        "metric":"city.temperature",
        "value":"24.7",
        "timestamp":1572331517,
        "tags":
            {
                "city":"beijing"
            }
    },
    {
        "metric":"city.temperature",
        "value":"23",
        "timestamp":1572331577,
        "tags":
            {
                "city":"beijing"
            }
    },
    {
        "metric":"city.temperature",
        "value":"21",
        "timestamp":1572331637,
        "tags":
            {
                "city":"beijing"
            }
    },
    {
        "metric":"city.temperature",
        "value":"27",
        "timestamp":1572331517,
        "tags":
            {
                "city":"shanghai"
            }
    },
    {
        "metric":"city.temperature",
        "value":"24",
        "timestamp":1572331577,
        "tags":
            {
                "city":"shanghai"
            }
    },
    {
        "metric":"city.temperature",
        "value":"22",
        "timestamp":1572331637,
        "tags":
            {
                "city":"shanghai"
            }
    }
]

新的全部数据如上所示,其在TSDB中的时间线如下图所示:

在TSDB中,时间线的组织是以metric和tags进行组织的,例如,如果再上报一条:

[
    {
        "metric":"city.temperature",
        "value":"24.7",
        "timestamp":1572331517,
        "tags":
            {
                "city":"beijing",
                "address":"tiananmen"
            }
    }
]

此时便会变为三条时间线,因此,只要metric和tag有任何不一样,便会产生一条时间线。

1)aggregator为不同时间线间数据的聚合方式,例如在上面的两条时间线中,我们要求每一时刻的两个城市(所有城市)的温度之和,可以这样请求:

在这个请求中,我们将aggregator设置为sum(当然也可以尝试max、min等),此时便求出了两个城市在不同时间的温度之和,aggregator的时间线操作如下图所示:

2)关于downsample,假如我们一秒一个点,这样会导致数据点繁多,为了解决这个问题,我们可以对1分钟(或5分钟等等)的数据进行采样,比如,我们想对北京这个城市的温度每5分钟进行一个采样,采样方式为去平均值,我们可以这样请求:

在上面的请求中,我们的采样方式为每五分钟进行采样,采样方式为取平均值,没有值时补值为null。downsample的时间线操作如下:

3)关于groupBy,group为对不同的tags是否进行分组,如果值为true,则为分组,如上两条时间线,分组查询会返回两条时间线:

返回如下:

[
    {
        "metric": "city.temperature",
        "tags": {
            "city": "shanghai"
        },
        "aggregateTags": [],
        "dps": {
            "1572331500": 24.333333333333332,
            "1572331800": null,
            "1572332100": null
        }
    },
    {
        "metric": "city.temperature",
        "tags": {
            "city": "beijing"
        },
        "aggregateTags": [],
        "dps": {
            "1572331500": 22.900000000000002,
            "1572331800": null,
            "1572332100": null
        }
    }
]

如果值为false,则为不分组,如上两条时间线,不分组查询会返回一条时间线:

返回如下:

[
    {
        "metric": "city.temperature",
        "tags": {},
        "aggregateTags": [
            "city"
        ],
        "dps": {
            "1572331500": 23.616666666666667,
            "1572331800": null,
            "1572332100": null
        }
    }
]

注:本例中我们同时使用了聚合方式和采样方式。

猜你喜欢

转载自blog.csdn.net/m0_38075425/article/details/102798586