基本概念
line-protocol
line protocol elements
- measurement(必要): 用于存储数据的指标名字
- tag set: 以逗号分隔的键值对列表, 每个键值对都代表一个标签; 标签的键和值是无引号的字符串, 空格、逗号、等号必须被转义; 可以类比关系型数据库表中带索引的字段;
- field set(必要): 以逗号分隔的键值对列表, 每个键值对都代表一个字段; 字段键是无引号的字符串, 空格和逗号必须被转义; 字段值可以是字符串(带引号)、浮点数、整数、无符号整数或布尔运算; 可以类比关系型数据库表中不带索引的字段;
- timestamp: 与数据相关的unix时间戳, influxDB支持最高纳秒级的精度; 如果时间戳的精度不是纳秒, 必须在向influxDB写入数据时指定精度
line protocol element parsing
- measurement: 第一个未转义的逗号之前的所有内容
- tag set: 第一个未转义的逗号和第一个未转义的空白之间的键值对
- field set: 在第一个和第二个没有转义的空白处之间的键值对
- timestamp: 在第二个未转义的空白处之后的整数值
- 行与行之间用换行符(\n)分割
organization
一组用户的workspace, 所有的dashboard、tasks、buckets、members等资源都属于一个组织
bucket
一个bucket是一个命名的位置用来存储时间序列数据; 所有的bucket都有一个retention period; 一个bucket属于一个organization
point
在influxdb中, 一个point代表一条数据记录, 类似于SQL数据库表中的行记录
每个point包含:
- 一个measurement、一组tag、一个field key, 一个field value以及一个timestamp
- point由series和timestamp唯一标识
在一个series中, 每个point都有一个唯一的timestamp, 如果把一个timestamp和结合现有的point数据写入series, 那么新旧field会取并集
series
influxdb数据结构中共享一个measurement和tag set的数据集合
series基数
influxdb bucket中唯一的measurement、tag set、field key组合的数量
栗子1: 假设一个bucket有一个measurement, 单个measurement又两个tag(email和status); 如果有三个不同的email并且每个email地址关联两个不同的status, 那么对于这个measurement的series基数为3*2=6
栗子2: 从属标签是由另外一个标签决定范围的, 不会增加series基数, 如下所示把标签firstname加到上面的例子中, series基数不会是18(323)而是6(3*2), 因为firstname标签已经呗email标签范围覆盖
命令行基本操作
启动influxdb服务
使用influxd启动默认配置的influxdb服务
默认情况下数据目录在$HOME/.influxdbv2中; 默认访问地址http://localhost:8086/; 通过influx客户端连接到服务端的连接信息默认是存在$HOME/.influxdbv2/configs文件中
通过influxdb-cli初始化admin用户
influx setup -u USERNAME -p PASSWORD -t TOKEN -o ORGANIZATION_NAME -b BUCKET_NAME -f
- -f: 使用非交互模式初始化用户
- -u: 用户名
- -p: 密码
- -t: token
- -o: 指定organization
- -b: 指定bucket
创建 All-Access tokens
influx auth create \
--all-access \
--host http://localhost:8086 \
--org <YOUR_INFLUXDB_ORG_NAME> \
--token <YOUR_INFLUXDB_OPERATOR_TOKEN>
注意: token需要使用admin用户的
注意: --token需要使用通过influxdb-cli初始化admin用户中创建的token
./influx auth create --all-access --host http://localhost:8086 --org myorg --token mytoken
ID Description Token User Name User ID Permissions
0a9060a7c836d000 c8YXKxUQtI3fvwPPg== admin 0a905edff1f6d000 [read:orgs/ff538db5e1fa9049/authorizations ……]
注意: 生成之后需要注意保留token
配置认证凭证
influx config create \
--config-name get-started \
--host-url http://localhost:8086 \
--org <YOUR_INFLUXDB_ORG_NAME> \
--token <YOUR_INFLUXDB_API_TOKEN>
注意: --token可以使用创建 All-Access tokens中创建的token
创建bucket
influx bucket create --name get-started
注意: --name使用配置认证凭证中创建的配置名字
写入数据
influx write \
--bucket get-started \
--precision s "
home,room=Living\ Room temp=21.1,hum=35.9,co=0i 1641024000
home,room=Kitchen temp=21.0,hum=35.9,co=0i 1641024000
home,room=Living\ Room temp=21.4,hum=35.9,co=0i 1641027600
home,room=Kitchen temp=23.0,hum=36.2,co=0i 1641027600
home,room=Living\ Room temp=21.8,hum=36.0,co=0i 1641031200
home,room=Kitchen temp=22.7,hum=36.1,co=0i 1641031200
home,room=Living\ Room temp=22.2,hum=36.0,co=0i 1641034800
home,room=Kitchen temp=22.4,hum=36.0,co=0i 1641034800
home,room=Living\ Room temp=22.2,hum=35.9,co=0i 1641038400
home,room=Kitchen temp=22.5,hum=36.0,co=0i 1641038400
home,room=Living\ Room temp=22.4,hum=36.0,co=0i 1641042000
home,room=Kitchen temp=22.8,hum=36.5,co=1i 1641042000
home,room=Living\ Room temp=22.3,hum=36.1,co=0i 1641045600
home,room=Kitchen temp=22.8,hum=36.3,co=1i 1641045600
home,room=Living\ Room temp=22.3,hum=36.1,co=1i 1641049200
home,room=Kitchen temp=22.7,hum=36.2,co=3i 1641049200
home,room=Living\ Room temp=22.4,hum=36.0,co=4i 1641052800
home,room=Kitchen temp=22.4,hum=36.0,co=7i 1641052800
home,room=Living\ Room temp=22.6,hum=35.9,co=5i 1641056400
home,room=Kitchen temp=22.7,hum=36.0,co=9i 1641056400
home,room=Living\ Room temp=22.8,hum=36.2,co=9i 1641060000
home,room=Kitchen temp=23.3,hum=36.9,co=18i 1641060000
home,room=Living\ Room temp=22.5,hum=36.3,co=14i 1641063600
home,room=Kitchen temp=23.1,hum=36.6,co=22i 1641063600
home,room=Living\ Room temp=22.2,hum=36.4,co=17i 1641067200
home,room=Kitchen temp=22.7,hum=36.5,co=26i 1641067200
"
基于FLUX查询数据
Flux是一个能够在influxdb查询和处理数据的函数式的脚本语言
Flux查询基础
- from() 从influxdb的bucket中查询数据
- range() 基于时间范围的数据过滤
- filter() 基于列值的数据过滤, 每一行用r表示, 每一列用r的一个属性表示, 可以应用多个后续过滤器。
r = {
_time: 2020-01-01T00:00:00Z,
_measurement: "home",
room: "Kitchen",
_field: "temp",
_value: 21.0,
}
(r) => r._measurement == "home" // Returns true
(r) => r.room == "Kitchen" // Returns true
(r) => r._field == "co" // Returns false
(r) => r._field == "co" or r._field == "temp" // Returns true
(r) => r._value <= 20.0 // Returns false
filter函数将每一行记录命名为r, 所以可以通过r._measurement, r.room这种方式来获取数据, 如果行判断为true则会在filter的输出中被包含, 否则会丢弃
Flux通过管道转发操作符|>将上一个函数的输出作为下一个函数的输入.
from(bucket: "get-started")
|> range(start: 2022-01-01T08:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> filter(fn: (r) => r._field== "co" or r._field == "hum" or r._field == "temp")
执行Flux查询
- 命令行方式
influx query '
from(bucket: "get-started")
|> range(start: 2022-01-01T08:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> filter(fn: (r) => r._field== "co" or r._field == "hum" or r._field == "temp")
'
使用map函数对数据重新赋值
map获取单个参数即fn, fn是一个匿名函数, 将每一行作为一条记录来读取, 在每一行记录中, 每个键值对代表一个列和他的值
r = {
_time: 2020-01-01T00:00:00Z,
_measurement: "home",
room: "Kitchen",
_field: "temp",
_value: 21.0,
}
fn函数以任何你需要的方式修改记录, 并返回一个新的记录, 如下所示:
(r) => ({ _time: r._time, _field: "temp_F", _value: (r._value * 1.8) + 32.0})
// Returns: {_time: 2020-01-01T00:00:00Z, _field: "temp_F", _value: 69.8}
注意: 在上例中有部分的列会被丢弃, 原因是因为fn只显式的映射_time、_field、_value列, 如果需要只更新或者添加指定的列需要使用with操作
(r) => ({r with _value: (r._value * 1.8) + 32.0, degrees: "F"})
// Returns:
// {
// _time: 2020-01-01T00:00:00Z,
// _measurement: "home",
// room: "Kitchen",
// _field: "temp",
// _value: 69.8,
// degrees: "F",
// }
from(bucket: "get-started")
|> range(start: 2022-01-01T08:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> filter(fn: (r) => r._field == "hum")
|> map(fn: (r) => ({r with _value: r._value / 100.0}))
使用group函数重新将数据分组
默认情况下,from()返回从InfluxDB查询的数据,按系列(测量、标签和字段键)分组。返回的表流中的每个表代表一个组。每个表都包含相同的数据分组列的值。这种分组在你汇总数据时是很重要的。
from(bucket: "get-started")
|> range(start: 2022-01-01T08:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> group(columns: ["room", "_field"])
若 |> group() 则为不分组
聚合数据
取平均值
from(bucket: "get-started")
|> range(start: 2022-01-01T08:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> filter(fn: (r) => r._field == "co" or r._field == "hum" or r._field == "temp")
|> mean()
计数
from(bucket: "get-started")
|> range(start: 2022-01-01T14:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> toFloat()
|> group(columns: ["room"])
|> count()
内置聚合方法: docs.influxdata.com/flux/v0.x/f…
内置selector方法:docs.influxdata.com/flux/v0.x/f…
转换数据结构为关系型数据库表结构
pivot函数: docs.influxdata.com/flux/v0.x/s…
from(bucket: "get-started")
|> range(start: 2022-01-01T14:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> filter(fn: (r) => r._field == "co" or r._field == "hum" or r._field == "temp")
|> filter(fn: (r) => r.room == "Kitchen")
|> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value")
使用aggregateWindow采样数据
aggregateWindow函数:docs.influxdata.com/influxdb/v2…
数据采样是一种策略, 可以提高查询时的性能, 也可以优化长期数据存储; 简单来说采样数据减少返回点的数量, 而不会丢失数据的总体趋势
from(bucket: "get-started")
|> range(start: 2022-01-01T14:00:00Z, stop: 2022-01-01T20:00:01Z)
|> filter(fn: (r) => r._measurement == "home")
|> filter(fn: (r) => r._field == "temp")
|> aggregateWindow(every: 2h, fn: mean)
- every参数指定窗口周期
- fn指定使用aggregate或selector中的函数
- timeSrc指定使用哪一列值来为每个窗口创建新的聚合时间戳, 默认是_stop
InfluxDB任务
task是预定的查询, 可以执行上述任何数据处理操作; 一般来说任务会使用to函数将处理后的结构写回给InfluDB
InfluxDB任务: docs.influxdata.com/influxdb/v2…