时序数据库-InfluxDB-1-基础概念与简单实用
一、什么是InfluxDB
InfluxDB是一个由InfluxData开发的开源时序型数据。它由Go写成,着力于高性能地查询与存储时序型数据。InfluxDB被广泛应用于存储系统的监控数据,IoT行业的实时数据等场景。
当前最新稳定版本InfluxDB v2.0
二、InfluxDB基础概念
2.1 database(数据库)
同SQL中的database
1 | show databases |
2.2 measurement(表)
同SQL中的table
1 | use telegraf |
2.3 point(时序数据记录)
相当于SQL中的数据行。下面每一条数据就是一个point。由时序(series)和时间戳(timestamp)唯一标识。
1 | select * from system limit 10 |
2.4 time(时间)
既然是时间序列数据库,influxdb的数据都有一列名为time的列,里面存储UTC时间戳。time可以在插入数据时自己添加,如果没有添加,InfluxDB会自动创建。在InfluxDB中,时间几乎可以看作是主键。
2.5 tag(标签)
用于创建索引,提升查询性能,一般存放标识数据来源的属性信息。在下方代码中,system表中的标签为host,对应的标签值为telegraf-getting-started。
1 | show tag keys from system |
2.6 field(指标)
一般存放的是具体的时序数据,即随着时间戳的变化而变化的数据,与标签不同的是,未对指标数据创建索引。
1 | show field keys from system |
2.7 retention policy(保留策略)
定义InfluxDB的数据保留时长和数据存储的副本数量,通过设置合理的保存时间(Duration)和副本数量(Replication),在提升数据存储可用性的同时,避免数据爆炸。
1 | show databases |
以上表示telegraf数据库中存在一个数据保留策略,其中的数据永久保存,不过期(duration=0s),副本数为1(replicaN=1)
2.8 series(时间序列线)
表示表名、保留策略、标签集都相同的组数据。
1 | show series on telegraf from system |
三、InfluxDB操作模式
InfluxDB提供两种原生的操作模式:influx命令行工具和InfluxDB API。
influx命令行工具是一种类似于mysql命令行工具的命令行接口,可以方便地执行管理、运维、调试性质的操作。
InfluxDB API是一种可编程性强、编程语言友好的RESTful API的操作接口,支持HTTP和HTTPS协议。
3.1 influx命令行工具
3.1.1 内置命令
与mysql命令行工具类似,influx也内置了丰富、强大的命令,下面将详细介绍常用的内置命令。
a.help命令
help命令输出支持的内置命令的及其使用帮助信息。
1 | > help |
b.auth命令
auth命令,提示输入用户名和密码,后续执行influx命令行操作时,进行认证。
1 | auth |
通过auth命令输入用户名密码时,密码不会显示。
c.connect命令
connect命令,在不退出命令行shell情况下,连接到指定的IP和端口的InfluxDB服务器上。默认连接localhost:8086
1 | connect localhost:8086 |
d.consistency命令
consistency命令,用于配置写一致性的级别:any、one、quorum、all
写一致性级别 | 描述 |
---|---|
any | 任何一个节点写入成功后,或者接收节点已将数据写入hinted handoff缓存队列后,就会返回成功给客户端。 |
one | 任何一个节点写入成功后,立即返回成功给客户端,不包括成功写入hinted handoff缓存队列。 |
quorum | 当大多数节点写入成功后,会返回成功给客户端。此选项仅在副本数大于2时有意义,否则等效于all。 |
all | 仅在所有节点都写入成功后返回成功。 |
设置写一致性级别为all。
1 | consistency all |
e.format命令
format命令,设置服务器响应数据的格式:json、csv、column
1 | format json |
f.insert命令
insert命令,写入行协议格式的时序数据。
1 | 基础语法 |
g.select命令
select命令,查询InfluxDB数据
1 | 语法 |
h.pretty命令
pretty命令,支持json格式的漂亮打印。
1 | format json |
i.precision命令
设置InfluDB任何返回的时间戳的格式和精度
1 | select usage_idle from cpu limit 10 |
j.InfluxQL命令
InfluxDB OSS 2.0支持InfluxQL只读查询。
支持的InfluxQL查询 | 支持的InfluxQL查询 |
---|---|
DELETE* *DROP MEASUREMENT EXPLAIN ANALYZE SELECT (只读) SHOW DATABASES SHOW MEASUREMENTS SHOW TAG KEYS SHOW TAG VALUES SHOW FIELD KEYS |
SELECT INTO ALTER CREATE DROP (有限的支持) GRANT KILL REVOKE |
详细参考:InfluxDB v2.0 Documentation
3.2 InfluxDB API模式
InfluxDB API是一种RESTful API风格的接口,返回json格式的响应数据,并支持身份认证、JWT令牌、丰富的HTTP响应等。
1 | 使用InfluxDB API检查InfluxDB服务的实例状态和版本信息。 |
使用HTTP API模式时,InfluxDB响应主要有以下几个:
2xx:204代表no content,写入成功。
200代表InfluxDB可以接收请求但是没有完成请求。一般会在body体中带有出错信息。
4xx:InfluxDB不能解析请求。
5xx:系统出现错误。
四、连续查询和保留策略
在实际生产中,可以通过连续查询提高查询效率,降低查询延时。通过保留策略淘汰过期的冷数据,降低存储成本。
4.1 连续查询
连续查询是InfluxDB中的一种查询类型。它会按照用户指定的查询规则,自动地、周期性地查询实时数据并执行指定运算,然后将查询结果保存在一张指定的表中。
通过创建连续查询,用户可以指定InfluxDB执行连续查询的时间间隔、单次查询的时间范围以及查询规则。InfluxDB会根据用户所指定的规则,定期地将过去一段时间内的原始时序数据以用户所期望的方式保存至新的结果表中,从而降低存储数据的时间精度,大大减少新表中的数据量。同时,将查询的结果保存在指定的数据表中,也便于用户直接查询所关心的内容,从而降低查询的运算复杂度,提升查询效率。
4.1.1 连续查询基础特性
a.创建基础连续查询
1 | CREATE CONTINUOUS QUERY <cq_name> ON <database_name> |
其中:
<cq_name>
:连续查询的名称。<database_name>
:连续查询所在数据库的名称。<cq_query>
:具体连续查询语句。
cq_query语法
cq_query需要一个函数,一个INTO子句和一个GROUP BY time()子句。
1 | 注意:请注意,在WHERE子句中,cq_query不需要时间范围。 InfluxDB在执行CQ时自动生成cq_query的时间范围。cq_query的WHERE子句中的任何用户指定的时间范围将被系统忽略。 |
<function[s]>
:要查询的字段以及所查询的内置函数。<destination_measurement>
:保存查询结果的目标表。若目标表不存在,将自动创建。<measurement>
:要查询的数据表。<stuff>
:具体查询条件,可选参数。<interval>
:连续查询语句执行的时间间隔与查询的时间范围。<tag_key[s]>
:归类的标签字段,可选参数。
b.连续查询运行时间点和覆盖时间范围
InfluxDB在执行连续查询时,GROUP BY time()指定的时间既决定了连续查询每次执行的时间间隔,也决定了连续查询的查询时间范围。
InfluxDB会根据连续查询语句中GROUP BY time()所指定的时间间隔,基于InfluxDB本地服务器的时间,在预设的时间节点开始执行这些连续查询语句。例如,GROUP BY time(1h)指定的时间间隔是1小时,InfluxDB则会在每个小时开始的时候执行连续查询语句,如11:00、12:00、13:00开始执行。
InfluxDB在执行连续查询语句时,首先通过now()函数获取当前的时间,再用当前时间减去GROUP BY time()所指定的时间间隔。这两个时间点之间的左闭右开区间就是连续查询语句查询的时间范围。例如,GROUP BY time()设置的时间长度是1个小时,执行的时间点是12:00,那么所查询的时间范围就是11:00-11:59.999999999。
c.基础连续查询例子
以下例子使用数据库telegraf
中的示例数据。measurement cpu
存储有关cpu的利用率数据:
1 | select usage_idle from cpu where cpu='cpu-total' limit 10 |
使用简单的CQ自动从单个字段中下采样数据,并将结果写入同一数据库中的另一个measurement。
1 | create continuous query cpu_usage_idle_15m on telegraf |
在数据库telegraf
中创建一个名为cpu_usage_idle_15m
的连续查询,每15m求measurement cpu
中usage_idle
的平均数。
例子参考:InfluxDB中文文档-连续查询
d.基础连续查询常见问题
问题一:无数据处理时间间隔
如果没有数据落在该时间范围内,则CQ不会在时间间隔内写入任何结果。请注意,基本语法不支持使用fill()更改不含数据的间隔报告的值。如果基本语法CQs包括了fill(),则会忽略fill()。一个解决办法是使用下面的高级语法。
问题二:重新采样以前的时间间隔
基本的CQ运行一个查询,覆盖了now()和now()减去GROUP BY time()间隔之间的时间段。有关如何配置查询的时间范围,请参阅高级语法。
问题三:旧数据的回填结果
CQ对实时数据进行操作,即具有相对于now()发生的时间戳的数据。使用基本的INTO查询来回填具有较旧时间戳的数据的结果。
问题四:CQ结果中缺少tag
默认情况下,所有INTO查询将源measurement中的任何tag转换为目标measurement中的field。在CQ中包含GROUP BY *,以保留目的measurement中的tag。
4.1.2 连续查询高级特性
a.创建高级连续查询
1 | CREATE CONTINUOUS QUERY <cq_name> ON <database_name> |
相比创建基础连续查询语句的语法,创建高级连续查询多了RESAMPLE子句。用户可以通过RESAMPLE子句分别指定更具体的查询时间间隔和时间范围。
EVERY <interval>
:指定执行连续查询的时间间隔。每隔EVERY子句所指定的时间间隔,InfluxDB会在预设的时间点开始执行连续查询。假设EVERY子句设置时间间隔为1小时,那么每隔1个小时,InfluxDB会在当前小时开始的时间点执行连续查询语句。FOR <interval>
:指定查询的时间范围。同样地,InfluxDB会通过now()函数查询当前时间,并用当前时间减去FOR子句所设置的时间间隔,由这两个时间点得到所查询的时间范围。如果FOR子句设置的时间间隔是2小时,并且当前时间是12:00,那么查询的时间范围就是10:00到11:59.999999999。
EVERY子句和FOR子句其一或者二者都有设置的时候,RESAMPLE子句就会生效。如果二者都没有设置,则连续查询语句按照基础语法规则执行。
b.高级连续查询的时间设置
由于高级连续查询语句中有多处涉及时间的设置,常会出现以下两种情况:
1)如果EVERY子句设置的时间间隔大于GROUP BY time()所设置的时间间隔,且FOR未设置,连续查询语句将按照EVERY子句设置的时间间隔执行,查询的时间范围是now()减去EVERY子句设置的时间间隔(GROUP BY time()指定的时间间隔不生效)。
例如,GROUP BY time()设置的时间间隔是5分钟,EVERY设置的时间间隔是10分钟,则连续查询语句会每隔10分钟执行一次。每次执行,查询的时间范围为当前时间过去的10分钟。
2)FOR子句设置的查询时间范围必须大于连续查询执行的时间间隔。如果FOR子句设置的查询时间范围小于连续查询执行的时间间隔,如小于GROUP BY time()设置的时间间隔(如果EVERY子句有指定,则是EVERY子句指定的时间间隔),这时InfluxDB会报错,错误信息如下。
1 | create continuous query cpu_usage_idle_15m_t on telegraf resample for 10m begin select mean(usage_idle) as usage_idle_15m_t into cpu_usage_idle_15m_t from cpu group by time(15m) end |
c.高级连续查询例子
1 | create continuous query cpu_usage_idle_30m on telegraf |
在数据库telegraf
中创建一个名为cpu_usage_idle_30m
的连续查询,每15m求measurement cpu
在过去30分钟内usage_idle
的平均数。
例子参考:InfluxDB中文文档-连续查询
4.1.3 管理连续查询
a.查询已创建连续查询
1 | show continuous queries |
b.删除已创建的连续查询
1 | DROP CONTINUOUS QUERY <cq_name> ON <database_name> |
4.1.4 连续查询的应用场景
a.复杂查询的预处理
我们的监控数据往往粒度较细、数据量大,不能直观地反映监控对象的状态,需要进一步进行处理和汇总,这时需要进行比较复杂的查询。这些查询可能耗时较长,也可能会造成较大的系统开销,如果高频实时地进行查询,可能会对业务体验、系统的稳定性带来一定的冲击。
如果采用连续查询,系统将提前定期对监控数据进行处理、汇总,将粒度过细的数据转化成我们期望的数据并进行存储,然后再对处理后的数据进行实时直接查询,这样不但可以满足我们的查询需求,而且可以降低查询延时、减少对系统资源的消耗。
b.降低数据采样率,结合数据保留策略节省成本
监控数据的上报往往是海量的,并随时间的推移不断增加,这些数据会占用大量的存储空间。连续查询会定期自动地将高精度数据转化成低精度数据,并通过数据保留策略将我们不关心的高精度数据从数据库中清除,大大减少了存储数据量,降低了存储成本。
通过连续查询,结合InfluxDB的数据保留策略,可以很好地解决存储成本的问题。
c.实现SQL的Having功能
InfluxDB不支持SQL中的Having子句,但我们可以通过连续查询的方式对数据进行聚合、统计,再对这些结果进行查询,即可达到SQLHaving一样的效果。
例如,我们要统计每小时CPU利用率的平均值,并找到平均值大于80的结果,SQL的查询语句如下:
1 | SELECT mean("cpu_usage") FROM "cpu_usage_detail" GROUP BY time(60m) HAVING mean("cpu_usage ") > 80 |
在InfluxDB中,先通过连续查询的方式对数据进行聚合、统计,再对这些结果进行查询,即可达到SQL Having语句的功能,具体步骤如下:
1.创建一条连续查询
首先,我们创建一条连续查询,用于定期统计每个小时CPU利用率的平均值,并将结果保存在表cpu_result中。
1 | create continuous query "cpu_cq" on "cpu_db" |
2.对连续查询结果进行查询
查询表cpu_result,查询到CPU利用率均值大于80的结果。
1 | select "mean_cpu_usage" from "cpu_result" where "mean_cpu_usage" > 80 |
d.实现SQL的函数嵌套
大多数InfluxQL的内置函数不支持函数的嵌套,如果某些查询场景要用到函数的嵌套,我们可以通过连续查询先执行内部函数的计算,然后再对计算结果进行查询和执行外部函数的计算。
例如,统计过去每小时CPU的最大利用率,并计算它们的总平均值。 SQL函数嵌套语句如下:
1 | select mean(max("cpu_usage")) from "cpu_usage_detail" group by time(60m) |
在InfluxDB中可以先通过连续查询执行内部函数的计算,然后再对计算结果进行查询和执行外部函数的计算,即可达到SQL函数嵌套语句的功能,具体步骤如下:
1.创建一条连续查询
创建一条连续查询,用于定期统计每小时CPU的最大利用率,并将结果保存在表cpu_result中。
1 | create continuous query "cpu_cq" on "cpu_db" |
2.对连续查询结果进行查询
对表cpu_result进行查询,计算出一段时间内的每小时CPU的最大利用率的均值。
1 | select mean("max_cpu") from "cpu_result" |
4.2 保留策略
数据保留策略是InfluxDB的一个重要组成部分,InfluxDB通过保留策略来决定数据的保留时长。InfluxDB会计算本地服务器时间和存储数据的时间戳的差值,如果该差值大于保留策略设置的保留时长,则会将这些过期数据删除。
4.2.1 创建保留策略
创建保留策略的基本语法:
1 | CREATE RETENTION POLICY <retention_policy_name> ON <database_name> DURATION <duration> REPLICATION <n> [SHARD DURATION <duration>] [DEFAULT] |
其中SHARD DURATION、DEFAULT为可选设置项,其他均为必选设置项。
DURATION
:DURATION子句指定了InfluxDB需要保留数据的时长。DURATION所指定的值<duration>
为保留时间长度或者为INF(代表infinite,无限长)。InfluxDB最小的保留时间间隔是1个小时,最长的保留时间间隔是无限长(INF)。REPLICATION
:REPLICATION子句指定了集群中每条数据有多少个不相关的副本,<n>
表示指定的副本数,副本数的最大值为DATA节点的节点个数。DEFAULT
:将所创建的数据保留策略设置为该数据库的默认保留策略,该项为可选设置项。一个数据库可以有多个数据保留策略,同一个数据库中的不同保留策略的名字必须是唯一的。如果成功创建保留策略,InfluxDB不返回任何信息;如果重复创建相同的保留策略,即保留策略名字相同,策略规则也完全相同,则InfluxDB不会报错;如果创建的保留策略名字已存在,但策略规则不同,则InfluxDB会报错。
1 | 在数据库rp_test_database中创建了一条保留策略rp_one_day,保留数据的时间长度为1天,数据副本数为1。 |
4.2.2 查询保留策略
查询保留策略的基本语法:
1 | SHOW RETENTION POLICIES ON <database_name> |
<database_name>
:数据库名称。
4.2.3 修改保留策略
修改保留策略的基本语法:
1 | ALTER RETENTION POLICY <retention_policy_name> ON <database_name> DURATION <duration> REPLICATION <n> SHARD DURATION <duration> [DEFAULT] |
其中参数含义和创建相同。
4.2.4 删除保留策略
删除保留策略的基本语法:
1 | DROP RETENTION POLICY <retention_policy_name> ON <database_name> |
<retention_policy_name>
:指定的保留策略的名称。<database_name>
:指定的数据库名称。注意,若删除成功,InfluxDB不返回任何信息,如果删除一个不存在的保留策略,InfluxDB不会报错。