最近做的项目涉及到InfluxDB,相对来说,这算是个稍微偏门些的了吧,毕竟时序数据库很多朋友都不会接触。这里记录下与spring的对接,以便刚入手的朋友参考。
参照官网上数据写入这块,首先是创建数据库(database),这里默认已经安装好了Influx,这个比较简单。
官网给出的Http示例都是curl的:
curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
执行及结果(我之前已经创建了几个数据库):
[root@iZ8vb8r420ejxfron03cj7Z ~]# curl -i -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Request-Id: 67281cc5-6c54-11e7-81bf-000000000000
X-Influxdb-Version: 1.2.4
Date: Wed, 19 Jul 2017 07:32:22 GMT
Transfer-Encoding: chunked
{"results":[{"statement_id":0}]}
[root@iZ8vb8r420ejxfron03cj7Z ~]# influx
Connected to http://localhost:8086 version 1.2.4
InfluxDB shell version: 1.2.4
> show databases
name: databases
name
----
_internal
testdb
mydb
mydb2
mydb3
mydb4
这是官网给的curl方法,这种方式很简单,而且在influx提供的web页面就可以实现这种功能。所以,下面介绍在代码层实现。
这里我借用的是spring的Resttemplate(使用httpclient也一样):
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
* Created by pangkunkun on 2017/7/19.
*/
public class InfluxDBTest {
public static void main(String[] args){
new InfluxDBTest().createDatabase();
}
public void createDatabase(){
String url="http://localhost:8086/query";
MultiValueMap postParameter=new LinkedMultiValueMap<>();
postParameter.add("q","CREATE DATABASE mydb1");
RestTemplate restTemplate=new RestTemplate();
restTemplate.postForObject(url,postParameter,Object.class);
}
}
因为已经创建了mydb数据库,所以这里我写的是mydb1。
在服务器上查询可见mydb1在最下方,已经创建Ok。
> show databases
name: databases
name
----
_internal
testdb
mydb
mydb2
mydb3
mydb4
mydb1
>
简单说明下,因为官网的示例是使用的post方法,data-urlencode这块的值我是把q当作一个字段,后边的创建语句当作具体值来传输的。
数据库创建OK了,现在开始写入数据。
先看官网给的示例:
curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'
上面代码中cpu_load_short是measurement(下边我们称之为表),host和region为tag,value是field,后边的时间戳是表中的time的值,如果不传,默认为当前的服务器时间。
下面开始代码实现(这里以mydb1为数据库):
public void write(){
String url="http://localhost:8086/write?db=mydb1";
String pointValue="cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000";
RestTemplate restTemplate=new RestTemplate();
restTemplate.postForObject(url,pointValue,Object.class);
}
查询结果
> use mydb1
Using database mydb1
> select * from cpu_load_short
name: cpu_load_short
time host region value
---- ---- ------ -----
1434055562000000000 server01 us-west 0.64
>
上边是单条数据插入,继续多条数据的插入。
官网示例:
curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary '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'
示例中显示每条记录之间用换行隔开,且每条数据的字段数可以不一样。
最简单的实现方式是把每条记录用换行符(\n)隔开,作为一个字符串来处理:
public void writeMultiplePoints(){
String url="http://localhost:8086/write?db=mydb1";
String pointValue="cpu_load_short,host=server02 num=0.67\ncpu_load_short,host=server02,region=us-west value=0.55 1422568543702900257\ncpu_load_short,direction=in,host=server01,region=us-west value=2.0 1422568543702900257";
RestTemplate restTemplate=new RestTemplate();
restTemplate.postForObject(url,pointValue,Object.class);
}
查询结果(其中有一条是上边单此插入的):
> select * from cpu_load_short
name: cpu_load_short
time direction host num region value
---- --------- ---- --- ------ -----
1422568543702900257 in server01 us-west 2
1422568543702900257 server02 us-west 0.55
1434055562000000000 server01 us-west 0.64
1500451813612820648 server02 0.67
>
下面示例中我们把表(measurement)也给写成不一样的,为了查看方便先把数据库清空了。
> delete from cpu_load_short
> select * from cpu_load_short
>
下面在插入语句中新增了一个my_test_table表:
public void writeMultiplePoints(){
String url="http://localhost:8086/write?db=mydb1";
String pointValue="my_test_table,host=server02 num=0.67\nmy_test_table,host=server02 num=0.81\ncpu_load_short,host=server02,region=us-west value=0.55 1422568543702900257\ncpu_load_short,direction=in,host=server01,region=us-west value=2.0 1422568543702900257";
RestTemplate restTemplate=new RestTemplate();
restTemplate.postForObject(url,pointValue,Object.class);
}
查询:
> select * from cpu_load_short
name: cpu_load_short
time direction host num region value
---- --------- ---- --- ------ -----
1422568543702900257 in server01 us-west 2
1422568543702900257 server02 us-west 0.55
> select * from my_test_table
name: my_test_table
time host num
---- ---- ---
1500452059044438976 server02 0.81
>
上面显示的my_test_table中只有一条数据,我上面代码中明明有两条,所以我做了几次测试,结果说明,如果tag的值都相同,且time也一样,这两条数据只能保存一条,而且是最后一条是保存成功的。
所以我猜测,这是由于前面所有tag都相同,且时间也一样,这时只能保存一条记录,即该point的唯一一条记录。最后一条数据保存成功,应该是把前边的已经写入的数据给覆盖重写了。具体大家可以测试下。
下边给出list个json辅助处理多条数据的方法:
public String listValue(){
List<String> list=new ArrayList();
list.add("cpu_load_short,host=server02 value=0.67\n");
list.add("cpu_load_short,host=server02,region=us-west value=0.55\n");
list.add("cpu_load_short,direction=in,host=server01,region=us-west value=2.0\n");
String listStr=list.toString();
listStr=listStr.replace("[","").replace("]","").replace(", ","");
return listStr;
}
public String jsonArry(){
JSONArray jsonArray=new JSONArray();
jsonArray.put("test_table,host=server02 value=0.67");
jsonArray.put("test_table,host=server02,region=us-west value=0.55");
jsonArray.put("test_table,direction=in,host=server01,region=us-west value=2.0");
String str=jsonArray.toString();
str=str.replace("[","").replace("]","").replace("\",\"","\n").replace("\"","");
return str;
}