|
|
俊秀的豆腐 · 在XML命名空间中不存在WPF自定义控件-腾 ...· 2 年前 · |
|
|
任性的黑框眼镜 · SpringBoot整合Druid配置数据源 ...· 2 年前 · |
|
|
想出家的山寨机 · 左移和右移运算符(“<>”) | ...· 2 年前 · |
Go语言标准库中文文档
[root@localhost influxdata]# pwd
/root/dev/golib/src/github.com/influxdata
[root@localhost influxdata]# tree -d -L 1
.
├── influxdb
├── influxql
├── usage-client
├── yamux
└── yarpc
目录解析说明:
为源码的主目录
实现了InfluxDB查询语言的解析器(源码主目录里面引用的是influxdata/influxdb/influxql,没有该目录的相关引用)
client lib V1版本
Yet another Multiplexer(又一个多路复用器)是Golang的多路复用库
Yet Another RPC (又一个RPC)是Golang的RPC库
一级目录结构如下:
[root@localhost influxdb]# pwd
/root/dev/golib/src/github.com/influxdata/influxdb
[root@localhost influxdb]# tree -d -L 1
.
├── client
├── cmd
├── coordinator
├── etc
├── importer
├── influxql
├── internal
├── man
├── models
├── monitor
├── pkg
├── scripts
├── services
├── stress
├── tcp
├── tests
├── toml
├── tsdb
└── uuid
二级目录结构如下:
[root@localhost influxdb]# tree -d -L 2
.
├── client
│ └── v2
├── cmd
│ ├── influx
│ ├── influxd
│ ├── influx_inspect
│ ├── influx_stress
│ └── influx_tsm
├── coordinator
├── etc
│ └── burn-in
├── importer
│ └── v8
├── influxql
│ ├── internal
│ └── neldermead
├── internal
├── man
├── models
├── monitor
│ └── diagnostics
├── pkg
│ ├── deep
│ ├── escape
│ ├── limiter
│ ├── pool
│ └── slices
├── scripts
├── services
│ ├── admin
│ ├── collectd
│ ├── continuous_querier
│ ├── graphite
│ ├── httpd
│ ├── meta
│ ├── opentsdb
│ ├── precreator
│ ├── retention
│ ├── snapshotter
│ ├── subscriber
│ └── udp
├── stress
│ ├── stress_test_server
│ └── v2
├── tcp
├── tests
│ ├── siege
│ ├── tmux
│ └── urlgen
├── toml
├── tsdb
│ ├── engine
│ └── internal
└── uuid
目录解析说明:
client lib V2版本
InfluxDB相关程序所在目录
其中:
influxd目录为InfluxDB主程序代码;
influx为InfluxDB自带的控制台管理工具源码;
influx_inspect为InfluxDB数据查看工具源码;
influx_stress为InfluxDB压力测试工具源码;
influx_tsm为数据库转换工具(将数据库从b1或bz1格式转换为tsm1格式)源码
协调器,负责数据的写入和一些创建语句的执行。
在InfluxDB的ChangeLog中显示在v1.0.0中使用coordinator替换cluster,感觉自建集群功能可以通过此模块实现。
存放默认配置
版本向后兼容相关代码,在ReadMe中已经提到:Version 0.8.9 of InfluxDB adds support to export your data to a format that can be imported into 0.9.3 and later.
实现了 InfluxDB查询语言 的解析器
主要实现了MetaClient接口
帮助手册
基础数据类型定义
InfluxDB系统监控
一些通用包的集合。
deep里面主要实现了deepValueEqual方法,用于深层次比较两个值是否相等;
escape里面主要实现了byte和string两种数据类型转义字符的相关操作;
limiter里面主要是一个基于channel实现的简单并发限制器Fixed;
pool里面主要实现了Bytes和Generic两种类型的Pool,在Pool中的对象不使用时不会被垃圾回收自动清理掉;
slices 里面主要实现了一些string数组的操作;
该目录存放的是一些关于InfluxDB的脚本。
该目录存放的是一些关于InfluxDB的服务。
admin 为InfluxDB内置的管理服务;
collectd 为collectd( https://collectd.org )对接服务,可以接收通过UDP发送过来的collectd格式数据;
continuous_querier 为InfluxDB的CQ服务;
graphite 为InfluxDB的graphite服务;
httpd 为InfluxDB的http服务,可以通过该接口进行数据库数据的写入和查询等操作;
meta 为InfluxDB的元数据服务,用于管理数据库的元数据相关内容;
opentsdb 为InfluxDB的opentsdb服务,可用于替换opentsdb;
precreator 为InfluxDB的Shard预创建服务;
retention 为InfluxDB的数据保留策略的强制执行服务,主要用于定时删除文件;
snapshotter 为InfluxDB的快照服务;
subscriber 为InfluxDB的订阅服务;
udp 为InfluxDB的udp服务,可以通过该接口进行数据库的写入和查询等操作;
该目录存放的是压力测试相关内容。
网络连接的多路复用。
测试相关内容
toml的解析器,和另一个toml解析器(github.com/BurntSushi/toml)不同,为独立的解析模块,主要是解析时间字符串和磁盘容量数据。
tsdb目录主要是时序数据库的实现。
该目录里面主要存放uuid生成的相关代码。
在
src
源文件中编译执行influx:
step1:先执行
cmd\influxd\main.go
文件,启动本地influxDB实例;
step2:执行
cmd\influx\main.go
文件,将influx连接到本地的influxDB实例上;
在cmd中运行
influx.exe
可执行文件,从而执行influx:
//用cmd方式执行influx可执行文件:influx2/bin/influx.exe(前提先运行influxd.exe)
$ influx -precision rfc3339
Connected to http://localhost:8086 version 1.2.x
InfluxDB shell 1.2.x
###说明
# InfluxDB的HTTP接口默认起在8086上,所以influx默认也是连的本地的8086端口,你可以通过influx --help来看怎么修改默认值。
# -precision参数表明了任何返回的时间戳的格式和精度,在上面的例子里,rfc3339是让InfluxDB返回RFC339格式(YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ)的时间戳。
这样这个命令行已经准备好接收influx的查询语句了(简称InfluxQL),用
exit
可以退出命令行。
第一次安装好InfluxDB之后是没有数据库的(除了系统自带的
_internal
),因此创建一个数据库是我们首先要做的事,通过
CREATE DATABASE <db-name>
这样的InfluxQL语句来创建,其中
<db-name>
就是数据库的名字。数据库的名字可以是被双引号引起来的任意Unicode字符。 如果名称只包含ASCII字母,数字或下划线,并且不以数字开头,那么也可以不用引起来;
创建一个
mydb
数据库:
> CREATE DATABASE mydb
说明:在输入上面的语句之后,并没有看到任何信息,这在CLI里,表示语句被执行并且没有错误,如果有错误信息展示,那一定是哪里出问题了,这就是所谓的没有消息就是好消息;
现在数据库
mydb
已经创建好了,我们可以用
SHOW DATABASES
语句来看看已存在的数据库:
> SHOW DATABASES
name: databases
name
----
_internal
mydb
说明:_internal数据库是用来存储InfluxDB内部的实时监控数据的。
大部分InfluxQL需要作用在一个特定的数据库上。你当然可以在每一个查询语句上带上你想查的数据库的名字,但是CLI提供了一个更为方便的方式
USE
,这会为你后面的所以的请求设置到这个数据库上;
> USE mydb
Using database mydb
以下的操作都作用于
mydb
这个数据库之上;
首先对数据存储的格式来个入门介绍;InfluxDB里存储的数据被称为时间序列数据,其包含一个数值,就像CPU的load值或是温度值;时序数据有零个或多个数据点,每一个都是一个指标值;数据点包括
time
(一个时间戳),
measurement
(例如cpu_load),至少一个k-v格式的
field
(也即指标的数值例如 “value=0.64”或者“temperature=21.2”),零个或多个
tag
,其一般是对于这个指标值的元数据(例如“host=server01”, “region=EMEA”, “dc=Frankfurt);
在概念上,你可以将
measurement
类比于SQL里面的table,其
主键索引
总是
时间戳
;
tag
和
field
是在table里的其他列,
tag
是被索引起来的,
field
没有;不同之处在于,在InfluxDB里,你可以有几百万的measurements,你不用事先定义数据的scheme,并且null值不会被存储;
将数据点写入InfluxDB,只需要遵守如下的行协议:
<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
使用CLI插入单条的时间序列数据到InfluxDB中,用
INSERT
后跟数据点:
INSERT cpu,host=serverA,region=us_west value=0.64
说明:我们在写入的时候没有包含时间戳,当没有带时间戳的时候,InfluxDB会自动添加本地的当前时间作为它的时间戳。
这样一个measurement为
cpu
,tag是
host
和
region
,
value
值为
0.64
的数据点被写入了InfluxDB中;
跟SQL语法类型
> SELECT "host", "region", "value" FROM "cpu"
name: cpu
time host region value
---- ---- ------ -----
1604823941584418500 serverA us_west 0.64
> select * from cpu
name: cpu
time host region value
---- ---- ------ -----
1604823941584418500 serverA us_west 0.64
CREATE DATABASE "testDB" --创建数据库
show databases --展示所有数据库
use testDB --使用testDB数据库
SHOW MEASUREMENTS --查询当前数据库中含有的表
SHOW FIELD KEYS --查看当前数据库所有表的字段
SHOW series from pay --查看key数据
SHOW TAG KEYS FROM "pay" --查看key中tag key值
SHOW TAG VALUES FROM "pay" WITH KEY = "merId" --查看key中tag 指定key值对应的值
SHOW TAG VALUES FROM cpu WITH KEY IN ("region", "host") WHERE service = 'redis'
DROP SERIES FROM <measurement_name[,measurement_name]> WHERE <tag_key>='<tag_value>' --删除key
SHOW CONTINUOUS QUERIES --查看连续执行命令
SHOW QUERIES --查看最后执行命令
KILL QUERY <qid> --结束命令
SHOW RETENTION POLICIES ON mydb --查看保留数据
查询数据
SELECT * FROM /.*/ LIMIT 1 --查询当前数据库下所有表的第一行记录
select * from pay order by time desc limit 2
select * from db_name."POLICIES name".measurement_name --指定查询数据库下数据保留中的表数据 POLICIES name数据保留
删除数据
delete from "query" --删除表所有数据,则表就不存在了
drop MEASUREMENT "query" --删除表(注意会把数据保留删除使用delete不会)
DELETE FROM cpu
DELETE FROM cpu WHERE time < '2000-01-01T00:00:00Z'
DELETE WHERE time < '2000-01-01T00:00:00Z'
DROP DATABASE “testDB” --删除数据库
DROP RETENTION POLICY "dbbak" ON mydb --删除保留数据为dbbak数据
DROP SERIES from pay where tag_key='' --删除key中的tag
SHOW SHARDS --查看数据存储文件
DROP SHARD 1
SHOW SHARD GROUPS
SHOW SUBSCRIPTIONS
参考文字:
influxdb语法
cmd
命令行中可以通过HTTP接口连接数据库,从而进行读写操作;
使用
POST
方式发送到URL的
/query
路径,参数
q
为
CREATE DATABASE
,下面的例子发送一个请求到本地运行的InfluxDB创建数据库
mydb
:
curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
通过HTTP接口
POST
数据到
/write
路径是我们往InfluxDB写数据的主要方式。下面的例子写了一条数据到
mydb
数据库。这条数据的组成部分是measurement为
cpu_load_short
,tag 的 key为 host 和 region,对应 tag 的 value 是
server01
和
us-west
,field的key是
value
,对应的数值为
0.64
,而时间戳是
1434055562000000000
;
第一次尝试
>>C:\Users\Luweir>curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'
弹出以下提示:
curl: (1) Protocol "'http" not supported or disabled in libcurl
curl: (6) Could not resolve host: value=0.64
curl: (6) Could not resolve host: 1434055562000000000'
查阅后发现这个命令中 ' ' 的部分都要使用 " "
更正后:
>>C:\Users\Luweir>curl -i -XPOST "http://localhost:8086/write?db=mydb" --data-binary "cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000"
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: 410f780d-219d-11eb-800a-9c7bef3eea50
X-Influxdb-Build: OSS
X-Influxdb-Version: unknown
X-Request-Id: 410f780d-219d-11eb-800a-9c7bef3eea50
Date: Sun, 08 Nov 2020 08:34:45 GMT
HTTP返回值:
2xx:如果你写了数据后收到HTTP 204 No Content ,说明写入成功了;
4xx:表示InfluxDB不知道你发的是什么鬼;
5xx:系统过载或是应用受损;
当写入这条数据点的时候,你必须明确存在一个数据库对应名字是
db
参数的值。如果你没有通过
rp
参数设置retention policy的话,那么这个数据会写到
db
默认的retention policy中;
POST的请求体我们称之为
Line Protocol
,包含了你希望存储的时间序列数据。它的组成部分有measurement,tags,fields和timestamp。measurement是InfluxDB必须的,严格地说,tags是可选的,但是对于大部分数据都会包含
tags用来区分数据的来源
,让查询变得容易和高效。
tag的key和value都必须是字符串
。fields的key也是必须的,而且是字符串**,**
默认情况下field的value是float类型的
。timestamp在这个请求行的最后,是一个从1/1/1970 UTC开始到现在的一个纳秒级的Unix time,它是可选的,如果不传,InfluxDB会使用服务器的本地的纳米级的timestamp来作为数据的时间戳,注意无论哪种方式,在InfluxDB中的timestamp只能是UTC时间。
写入文件中的数据:
把下列数据行写入一个txt文件:以
cpu_data.txt
为例
cpu_load_short,host=server02 value=0.67
cpu_load_short,host=server02,region=us-west value=0.55 1422568543702900257
cpu_load_short,direction=in,host=server01,region=us-west value=2.0 1422568543702900257
把
cpu_data.txt
的数据写入
mybd
数据库:
curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary @cpu_data.txt
说明:如果你的数据文件的数据点大于5000时,你必须把他们拆分到多个文件再写入InfluxDB。因为默认的HTTP的timeout的值为5秒,虽然5秒之后,InfluxDB仍然会试图把这批数据写进去,但是会有数据丢失的风险;
InfluxDB是一个无模式(schemaless)的数据库,你可以在任意时间添加measurement,tags和fields。注意:如果你 试图写入一个和之前的类型不一样的数据 (例如,filed字段之前接收的是数字类型,现在写了个字符串进去),那么InfluxDB会 拒绝 这个数据;
以下列数据为例:
数据展示了在2015年8月18日午夜至2015年8月18日上午6时12分在两个地点
location
(地点
1
和地点
2
)显示两名科学家
scientists
(
langstroth
和
perpetua
)计数的蝴蝶(
butterflies
)和蜜蜂(
honeybees
)数量;
其中census是
measurement
,butterflies和honeybees是
field key
,location和scientist是
tag key
;
InfluxDB是一个时间序列数据库,因此我们开始一切的根源就是——时间。在上面的数据中有一列是
time
,在InfluxDB中所有的数据都有这一列。
time
存着时间戳,这个时间戳以
RFC3339
格式展示了与特定数据相关联的UTC日期和时间;
接下来两个列叫作
butterflies
和
honeybees
,称为fields。fields由field key和field value组成。field key(
butterflies
和
honeybees
)都是字符串,他们存储元数据;field key
butterflies
告诉我们蝴蝶的计数从12到7;field key
honeybees
告诉我们蜜蜂的计数从23变到22;
field value就是你的数据,它们可以是字符串、浮点数、整数、布尔值,因为InfluxDB是时间序列数据库,所以field value总是和时间戳相关联;
示例中,field value如下:
12 23
1 30
11 28
3 28
2 11
1 10
8 23
7 22
field是InfluxDB数据结构所必需的一部分——在InfluxDB中不能没有field;还要注意, field是没有索引的 ;如果使用field value作为过滤条件来查询,则必须扫描其他条件匹配后的所有值;因此,这些查询相对于tag上的查询(下文会介绍tag的查询)性能会低很多。 一般来说,字段不应包含常用来查询的元数据;
样本数据中的最后两列(
location
和
scientist
)就是tag; tag由tag key和tag value组成。tag key和tag value都作为字符串存储,并记录在
元数据
中。示例数据中的 tag key是
location
和
scientist
。
location
有两个tag value:
1
和
2
。
scientist
还有两个tag value:
langstroth
和
perpetua
。
在上面的数据中,tag set 是不同的每组 tag key 和 tag value的集合,示例数据里有四个tag set:
location = 1, scientist = langstroth
location = 2, scientist = langstroth
location = 1, scientist = perpetua
location = 2, scientist = perpetua
tag不是必需的字段,但是在你的数据中使用tag总是大有裨益,因为不同于field, tag是索引起来的。这意味着 对tag的查询更快 ,tag是存储常用元数据的最佳选择;
measurement作为tag,fields和time列的容器,measurement的名字是存储在相关fields数据的描述。 measurement的名字是字符串,对于一些SQL用户,measurement在概念上类似于表。样本数据中唯一的测量是
census
。 名称
census
告诉我们,fields值记录了
butterflies
和
honeybees
的数量,而不是不是它们的大小,方向或某种幸福指数;
单个measurement可以有不同的retention policy。 retention policy描述了InfluxDB保存数据的时间(DURATION)以及这些存储在集群中数据的副本数量(REPLICATION) ;
在样本数据中,measurement
census
中的所有内容都属于
autogen
的retention policy。 InfluxDB自动创建该存储策略; 它具有无限的持续时间和复制因子设置为1。
series是共同retention policy,measurement 和 tag set 的集合;以上数据由四个series组成:
最后,point就是具有相同timestamp的相同series的field集合。例如,这就是一个point:
例子里的series的retention policy为
autogen
,measurement为
census
,tag set为
location = 1, scientist = perpetua
。point的timestamp为
2015-08-18T00:00:00Z
。
刚刚涵盖的所有内容都存储在数据库(database)中——示例数据位于数据库
my_database
中。 InfluxDB数据库与传统的关系数据库类似,并作为users,retention policy,continuous以及point的逻辑上的容器。;
数据库可以有多个users,retention policy,continuous和measurement。 InfluxDB是一个无模式数据库,意味着可以随时添加新的measurement,tag和field。 它旨在使时间序列数据的工作变得非常棒;
更多见:https://jasper-zhang1.gitbooks.io/influxdb/content/Concepts/glossary.html
retention policy中的一个属性,决定InfluxDB中数据保留多长时间;在duration之前的数据会自动从database中删除掉;
InfluxDB数据结构的一部分由series中的的一堆field组成。 每个点由其series和timestamp唯一标识。
你不能在同一series中存储多个具有相同timestamp的点。 相反,当你使用与该series中现有点 相同的timestamp 记将新point写入同一series时,该field set将成为旧field set和新field set的并集;
shard包含 实际的编码和压缩数据 ,并由磁盘上的TSM文件表示。 每个shard都属于唯一的一个shard group。多个shard可能存在于单个shard group中。每个shard包含一组特定的series。给定shard group中的给定series上的所有点将存储在磁盘上的相同shard(TSM文件)中;
下表是一个叫
foodships
的SQL数据库的例子,并有没有索引的
#_foodships
列和有索引的
park_id
,
planet
和
time
列;
这些数据在influxdb中看起来像这样:
参考上面的数据,一般可以这么说:
foodships
)和SQL数据库里的table类似;
park_id
和
planet
)类似于SQL数据库里索引的列;
#_foodships
)类似于SQL数据库里没有索引的列;
2015-04-16T12:00:00Z 5
)类似于SQL数据库的行;
基于这些数据库术语的比较,InfluxDB的continuous query和retention policy与SQL数据库中的存储过程类似。 它们被指定一次,然后定期自动执行。
当然,SQL数据库和InfluxDB之间存在一些重大差异。SQL中的
JOIN
不适用于InfluxDB中的measurement。而且,正如我们上面提到的那样,一个measurement就像一个SQL的table,其中
主索引总是被预设为时间
;InfluxDB的时间戳记必须在UNIX epoch(GMT)或格式化为日期时间RFC3339格式的字符串才有效。
InfluxQL的
select
语句来自于SQL中的
select
形式:
SELECT <stuff> FROM <measurement_name> WHERE <some_conditions>
where
是可选的,在InfluxDB里为了查询到上面数据,需要输入:
SELECT * FROM "foodships"
如果你仅仅想看planet为
Saturn
的数据:
SELECT * FROM "foodships" WHERE "planet" = 'Saturn'
如果你想看到planet为
Saturn
,并且在UTC时间为2015年4月16号12:00:01之后的数据:
SELECT * FROM "foodships" WHERE "planet" = 'Saturn' AND time > '2015-04-16 12:00:01'
如上例所示,InfluxQL允许您在
WHERE
子句中指定查询的时间范围。您可以使用包含单引号的日期时间字符串,格式为YYYY-MM-DD HH:MM:SS.mmm(mmm为毫秒,为可选项,您还可以指定微秒或纳秒。您还可以使用相对时间与
now()
来指代服务器的当前时间戳:
SELECT * FROM "foodships" WHERE time > now() - 1h
该查询输出measurement为
foodships
中的数据,其中时间戳比服务器当前时间减1小时(即最近一小时的数据);与now()做计算来决定时间范围的可选单位有:
|
字母 |
意思 |
|
u或µ |
微秒 |
|
ms |
毫秒 |
|
s |
秒 |
|
m |
分钟 |
|
h |
小时 |
|
d |
天 |
|
w |
星期 |
InfluxQL还支持正则表达式,表达式中的运算符,
SHOW
语句和
GROUP BY
语句;
InfluxDB是针对时间序列数据进行了优化的数据库;这些数据通常来自分布式传感器组,来自大型网站的点击数据或金融交易列表等。
这个数据有一个共同之处在于它只看一个点没什么用。一个读者说,在星期二UTC时间为12:38:35时根据他的电脑CPU利用率为12%,这个很难得出什么结论。 只有跟其他的series结合并可视化时,它变得更加有用 。随着时间的推移开始显现的趋势,是我们从这些数据里真正想要看到的。另外,时间序列数据通常是 一次写入 ,很少更新。
结果是,由于优先考虑create和read数据的性能而不是update和delete,InfluxDB不是一个完整的CRUD数据库,更像是一个CR-ud。
InfluxDB的行协议是一种写入数据点到InfluxDB的文本格式。必须要是这样的格式的数据点才能被Influxdb解析和写入成功;
你想要写入数据的measurement,这在行协议中是必需的,例如这里的measurement是
weather
。
你想要数据点中包含的tag,tag在行协议里是可选的。注意 measurement和tag set是用不带空格的逗号分开的 ;
用不带空格的
=
来分割一组tag的键值:
<tag_key>=<tag_value>
多组tag直接用不带空格的逗号分开:
<tag_key>=<tag_value>,<tag_key>=<tag_value>
例如上面的tag set由一个tag组成
location=us-midwest
,现在加另一个tag(
season=summer
),就变成了这样:
weather,location=us-midwest,season=summer temperature=82 1465839830100400200
为了获得最佳性能,您应该在将它们发送到数据库之前按键进行排序;排序应该与 Go bytes.Compare function 的结果相匹配;
分离 measurement 和 field set,或者如果您使用数据点包含tag set,则使用空格分隔tag set和field set;行协议中空格是必需的;
没有 tag set 的有效行协议:
weather temperature=82 1465839830100400200
每个数据点在行协议中至少需要一个field。使用无空格的
=
分隔field的键值对:
<field_key>=<field_value>
多组field直接用不带空格的逗号分开:
<field_key>=<field_value>,<field_key>=<field_value>
例如上面的field set由一个field组成
temperature=82
,现在加另一个field(
bug_concentration=98
),就变成了这样:
weather,location=us-midwest temperature=82,bug_concentration=98 1465839830100400200
使用空格分隔field set和可选的时间戳。如果你包含时间戳,则行协议中需要空格。
数据点的时间戳记以纳秒精度Unix时间。行协议中的时间戳是可选的。 如果没有为数据点指定时间戳,InfluxDB会使用服务器的本地纳秒时间戳。
在这个例子中,时间戳记是
1465839830100400200
(这就是RFC6393格式的
2016-06-13T17:43:50.1004002Z
)。下面的行协议是相同的数据点,但没有时间戳;当InfluxDB将其写入数据库时,它将使用您的服务器的本地时间戳而不是
2016-06-13T17:43:50.1004002Z
。
weather,location=us-midwest temperature=82
使用HTTP API来指定精度超过纳秒的时间戳,例如微秒,毫秒或秒。我们 建议使用最粗糙的精度,因为这样可以显着提高压缩率 ;
Field value可以是整数、浮点数、字符串和布尔值:
浮点数 —— 默认是浮点数,InfluxDB假定收到的所有field value都是浮点数。
以浮点类型存储上面的
82
:
weather,location=us-midwest temperature=82 1465839830100400200
整数 —— 添加一个
i
在field之后,告诉InfluxDB以整数类型存储:
以整数类型存储上面的
82
:
weather,location=us-midwest temperature=82i 1465839830100400200
字符串 —— 双引号把字段值引起来表示字符串:
以字符串类型存储值
too warm
:
weather,location=us-midwest temperature="too warm" 1465839830100400200
布尔型 —— 表示TRUE可以用
t
,
T
,
true
,
True
,
TRUE
;表示FALSE可以用
f
,
F
,
false
,
False
或者
FALSE
:
以布尔类型存储值
true
:
weather,location=us-midwest too_hot=true 1465839830100400200
在measurement中, field value的类型在分片内不会有差异,但在分片之间可能会有所不同 。例如,如果InfluxDB尝试将整数写入到与浮点数相同的分片中,则写入会失败:
> INSERT weather,location=us-midwest temperature=82 1465839830100400200
> INSERT weather,location=us-midwest temperature=81i 1465839830100400300
ERR: {"error":"field type conflict: input field \"temperature\" on measurement \"weather\" is type int64, already exists as type float"}
但是,如果InfluxDB将整数写入到一个新的shard中,虽然之前写的是浮点数,那依然可以写成功:
> INSERT weather,location=us-midwest temperature=82 1465839830100400200
> INSERT weather,location=us-midwest temperature=81i 1467154750000000000
>
> INSERT weather,location=us-midwest temperature='too warm'
ERR: {"error":"unable to parse 'weather,location=us-midwest temperature='too warm'': invalid boolean"}
InfluxDB是一个时间序列数据库。针对这种用例进行优化需要进行一些权衡,主要是以 牺牲功能为代价来提高性能 ;以下列出了一些权衡过的设计见解:
1、对于时间序列用例,我们假设如果相同的数据被多次发送,那么认为客户端几次都是同一笔数据。
2、 删除是罕见的事情 ,当它们发生时,肯定是针对大量的旧数据,这些数据对于写入来说是冷数据。
3、 对现有数据的更新是罕见的事件 ,持续地更新永远不会发生。时间序列数据主要是永远不更新的新数据。
4、绝大多数写入都是接近当前时间戳的数据,并且数据是按时间递增的顺序添加。
5、 规模至关重要。数据库必须能够处理 大量的读取和写入 。
6、能够写入和查询数据比具有强一致性更重要。
7、许多时间序列都是短暂的。经常是时间序列,只出现了几个小时,然后消失,例如一个新的主机,开机并监控数据被写入一段时间,然后被关闭。
8、没有数据点太重要了。
influxdb的存储引擎具有wal和一组只读数据文件,它们在概念上与LSM树中的SSTables类似;TSM文件包含排序,压缩的series数据。
存储引擎将多个组件结合在一起,并提供用于存储和查询series数据的外部接口。 它由许多组件组成,每个组件都起着特定的作用:
InfluxDB的0.9版本使用BoltDB作为底层存储引擎。下面要介绍的TSM,它在0.9.5中发布,是InfluxDB 0.11+中唯一支持的存储引擎,包括整个1.x系列。
BoltDB,这是一个基于内存映射B+ Tree的引擎,它是针对读取进行了优化的。最后,我们最终建立了我们自己的存储引擎,它在许多方面与LSM树类似。借助我们的新存储引擎,我们可以达到比B+ Tree实现高达45倍的磁盘空间使用量的减少,甚至比使用LevelDB及其变体有更高的写入吞吐量和压缩率。
数据的恢复restore要使用
gzip压缩算法
压缩,在路径
influxd/restore/restore.go
中;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RjN0lCD9-1606126788698)(https://raw.githubusercontent.com/Luweir/picpicgo/main/img/20201123144327.png)]
数据的备份back up要使用
gzip
压缩算法压缩,在路径
influxd/backup/restore.go
中;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IJqbunkv-1606126788699)(https://raw.githubusercontent.com/Luweir/picpicgo/main/img/20201123144331.png)]
func NewWriter(w io.Writer) *Writer
NewWriter创建并返回一个Writer;写入返回值的数据都会在压缩后写入w;调用者有责任在结束写入后调用返回值的Close方法。因为写入的数据可能保存在缓冲中没有刷新入下层;
func (z *Writer) Write(p []byte) (int, error)
Write将p压缩后写入下层 io.Writer 接口(NewWriter返回的Writer);压缩后的数据不一定会立刻刷新(压缩后的数据放在缓存中),除非Writer被关闭或者显式的刷新,才会将缓存中的数据刷新到下层 io.Writer 接口中;
接下来,关闭或者刷新缓存
func (z *Writer) Flush() error
Flush将缓冲中的压缩数据刷新到下层io.Writer接口中;本方法主要用在传输压缩数据的 网络连接 中,以保证远端的接收者可以获得足够的数据来重构数据报。Flush会阻塞直到所有缓冲中的数据都写入下层io.Writer接口后才返回;
所以关闭即可
func (z *Writer) Close() error
调用Close会关闭z,但不会关闭下层io.Writer接口;
func Copy
func Copy(dst Writer, src Reader) (written int64, err error)
将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。
对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝。
源代码
cmd/influxd/backup/backup.go
func NewReader(r io.Reader) (*Reader, error)
NewReader返回一个从 r 读取并解压数据的*Reader;其实现会缓冲输入流的数据,并可能从r中读取比需要的更多的数据;调用者有责任在读取完毕后调用返回值的Close方法;
源代码
cmd/influxd/restore/restore.go
: