最近帮助公司前端小伙伴处理他们的nginx访问日志,log的数据是半结构化的数据,同时也是典型的时序数据,每一条数据都带有时间戳。于是考虑使用时间序列数据库存储,而不会去使用mysql或是mongodb(zabbix用的是mysql,它在IO上面遇到了瓶颈)。现在时间序列的数据库是有很多的,比如graphite、opentsdb以及新生的influxdb。这次我使用了InfluxDB,在此记录下学习过程,同时也希望能够帮助到其他学习的同学。
InfluxDB介绍
什么是时间序列数据?最简单的定义就是数据格式里包含timestamp字段的数据。比如股票市场的价格,环境中的温度,主机的CPU使用率等。但是又有什么数据是不包含timestamp的呢?几乎所有的数据都可以打上一个timestamp字段。时间序列数据更重要的一个属性是如何去查询它。在查询的时候,对于时间序列我们总是会带上一个时间范围去过滤数据。同时查询的结果里也总是会包含timestamp字段。
InfluxDB 是一个开源分布式时序、事件和指标数据库。使用 Go 语言编写,无需外部依赖。其设计目标是实现分布式和水平伸缩扩展。
它有三大特性:
- Time Series (时间序列):你可以使用与时间有关的相关函数(如最大,最小,求和等)
- Metrics(度量):你可以实时对大量数据进行计算
- Eevents(事件):它支持任意的事件数据
特点:
- schemaless(无结构),可以是任意数量的列
- min, max, sum, count, mean, median 一系列函数,方便统计
- Native HTTP API, 内置http支持,使用http读写
- Powerful Query Language 类似sql
- Built-in Explorer 自带web管理界面。(从1.4版本开始去除了自带的web管理界面)
安装部署InfluxDB
influxdb下载地址:
https://portal.influxdata.com/downloads
influxdb文档:
http://docs.influxdata.com/influxdb/v1.4/introduction/getting_started/
1.下载安装
对于在不同操作系统上安装,官网都有说明,我这里使用的是CentOS 7。
[root@docdesginer local]# wget https://dl.influxdata.com/influxdb/releases/influxdb-1.4.2.x86_64.rpm
[root@docdesginer local]# yum localinstall influxdb-1.4.2.x86_64.rpm
[root@docdesginer local]# rpm -ql influxdb
/etc/influxdb/influxdb.conf
/etc/logrotate.d/influxdb
/usr/bin/influx
/usr/bin/influx_inspect
/usr/bin/influx_stress
/usr/bin/influx_tsm
/usr/bin/influxd
/usr/lib/influxdb/scripts/influxdb.service
/usr/lib/influxdb/scripts/init.sh
/usr/share/man/man1/influx.1.gz
/usr/share/man/man1/influx_inspect.1.gz
/usr/share/man/man1/influx_stress.1.gz
/usr/share/man/man1/influx_tsm.1.gz
/usr/share/man/man1/influxd-backup.1.gz
/usr/share/man/man1/influxd-config.1.gz
/usr/share/man/man1/influxd-restore.1.gz
/usr/share/man/man1/influxd-run.1.gz
/usr/share/man/man1/influxd-version.1.gz
/usr/share/man/man1/influxd.1.gz
/var/lib/influxdb
/var/log/influxdb
2.启动
[root@docdesginer local]# systemctl start influxdb
[root@docdesginer local]# systemctl status influxdb
3.登录
客户端工具:
[root@docdesginer local]# /usr/bin/influx
Connected to http://localhost:8086 version 1.4.2
InfluxDB shell version: 1.4.2
>
查看数据库:
> SHOW DATABASES
name: databases
name
----
_internal
>
HTTP API访问:
[root@docdesginer ~]# curl -G http://localhost:8086/query --data-urlencode "q=SHOW DATABASES"
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"]]}]}
此时数据库中还有没有用户,还没开启认证。
开启认证
1.创建管理员
[root@docdesginer local]# /usr/bin/influx
Connected to http://localhost:8086 version 1.4.2
InfluxDB shell version: 1.4.2
> CREATE USER root WITH PASSWORD 'wisedu123' WITH ALL PRIVILEGES
> quit
2.修改配置文件,开启认证
By default, authentication is disabled in the configuration file. Enable authentication by setting the auth-enabled option to true in the [http] section of the configuration file:
[http]
enabled = true
bind-address = ":8086"
auth-enabled = true
log-enabled = true
write-tracing = false
pprof-enabled = false
https-enabled = false
https-certificate = "/etc/ssl/influxdb.pem"
重启InfluxDB:
[root@docdesginer ~]# systemctl restart influxdb
3.再次登录
客户端工具连接数据库:
[root@docdesginer ~]# influx
Connected to http://localhost:8086 version 1.4.2
InfluxDB shell version: 1.4.2
> show databases;
ERR: unable to parse authentication credentials
Warning: It is possible this error is due to not setting a database.
Please set a database with the command "use <database>".
>
[root@docdesginer ~]# /usr/bin/influx
Connected to http://localhost:8086 version 1.4.2
InfluxDB shell version: 1.4.2
> auth
username: root
password:
> show databases;
name: databases
name
----
_internal
>
或者
[root@docdesginer ~]# /usr/bin/influx -username root -password wisedu123 -precision rfc3339
Connected to http://localhost:8086 version 1.4.2
InfluxDB shell version: 1.4.2
> show databases;
name: databases
name
----
_internal
>
HTTP API:
[root@docdesginer ~]# curl -G http://localhost:8086/query --data-urlencode "q=SHOW DATABASES"
{"error":"unable to parse authentication credentials"}
[root@docdesginer ~]# curl -G http://localhost:8086/query -u root:wisedu123 --data-urlencode "q=SHOW DATABASES"
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"]]}]}
InfluxDB概念
1.influxdb相关名词(可类比关系型数据库)
- database:数据库。
- measurement:数据库中的表。它就是tag,field,time的容器;对于influxDB的measurement来说,field是必须的,并且不能根据field来排序;Tag是可选的,tag可以用来做索引,tag是以字符串的形式存放的。
- points:表里面的一行数据。
2.influxDB中独有的概念
(1)Point由时间戳(time)、数据(field)和标签(tags)组成。
- time:每条数据记录的时间,也是数据库自动生成的主索引;
- fields:各种记录的值;
- tags:各种有索引的属性。
InfluxDb不需要做schema定义,这意味着你可以随意的添加measurements, tags, and fields at any time。
(2)series
a series is the collection of data that share a retention policy, measurement, and tag set
所有在数据库中的数据,都需要通过图表来展示,而这个series表示这个表里面的数据,可以在图表上画成几条线:通过tags排列组合算出来。
其实一个series就是一个测点,或者说一条曲线,那么retention policy, measurement, tagset就共同组成了一个定位测点序列的唯一标识。
point,就是某个series的同一个时刻的多个field的value,就组成了一个point;其实就是一条曲线上的一个点。
(3)retention policy
保留策略,用于决定要保留多久的数据,保存几个备份,以及集群的策略等。
InfluxDB基本操作
连接数据库:
[root@docdesginer ~]# /usr/bin/influx -username root -password wisedu123 -precision rfc3339
Connected to http://localhost:8086 version 1.4.2
InfluxDB shell version: 1.4.2
>
这里的-precision参数指定了时间戳的格式为rfc3339,也可以不使用该参数。
查看数据库:
> SHOW DATABASES
name: databases
name
----
_internal
>
创建数据库:
> CREATE DATABASE mydb
> SHOW DATABASES
name: databases
name
----
_internal
mydb
>
进入数据库:
> USE mydb
Using database mydb
>
插入数据:
influxDB存储数据采用的是Line Protocol格式。
Line Protocol格式:写入数据库的Point的固定格式。格式如下:
<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
比如:
weather,location=us-midwest temperature=82 1465839830100400200
| -------------------- -------------- |
| | | |
| | | |
+-----------+--------+-+---------+-+---------+
|measurement|,tag_set| |field_set| |timestamp|
+-----------+--------+-+---------+-+---------+
【注意】:最后的timestamp是 unix时间戳*1000000000 的值,或者使用 %Y-%m-%dT%H:%M:%SZ 这种格式。使用其他格式在插入时会报错。
示例:
> INSERT cpu,host=serverA,region=us_west value=0.64
其中:
- cpu是表名
- host=serverA,region=us_west 是tag
- value=0.64是field
想对此格式有详细的了解参见官方文档
查询数据:
influxDB是支持类sql语句的,具体的查询语法都差不多。
> select * from cpu
name: cpu
time host region value
---- ---- ------ -----
2017-12-15T13:17:09.660446488Z serverA us_west 0.64
【注意】:InfluxDB集群功能已经不再开源。要想使用集群服务需要购买企业版。开源版和企业版的主要区别就是企业版的InfluxDB支持集群,而开源版不支持,此外企业版提供了先进的备份/恢复功能,而开源版本没有。但InfluxDB单机版性能也足够支撑中小公司的业务了。
InfluxDB数据保存策略(Retention Policies)
InfluxDB每秒可以处理成千上万条数据,要将这些数据全部保存下来会占用大量的存储空间,有时我们可能并不需要将所有历史数据进行存储,因此,InfluxDB推出了数据保留策略(Retention Policies),用来让我们自定义数据的保留时间。
InfluxDB的数据保留策略(RP) 用来定义数据在InfluxDB中存放的时间,或者定义保存某个期间的数据。
一个数据库可以有多个保留策略,但每个策略必须是独一无二的。
1.查询策略
可以通过如下语句查看数据库的现有策略:
> SHOW RETENTION POLICIES ON mydb
name duration shardGroupDuration replicaN default
---- -------- ------------------ -------- -------
autogen 0s 168h0m0s 1 true
>
【说明】:数据库mydb只有一个策略,各字段的含义如下:
- name:名称,此示例名称为 autogen。当你创建一个数据库的时候,InfluxDB会自动为数据库创建一个名叫 autogen 的策略,这个策略会永久保存数据。你可以重命名这个策略,并且在InfluxDB的配置文件中禁止掉自动创建策略。
- duration:数据保存时间,0代表无限制
- shardGroupDuration:shardGroup的存储时间,shardGroup是InfluxDB的一个基本储存结构。
- replicaN:全称是REPLICATION,副本个数
- default:是否是默认策略。
这里有两个概念:
shard:
shard 在 InfluxDB 中是一个比较重要的概念,它和 retention policy 相关联。每一个存储策略下会存在许多 shard,每一个 shard 存储一个指定时间段内的数据,并且不重复,例如 7点-8点 的数据落入 shard0 中,8点-9点的数据则落入 shard1 中。每一个 shard 都对应一个底层的 tsm 存储引擎,有独立的 cache、wal、tsm file。
创建数据库时会自动创建一个默认存储策略,永久保存数据,对应的在此存储策略下的 shard 所保存的数据的时间段为 7 天,也就是上面查询时看到的168h。计算的函数如下:
func shardGroupDuration(d time.Duration) time.Duration {
if d >= 180*24*time.Hour || d == 0 { // 6 months or 0
return 7 * 24 * time.Hour
} else if d >= 2*24*time.Hour { // 2 days
return 1 * 24 * time.Hour
}
return 1 * time.Hour
}
如果创建一个新的 retention policy 设置数据的保留时间为 1 天,则单个 shard 所存储数据的时间间隔为 1 小时,超过1个小时的数据会被存放到下一个 shard 中。
shard group:
shard group是shards的逻辑容器。
2.创建策略
语法:
CREATE RETENTION POLICY <retention_policy_name> ON <database_name> DURATION <duration> REPLICATION <n> [SHARD DURATION <duration>] [DEFAULT]
其中:SHARD DURATION子句决定了每个shard group存储的时间间隔,在永久存储的策略里这个子句是无效的。这个子句是可选的。shard group duration默认由策略的 duration 决定。
Retention Policy’s DURATION | Shard Group Duration |
---|---|
< 2 days | 1 hour |
>= 2 days and <= 6 months | 1 day |
> 6 months | 7 days |
示例1:为数据库mydb创建一个策略
CREATE RETENTION POLICY "one_day_only" ON "mydb" DURATION 1d REPLICATION 1
示例2:为数据库mydb创建一个默认策略。
CREATE RETENTION POLICY "one_day_only" ON "mydb" DURATION 23h60m REPLICATION 1 DEFAULT
3.修改策略
ALTER RETENTION POLICY <retention_policy_name> ON <database_name> DURATION <duration> REPLICATION <n> SHARD DURATION <duration> DEFAULT
4.删除策略
DROP RETENTION POLICY <retention_policy_name> ON <database_name>
【注意】:策略这个关键词“POLICY”在使用是应该大写,小写应该会出错。
当一个表使用的策略不是默认策略时,在进行操作时一定要显式的指定策略名称,否则会出现错误。
Chronograf介绍
Influxdb在1.3以后版本已经关闭了内置的8086的web管理功能,需要单独的工具来管理。而这个工具就是Chronograf。
其实Chronograf是TICK技术栈的一个组成部分。TICK是InfluxdDB公司推出的监控套件,承包指标采集、分析、画图等时序数据库上下游的工作,有点模仿日志分析系统ELK套件的意思。TICK包含:
- T = Telegraf is a plugin-driven server agent for collecting and reporting metrics.
- I = InfluxDB is a time series database built from the ground up to handle high write and query loads.
- C = Chronograf is a graphing and visualization application for performing ad hoc exploration of data.
- K = Kapacitor is a data processing framework proving alerting, anomaly detection and action frameworks.
也就是说:
- Telegraf:数据采集
- InfluxDB:数据接收和存储
- Chronograf:数据汇总展示,报警等。
- Kapacitor:数据处理,比如监控策略等
安装Chronograf
1.安装部署
下载地址:https://portal.influxdata.com/downloads
[root@docdesginer local]# wget https://dl.influxdata.com/chronograf/releases/chronograf-1.3.10.0.x86_64.rpm
[root@docdesginer local]# yum localinstall chronograf-1.3.10.0.x86_64.rpm
[root@docdesginer local]# rpm -ql chronograf
/etc/logrotate.d/chronograf
/usr/bin/chronograf
/usr/lib/chronograf/scripts/chronograf.service
/usr/lib/chronograf/scripts/init.sh
/usr/share/chronograf/canned/apache.json
/usr/share/chronograf/canned/consul.json
/usr/share/chronograf/canned/consul_agent.json
...
2.启动
[root@docdesginer local]# systemctl start chronograf
3.访问Chronograf
浏览器输入http://IP:8888
查询:
在查询时,最好数据库名和表名都加上引号。