时序数据库简介和influxdb部署

时序数据库

 

一、   背景

2017 年时序数据库忽然火了起来。开年 2 月 Facebook 开源了 beringei 时序数据库;到了 4 月基于 PostgreSQL 打造的时序数据库 TimeScaleDB 也开源了,而早在 2016 年 7 月,百度云在其天工物联网平台上发布了国内首个多租户的分布式时序数据库产品 TSDB,成为支持其发展制造,交通,能源,智慧城市等产业领域的核心产品,同时也成为百度战略发展产业物联网的标志性事件。时序数据库作为物联网方向一个非常重要的服务,业界的频频发声,正说明各家企业已经迫不及待的拥抱物联网时代的到来。

百度无人车在运行时需要监控各种状态,包括坐标,速度,方向,温度,湿度等等,并且需要把每时每刻监控的数据记录下来,用来做大数据分析。每辆车每天就会采集将近 8T 的数据。如果只是存储下来不查询也还好(虽然已经是不小的成本),但如果需要快速查询“今天下午两点在后厂村路,速度超过 60km/h 的无人车有哪些”这样的多纬度分组聚合查询,那么时序数据库会是一个很好的选择。

二、     什么是时序数据库

时序数据是基于时间的一系列的数据。在有时间的坐标中将这些数据点连成线,往过去看可以做成多纬度报表,揭示其趋势性、规律性、异常性;往未来看可以做大数据分析,机器学习,实现预测和预警。

时序数据库就是存放时序数据的数据库,并且需要支持时序数据的快速写入、持久化、多纬度的聚合查询等基本功能。

对比传统数据库仅仅记录了数据的当前值,时序数据库则记录了所有的历史数据。同时时序数据的查询也总是会带上时间作为过滤条件。

三、     时序数据库的基本概念不(同的时序数据库称呼略有不同)

metric: 度量,相当于关系型数据库中的 table。

data point: 数据点,相当于关系型数据库中的 row。

timestamp:时间戳,代表数据点产生的时间。

field: 度量下的不同字段。比如位置这个度量具有经度和纬度两个 field。一般情况下存放的是会随着时间戳的变化而变化的数据。

tag: 标签,或者附加信息。一般存放的是并不随着时间戳变化的属性信息。timestamp 加上所有的 tags 可以认为是 table 的 primary key。

 

ISERDESE2时序 b die 时序_数据

四、     数据的存储

1.         单机存储

如果只是存储起来,直接写成日志就行。但因为后续还要快速的查询,所以需要考虑存储的结构。

传统数据库存储采用的都是 B tree,这是由于其在查询和顺序插入时有利于减少寻道次数的组织形式。我们知道磁盘寻道时间是非常慢的,一般在 10ms 左右。磁盘的随机读写慢就慢在寻道上面。对于随机写入 B tree 会消耗大量的时间在磁盘寻道上,导致速度很慢。我们知道 SSD 具有更快的寻道时间,但并没有从根本上解决这个问题。

对于 90% 以上场景都是写入的时序数据库,B tree 很明显是不合适的。

业界主流都是采用 LSM tree 替换 B tree,比如 Hbase, Cassandra 等 nosql 中。这里我们详细介绍一下。

LSM tree 包括内存里的数据结构和磁盘上的文件两部分。分别对应 Hbase 里的 MemStore 和 HLog;对应 Cassandra 里的 MemTable 和 sstable。

LSM tree 操作流程如下:

数据写入和更新时首先写入位于内存里的数据结构。为了避免数据丢失也会先写到 WAL 文件中。

内存里的数据结构会定时或者达到固定大小会刷到磁盘。这些磁盘上的文件不会被修改。

随着磁盘上积累的文件越来越多,会定时的进行合并操作,消除冗余数据,减少文件数量。

 

ISERDESE2时序 b die 时序_数据_02

p4-Hbase LSM tree 结构介绍(注 1)

可以看到 LSM tree 核心思想就是通过内存写和后续磁盘的顺序写入获得更高的写入性能,避免了随机写入。但同时也牺牲了读取性能,因为同一个 key 的值可能存在于多个 HFile 中。为了获取更好的读取性能,可以通过 bloom filter 和 compaction 得到,这里限于篇幅就不详细展开。

2.        分布式存储

时序数据库面向的是海量数据的写入存储读取,单机是无法解决问题的。所以需要采用多机存储,也就是分布式存储。

分布式存储首先要考虑的是如何将数据分布到多台机器上面,也就是 分片(sharding)问题。下面我们就时序数据库分片问题展开介绍。分片问题由分片方法的选择和分片的设计组成。

3.        分片方法

时序数据库的分片方法和其他分布式系统是相通的。

哈希分片:这种方法实现简单,均衡性较好,但是集群不易扩展。

一致性哈希:这种方案均衡性好,集群扩展容易,只是实现复杂。代表有 Amazon 的 DynamoDB 和开源的 Cassandra。

范围划分:通常配合全局有序,复杂度在于合并和分裂。代表有 Hbase。

4.        分片设计

分片设计简单来说就是以什么做分片,这是非常有技巧的,会直接影响写入读取的性能。

结合时序数据库的特点,根据 metric+tags 分片是比较好的一种方式,因为往往会按照一个时间范围查询,这样相同 metric 和 tags 的数据会分配到一台机器上连续存放,顺序的磁盘读取是很快的。再结合上面讲到的单机存储内容,可以做到快速查询。

进一步我们考虑时序数据时间范围很长的情况,需要根据时间范围再将分成几段,分别存储到不同的机器上,这样对于大范围时序数据就可以支持并发查询,优化查询速度。

如下图,第一行和第三行都是同样的 tag(sensor=95D8-7913;city= 上海),所以分配到同样的分片,而第五行虽然也是同样的 tag,但是根据时间范围再分段,被分到了不同的分片。第二、四、六行属于同样的 tag(sensor=F3CC-20F3;city= 北京)也是一样的道理。

 

ISERDESE2时序 b die 时序_时序数据库_03

 

五、     时序数据库特点和分类

专门优化用于处理时间序列数据

1)该类数据以时间排序

2)由于该类数据通常量级大(因此Sharding和Scale非常重要)或逻辑复杂(大量聚合,上取,下钻),关系数据库通常难以处理

3)时间序列数据按特性分为两类

4)高频率低保留期(数据采集,实时展示)

5)低频率高保留期(数据展现、分析)

按频度

1)规则间隔(数据采集)

2)不规则间隔(事件驱动)

 时间序列数据的几个前提

1)单条数据并不重要

2)数据几乎不被更新,或者删除(只有删除过期数据时),新增数据是按时间来说最近的数据

3)同样的数据出现多次,则认为是同一条数据

六、     InfluxDB和ElasticSearch比较

 

ISERDESE2时序 b die 时序_数据库_04

1.    时间序列数据库关键比对

InfluxDB

ElasticSearch

流行(TSDB排行第一)

流行(搜索引擎排行第一)

高可用需要收费

集群高可用容易实现,免费

单点写入性能高

单点写入性能低

查询语法简单,功能强

查询语法简单,功能强(弱于Influxdb)

后端时序数据库设计,写入快

设计并不是时序数据库,后端存储采用文档结构,写入慢

由此可见:高频度低保留期用Influxdb,低频度高保留期用ES。

2.    数据的查询与写入:

1)Influxdb与ES都是REST API风格接口

2)通过HTTP Post写入数据,通过HTTP Get获取数据,ES还有HTTP Put和Delete等

3)写入数据可以是JSON格式,Influxdb支持Line Protocol

4)JSON格式徒增解析成本,录入数据格式越简单越好

5)通常ES搭配Logstash使用,Influxdb搭配telegraf使用

七、     InfluxDB

1.    基本概念

1) 数据格式

在 InfluxDB 中,我们可以粗略的将要存入的一条数据看作一个虚拟的 key 和其对应的 value(field value)。格式如下:

cpu_usage,host=server01,region=us-west  value=0.64 1434055562000000000

虚拟的 key 包括以下几个部分: database, retention policy, measurement, tag sets, field name, timestamp。

database: 数据库名,在 InfluxDB 中可以创建多个数据库,不同数据库中的数据文件是隔离存放的,存放在磁盘上的不同目录。

retention policy: 存储策略,用于设置数据保留的时间,每个数据库刚开始会自动创建一个默认的存储策略 autogen,数据保留时间为永久,之后用户可以自己设置,例如保留最近2小时的数据。插入和查询数据时如果不指定存储策略,则使用默认存储策略,且默认存储策略可以修改。InfluxDB 会定期清除过期的数据。

measurement: 测量指标名,例如 cpu_usage 表示 cpu 的使用率。

tag sets: tags 在 InfluxDB 中会按照字典序排序,不管是 tagk 还是 tagv,只要不一致就分别属于两个 key,例如 host=server01,region=us-west 和 host=server02,region=us-west 就是两个不同的 tag set。

tag--标签,在InfluxDB中,tag是一个非常重要的部分,表名+tag一起作为数据库的索引,是“key-value”的形式。

field name: 例如上面数据中的 value 就是 fieldName,InfluxDB 中支持一条数据中插入多个 fieldName,这其实是一个语法上的优化,在实际的底层存储中,是当作多条数据来存储。

timestamp: 每一条数据都需要指定一个时间戳,在 TSM 存储引擎中会特殊对待,以为了优化后续的查询操作。

2) 与传统数据库中的名词做比较

influxDB中的名词

传统数据库中的概念

database

数据库

measurement

数据库中的表

points

表里面的一行数据

3) Point

Point由时间戳(time)、数据(field)、标签(tags)组成。

Point属性

传统数据库中的概念

time

每个数据记录时间,是数据库中的主索引(会自动生成)

fields

各种记录值(没有索引的属性)

tags

各种有索引的属性

4) Series

  Series 相当于是 InfluxDB 中一些数据的集合,在同一个 database 中,retention policy、measurement、tag sets 完全相同的数据同属于一个 series,同一个 series 的数据在物理上会按照时间顺序排列存储在一起。

5) Shard

Shard 在 InfluxDB 中是一个比较重要的概念,它和 retention policy 相关联。每一个存储策略下会存在许多 shard,每一个 shard 存储一个指定时间段内的数据,并且不重复,例如 7点-8点 的数据落入 shard0 中,8点-9点的数据则落入 shard1 中。每一个 shard 都对应一个底层的 tsm 存储引擎,有独立的 cache、wal、tsm file。

6)       组件

TSM 存储引擎主要由几个部分组成: cache、wal、tsm file、compactor。

 

ISERDESE2时序 b die 时序_数据_05

 

1)Cache:cache 相当于是 LSM Tree 中的 memtabl。插入数据时,实际上是同时往 cache 与 wal 中写入数据,可以认为 cache 是 wal 文件中的数据在内存中的缓存。当 InfluxDB 启动时,会遍历所有的 wal 文件,重新构造 cache,这样即使系统出现故障,也不会导致数据的丢失。

cache 中的数据并不是无限增长的,有一个 maxSize 参数用于控制当 cache 中的数据占用多少内存后就会将数据写入 tsm 文件。如果不配置的话,默认上限为 25MB,每当 cache 中的数据达到阀值后,会将当前的 cache 进行一次快照,之后清空当前 cache 中的内容,再创建一个新的 wal 文件用于写入,剩下的 wal 文件最后会被删除,快照中的数据会经过排序写入一个新的 tsm 文件中。

2)WAL:wal 文件的内容与内存中的 cache 相同,其作用就是为了持久化数据,当系统崩溃后可以通过 wal 文件恢复还没有写入到 tsm 文件中的数据。

3)TSM File:单个 tsm file 大小最大为 2GB,用于存放数据。

4)Compactor:compactor 组件在后台持续运行,每隔 1 秒会检查一次是否有需要压缩合并的数据。

主要进行两种操作,一种是 cache 中的数据大小达到阀值后,进行快照,之后转存到一个新的 tsm 文件中。

另外一种就是合并当前的 tsm 文件,将多个小的 tsm 文件合并成一个,使每一个文件尽量达到单个文件的最大大小,减少文件的数量,并且一些数据的删除操作也是在这个时候完成。

7) 目录与文件结构

InfluxDB 的数据存储主要有三个目录。默认情况下是 meta, wal 以及 data 三个目录。

meta 用于存储数据库的一些元数据,meta 目录下有一个 meta.db 文件。

 

ISERDESE2时序 b die 时序_数据库_06

wal 目录存放预写日志文件,以 .wal 结尾。

 

ISERDESE2时序 b die 时序_时序数据库_07

data 目录存放实际存储的数据文件,以 .tsm 结尾。

 

ISERDESE2时序 b die 时序_ISERDESE2时序_08

上面几张图中,_internal为数据库名,monitor为存储策略名称,再下一层目录中的以数字命名的目录是 shard 的 ID 值。

存储策略下有两个 shard,ID 分别为 1 和 2,shard 存储了某一个时间段范围内的数据。再下一级的目录则为具体的文件,分别是 .wal 和 .tsm 结尾的文件。

 

2.    安装部署

从网上下载influxdb-1.2.4_windows_amd64,如果你是linux用户,请下载linux相关版本。

解压后的文件如下:

 

ISERDESE2时序 b die 时序_数据库_09

修改influxdb.conf,修改内容如下:

meta部分 

 

ISERDESE2时序 b die 时序_时序数据库_10

data部分

 

ISERDESE2时序 b die 时序_数据库_11

retention部分 

 

ISERDESE2时序 b die 时序_数据_12

shard-percreation部分 

 

ISERDESE2时序 b die 时序_时序数据库_13

monitor部分 

 

ISERDESE2时序 b die 时序_数据库_14

admin部分 

 

ISERDESE2时序 b die 时序_ISERDESE2时序_15

bind-address端口视服务器端口使用情况而定,这个端口是用来通过浏览器访问的 

http部分 (这个端口是用来通过程序来访问的)

 

ISERDESE2时序 b die 时序_数据_16

启动

通过cmd进入到influxdb的放置目录, 执行命令:influxd.exe -config influxdb.conf即可开启influxdb服务,同时按照上面配置文件产生相应的文件

测试

重新打开cmd,进入到influxdb的放置目录,输入influx,可看到如下界面即表示成功

 

ISERDESE2时序 b die 时序_时序数据库_17

3.    Influxdb基本操作

InfluxDB提供多种操作方式:

1)客户端命令行方式

2)HTTP API接口

3)各语言API库

4)基于WEB管理页面操作

客户端命令行方式

1)InfluxDB数据库操作

  • 显示数据库

show databases

 

ISERDESE2时序 b die 时序_数据_18

 

  • 新建数据库

create database shhnwangjian

 

ISERDESE2时序 b die 时序_数据_19

 

  • 删除数据库

drop database shhnwangjian

 

ISERDESE2时序 b die 时序_数据库_20

 

  • 使用指定数据库

use shhnwangjian

 

ISERDESE2时序 b die 时序_ISERDESE2时序_21

 

2)InfluxDB数据表操作

在InfluxDB当中,并没有表(table)这个概念,取而代之的是MEASUREMENTS,MEASUREMENTS的功能与传统数据库中的表一致,因此我们也可以将MEASUREMENTS称为InfluxDB中的表。

显示所有表

SHOW MEASUREMENTS

新建表

InfluxDB中没有显式的新建表的语句,只能通过insert数据的方式来建立新表。

insert disk_free,hostname=server01 value=442221834240i

其中 disk_free 就是表名,hostname是索引(tag),value=xx是记录值(field),记录值可以有多个,系统自带追加时间戳

 

ISERDESE2时序 b die 时序_数据_22

或者添加数据时,自己写入时间戳

insert disk_free,hostname=server01 value=442221834240i 1435362189575692182

 

ISERDESE2时序 b die 时序_数据_23

  • 删除表

drop measurement disk_free

3)数据保存策略(Retention Policies)

influxDB是没有提供直接删除数据记录的方法,但是提供数据保存策略,主要用于指定数据保留时间,超过指定时间,就删除这部分数据。

  • 查看当前数据库Retention Policies

show retention policies on "db_name"

 

ISERDESE2时序 b die 时序_ISERDESE2时序_24

  • 创建新的Retention Policies

create retention policy "rp_name" on "db_name" duration 3w replication 1 default

rp_name:策略名;

db_name:具体的数据库名;

3w:保存3周,3周之前的数据将被删除,influxdb具有各种事件参数,比如:h(小时),d(天),w(星期);

replication 1:副本个数,一般为1就可以了;

default:设置为默认策略

  • 修改Retention Policies

alter retention policy "rp_name" on "db_name" duration 30d default

  • 删除Retention Policies

drop retention policy "rp_name" on "db_name" 

4)连续查询(Continuous Queries)

InfluxDB的连续查询是在数据库中自动定时启动的一组语句,语句中必须包含 SELECT 关键词和 GROUP BY time() 关键词。

InfluxDB会将查询结果放在指定的数据表中。

目的:使用连续查询是最优的降低采样率的方式,连续查询和存储策略搭配使用将会大大降低InfluxDB的系统占用量。而且使用连续查询后,数据会存放到指定的数据表中,这样就为以后统计不同精度的数据提供了方便。

  • 新建连续查询
CREATE CONTINUOUS QUERY <cq_name> ON <database_name>
[RESAMPLE [EVERY <interval>] [FOR <interval>]]
BEGIN SELECT <function>(<stuff>)[,<function>(<stuff>)] INTO <different_measurement>
FROM <current_measurement> [WHERE <stuff>] GROUP BY time(<interval>)[,<stuff>]
END

 样例:

CREATE CONTINUOUS QUERY wj_30m ON shhnwangjian BEGIN SELECT mean(connected_clients), MEDIAN(connected_clients), MAX(connected_clients), MIN(connected_clients) INTO redis_clients_30m FROM redis_clients GROUP BY ip,port,time(30m) END

在shhnwangjian库中新建了一个名为 wj_30m 的连续查询,每三十分钟取一个connected_clients字段的平均值、中位值、最大值、最小值 redis_clients_30m 表中。使用的数据保留策略都是 default。

不同database样例:

CREATE CONTINUOUS QUERY wj_30m ON shhnwangjian_30 BEGIN SELECT mean(connected_clients), MEDIAN(connected_clients), MAX(connected_clients), MIN(connected_clients) INTO shhnwangjian_30.autogen.redis_clients_30m FROM shhnwangjian.autogen.redis_clients GROUP
  •  显示所有已存在的连续查询

SHOW CONTINUOUS QUERIES

 

ISERDESE2时序 b die 时序_数据库_25

 

  • 删除Continuous Queries

DROP CONTINUOUS QUERY <cq_name> ON <database_name>

5)查看用户

显示所有用户 SHOW USERS

创建用户 CREATE USER leo WITH PASSWORD ‘admin‘

修改用户(密码) SET PASSWORD FOR leo = ‘admin‘

删除用户 DROP USER leo

4.    可视化界面grafana