一、InfluxDB Java 客户端
在InfluxDB入门记录(一)中介绍了如何安装和如何在SpringBoot框架中创建InfluxDB的Java客户端,InfluxDB的JAVA客户端是针对 InfluxDB HTTP REST API 的完整 Java 封装,相当于InfluxDB 平台的 Java SDK 入口,可以使用Java语言完成对 InfluxDB 的增删改查操作。
二、通过Java客户端进行数据增删改查
在对数据进行操作前,需要先创建客户端:
InfluxDBClient influxDBClient = InfluxDBClientFactory.create("http://localhost:8086", token, org, bucket);
1、插入数据
插入数据需要获取客户端的写入API,写入API分为异步写入和同步写入:
WriteApiBlocking writeApi = client.getWriteApiBlocking(); //同步写入数据
WriteApi writeApi = client.makeWriteApi(); //异步批量写入
- WriteApiBlocking:同步写入数据,会阻塞,适合小规模写入,不适用于高并发
- WriteApi:异步写入数据,自动批量聚合,吞吐量大
WriteApiBlocking
WriteApiBlocking 中的常用API如下:
void writePoint(Point point);
void writePoints(List<Point> points);
void writePoint(Point point, WriteParameters parameters)
void writePoints(List<Point> points, WriteParameters parameters)
WriteParameters 可用于设置WriteApiBlocking写入数据时的相关参数,包括:
bucket- 指定写入操作的目标存储桶。org- 指定写入操作的目标组织。precision- 时间戳的精度。consistency- 该数据点的写入一致性。
WriteApi
WriteApi的创建方法共有两种:
WriteApi makeWriteApi()
WriteApi makeWriteApi(WriteOptions writeOptions)
WriteApi使用后台线程将数据导入 InfluxDB,并且应该以单例模式运行。因此 不要每次写入都创建新实例。writeOptions支持用户自定义写入配置,参数信息和默认配置参数如下:
batchSize = 1000; //每次批量写入的最大数据条数
flushInterval = 1000 ms; //定时刷新间隔,必变长时间不写入
retryInterval = 5000 ms; //写入失败后的重试间隔
jitterInterval = 0; //写入抖动时间,避免多个客户端同时写入造成流量峰值
bufferLimit = 10_000; //客户端缓存队列最大容量
concatMapPrefetch = 2; //设置从上游预先获取的数据项数量,用于流式背压控制
captureBackpressureData = false; //是否捕获被丢弃的数据
WriteApi中的API与WriteApiBlocking基本一致:
void writePoint(Point point);
void writePoints(List<Point> points);
void writePoint(Point point, WriteParameters parameters)
void writePoints(List<Point> points, WriteParameters parameters)
Point
Point定义了要写入数据库的值。Point设置示例如下:
Point point = Point.measurement("temperature") //创建一个新的Point
.addTag("location", "west") //添加Tag信息,(tag key, tag value)
.addField("value", 55D) //添加field信息,(field key, field value)
.time(Instant.now().toEpochMilli(), WritePrecision.MS); //更新时间戳,否则使用当前时间
2、删除数据
删除数据需要获取客户端的删除API,删除指定时间内的数据:
DeleteApi deleteApi = client.getDeleteApi();
deleteApi.delete(
OffsetDateTime.ofInstant(startTime, ZoneId.of("Asia/Shanghai")),
OffsetDateTime.ofInstant(endTime, ZoneId.of("Asia/Shanghai")),
bucket,
org);
3、查询数据
查询数据需要获取客户端的查询API:
QueryApi getQueryApi ()
(1)、普通查询
QueryApi中的常用查询api如下:
List<FluxTable> query(String query) //查询并将返回值映射到List<FluxTable>中
其中query是 InfluxDB 中的 Flux 查询语句。Flux语句是 InfluxDB 特有的语言,查询示例如下:
from(bucket: "my-bucket")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "cpu")
重新学习一门语言的成本往往是很高的,因此 InfluxDB提供了 flux-dsl 项目,这是一个Flux 查询构建器(Query Builder)模块。它不像手写字符串那样拼接 Flux 语句,而是通过 Java API 的方法链式调用来构造 Flux 查询语句。如上代码可以替换为:
Flux flux = Flux
.from("myBucket")
.range(-1L, ChronoUnit.HOURS)
.filter(Restrictions.measurement().equal("cpu"));
String query = flux.toString();
List<FluxTable> results = queryApi.query(query);
更多查询语句的使用方法可参考 flux-dsl 的说明文档。
(2)、流式查询
QueryApi中的还有很多常用的查询api:
void query(String query, BiConsumer<Cancellable, FluxRecord> onNext) //流式查询,边查询边处理
如下是流式查询的使用方法示例,cancellable用于提前终止查询:
queryApi.query(flux, (cancellable, record) -> {
System.out.println("Time: " + record.getTime());
System.out.println("Measurement: " + record.getMeasurement());
System.out.println("Field: " + record.getField());
System.out.println("Value: " + record.getValue());
System.out.println("Tags: " + record.getValues());
System.out.println("--------------");
// 示例:如果值大于100则提前终止查询
if (record.getValue() instanceof Number) {
Number value = (Number) record.getValue();
if (value.doubleValue() > 100) {
System.out.println("Value > 100,停止查询");
cancellable.cancel(); // 终止查询
}
}
});
(3)、查询并直接映射为 POJO
<M> List<M> query(String query, Class<M> measurementType) //将返回值映射为 POJO
以下是该方法的使用示例:
List<CpuData> results = queryApi.query(flux, CpuData.class);
其中CpuData类中需要增加 InfluxDB相关注解:
// Column中的name为measurement中的列名,tag = true表示当前字段为tag内容
@Measurement(name = "cpu")
public class CpuData {
@Column(name = "_time")
private Instant time;
@Column(name = "_value")
private Double value;
@Column(name = "host", tag = true)
private String host;
}
(4)FluxRecord 和 FluxTable 的使用方法
FluxRecord 和 FluxTable 是记录 InfluxDB查询结果的类,使用方法如下:
List<FluxTable> tables = queryApi.query(flux);
for (FluxTable fluxTable : tables) {
List<FluxRecord> records = fluxTable.getRecords();
for (FluxRecord fluxRecord : records) {
System.out.println(fluxRecord.getTime() + ": " + fluxRecord.getValueByKey("_value"));
}
}