InfluxDB入门记录(二)

3 阅读4分钟

一、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"));
    }
}