InfluxDB是一个Go写的时序数据库(Time-Series Database)。

官网 / Github / 文档

基本

环境:Gentoo

目前版本V1.0,没有提供官方的ebuild,不过go-overlay有别人写好的:https://github.com/gentoo-mirror/go-overlay/tree/master/dev-db/influxdb

也可以直接下载tar包,里面是Go编译好的,包括二进制工具,配置文件和目录等。

tar包里的配置有详细注释,默认的比如数据存储路径都是/etc下。

也可以手动生成配置。手动生成的配置默认存储路径等在$HOME/.influxdb/,且注释相对少一些:

$ cp ./etc/influxdb/influxdb.conf{,bak}
$ ./usr/bin/influxd config > ./etc/influxdb/influxdb.conf

启动influxdb:

$ ./usr/bin/influxd run --config ./etc/influxdb/infludb.conf

默认会全局监听三个端口:

官方给出的硬件配置是,参考

另外就是注意启动时的进程权限以及存储目录权限问题了。

核心概念

Influxdb是一个时序数据库,数据都是一些可度量的值,比如cpu load或者温度等。

写入是一行行的数据,称为Point

<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]

time(时间戳), measurement(比如cpuload), 至少一个k/v对field(measured value,比如value=0.6), 0个或多个k/v对tags(一些元信息metadata, 如host=server01, region=us)

官方给的例子:

cpu,host=serverA,region=us_west value=0.64
payment,device=mobile,product=Notepad,method=credit billed=33,licenses=3i 1434067467100293230
stock,symbol=AAPL bid=127.46,ask=127.48
temperature,machine=unit42,type=assembly external=25,internal=37 1434067467000000000

和MySQL做类比,InfluxDB的measurement类似于表,主索引永远是time, tags是被索引的,fields不是;Point就是一行行的数据,只不过表名是在Point中。

常用操作

# -----------------------------------------------------------------------------
# Query Language列表:
# <https://docs.influxdata.com/influxdb/v1.0/query_language/spec/>
# -----------------------------------------------------------------------------

# 创建数据库
> create database mydb

# 查看有哪些数据库, 在配置了认证的情况下,只有admin权限的用户可以看
> show databases;
name: databases
---------------
name
_internal  # <-- 这个是内置的,用于存储一些influxdb元信息
mydb

# 选择使用的数据库
> use mydb
Using database mydb

# 插入数据
> INSERT cpu,host=serverA,region=us_west value=0.62

# 查询数据
# 需要用 **双引号**
# 也可以 **都** 不用双引号
# ref: https://docs.influxdata.com/influxdb/v1.2/write_protocols/line_protocol_tutorial/#quoting
> SELECT "host", "region", "value" FROM "cpu"
name: cpu
---------
time                    host    region  value
1474442747173411091     serverA us_west 0.62

# 插入多个数据(fields)
> INSERT temperature,machine=unit42,type=assembly external=25,internal=37

# 除了glob匹配,InfluxQL还支持Go-Style的正则
> SELECT * FROM 'cpu'
ERR: error parsing query: found cpu, expected identifier at line 1, char 14
> SELECT * FROM "cpu"
name: cpu
---------
time                    host    region  value
1474442747173411091     serverA us_west 0.62

# 显示所有的measurements
> show measurements
name: measurements
------------------
name
cpu


# 删除操作
# https://docs.influxdata.com/influxdb/v1.0/query_language/database_management/
# 看了下v1.0和v0.9的文档,这块变化还是不少
# 目前这块几种的具体区别还没弄明白 TODO

## drops the series from index
## FROM或WHERE至少存在一个
> DROP SERIES FROM "cpu" WHERE host='serverA'

## Unlike DROP SERIES, it does not drop the series from the index and it supports time intervals in the WHERE clause.
> DELETE FROM "cpu" WHERE host='serverA'

## The DROP MEASUREMENT query deletes all data and series from the specified measurement and deletes the measurement from the index.
> DROP MEASUREMENT "cpu"


# 其它
# 查询时时间显示,使用rfc3339格式时间(默认是时间戳)
# https://docs.influxdata.com/influxdb/v1.0//tools/shell/#influx-arguments
> precision rfc3339

用户认证和权限

文档:Authentication and Authorization

开启用户认证,首先创建admin权限用户和相应数据库的普通用户:

# 默认没有用户
> show users;
user    admin  # 这里admin是一个boolean值

# 创建一个admin权限的用户
> create user admin with password '********' with all privileges
> show users;
user    admin
admin   true

# 创建一个普通权限的用户
> create user tankywoo with password '********'
> show users;
user       admin
admin      true
tankywoo   false

# 给普通用户赋予某个数据库的权限
> grant all on mydb to tankywoo

# 查看某个用户的权限
> show grants for tankywoo
database        privilege
mydb            ALL PRIVILEGES

# 删除用户
> drop user tankywoo

配置文件的[http]块:

[http]
  enable = true
  bind-address = ":8086"
  auth-enabled = true  # 开启认证
  ...

重启influxd,下次使用influx cli时需要认证:

# influx cli认证
# 然后进入交互输入用户名和密码
> auth
username: tankywoo
password:

Retention Policy 和 Continuous Query

类似于rrdtool中的rra的概念,可以控制不同的存储时长有不同的数据采样粒度。

关于RP, 默认是autogen, 表示永久存储. 默认配置下对每一个DB会自动创建, 可以通过修改配置retention-autocreate来控制不自动创建.

可以修改其它RP为默认RP:

# 如新建一个one_hour的RP, 并设置为默认的RP
> show retention policies on mydb
name            duration        shardGroupDuration      replicaN        default
autogen         0               168h0m0s                1               false
one_hour        1h0m0s          1h0m0s                  1               true
one_day         24h0m0s         1h0m0s                  1               false

关于对其它RP的写入和查询, 格式和普通的稍微有些区别, 之前没看清楚文档, 结果被折腾了半天:

# 写入
> INSERT INTO [<database>.]<retention_policy> <line_protocol>

# 查询
> SELECT * FROM "<database>"."<retention_policy>"."<measurement>"

注意写入是有个INTO子句. How do I write to a non-DEFAULT retention policy with InfluxDB’s CLI?

比如:

> insert into one_hour load 1=1.0,5=2.0,15=3.0

> select * from one_hour.load

还有个地方需要注意:

Note that once you specify a retention policy with INSERT INTO, influx automatically writes data to that retention policy. This occurs even for later INSERT entries that do not include an INTO clause. Restarting the CLI will revert to using the DEFAULT retention policy. 来源

> insert into one_day mem value=2
Using retention policy one_day

如上可以看到, 说有使用one_day这个RP, 后续如果直接insert mem value=3,则依然是写入one_day这个RP. 要么重新insert into指定, 要么重新登录cli client.

如果需要清空 RP 里的数据,则直接删掉 RP 即可。

目前这块没法针对 RP 中的某个 measurement 单独删除,因为 drop measurement "xxx" 是没法指定 RP 的,以前这样会导致将默认RP的 measurement 删掉,现在会有提示(在 Issue 上看到的,没具体尝试)。

构建CQ:

> create continuous query "cq_5m" on "mydb" begin select mean("value") into "one_day"."load" from "load" group by time(5m) end

# 查看
> show continuous queries

关于这块,两点需要注意:

1 GROUP BY 后面如果没有接指定的 tags (逗号分隔),则生成的 RP 数据中,这些 tags 的值都是空的。

2 在我使用的情况,一个 db 里 N 个 measurements,一个 measurement 中 N 个 fields。全部按上面来添加,会累晕的,后来有支持 Automatically downsample a database with backreferencing,但是有个蛋疼的地方,比如用 mean(),它会将所有的 field 的名字都改为 mean_field,优点就是一个 CQ 就解决了所有 measurements 的问题,而且后面的 tags 也可以省略。不过最后我还是选择写个脚本生成20多个 CQ……

CREATE CONTINUOUS QUERY "cq_basic_br" ON "transportation"
BEGIN
  SELECT mean(*) INTO "downsampled_transportation"."autogen".:MEASUREMENT FROM /.*/ GROUP BY time(30m),*
END

参考文档:

关于 GROUP BY 语句

GROUP BY 语句用于筛选数据,最常见的是 GROUP BY time(interval),除了这个外,还有 GROUP BY tag

之前有个需求,机器外网流量的 points 有 location、if_name、host 几个字段,现在 Grafana 要画出同一个 location 的每个节点流量:

初始的写法是:

SELECT non_negative_derivative(mean("out"), 1s) * 8 as wan FROM "net" WHERE location = '$idc' AND "if_name" = 'wan' GROUP BY time($interval) fill(null)

但是这样画出来的所有数据是在一个数据里,无法区别同一个机房的每一台机器,且画出来的数据因为是混合的 derivative 操作,所以总数据也是错误的。

后来看文档发现还有 GROUP BY tag 的用法,可以将数据按指定的 tag 分开,适合这样的场景。

改正后的 metric 语句:

SELECT non_negative_derivative(mean("out"), 1s) * 8 as wan FROM "net" WHERE location = '$idc' AND "if_name" = 'wan' GROUP BY host, time($interval) fill(null)

参考:The GROUP BY clause

其它

关于 point 的唯一性

一个 Point 由 timestamp 和 tag 唯一识别。

所以要覆盖一个 Point 时,即修改这个 Point 的某些 value,只需要插入时指定相应的 timestamp 和 tag 即可:

> insert load,host=server1 value=0.00 1488435842307330152
> select * from load
name: load
---------
time                    host    value
1488435842307330152     server1 0

# 插入一条相同的
> insert load,host=server1 value=0.00 1488435842307330152
> select * from load
name: load
---------
time                    host    value
1488435842307330152     server1 0

# 插入一条值修改后的
> insert load,host=server1 value=0.01 1488435842307330152
> select * from load
name: load
---------
time                    host    value
1488435842307330152     server1 0.01

关于单双引号

总是忘了哪里改用单引号,哪里该用双引号,还是直接看文档吧:

术语

其它