Influxdb2集成springboot

简介

InfluxDB 2.x 是 InfluxData 公司推出的时间序列数据库的最新版本。与 InfluxDB 1.x 相比,InfluxDB 2.x 引入了一些新的特性和改进,旨在提供更强大、灵活和易于使用的时间序列数据存储和查询解决方案

特点

  1. Flux 查询语言: InfluxDB 2.x 引入了 Flux 查询语言,用于执行强大的数据处理和分析操作。Flux 提供了更灵活的查询能力,支持复杂的数据转换、过滤、聚合和连接操作,以更好地支持用户对时间序列数据的操作和分析。
  2. 新的数据存储引擎: InfluxDB 2.x 使用 Flux Engine 作为新的数据存储引擎。Flux Engine 具有更好的性能和扩展性,支持高并发写入和高效查询。
  3. Bucket 和 Organization: InfluxDB 2.x 引入了 Bucket 和 Organization 的概念。Bucket 是数据的逻辑容器,用于组织和存储时间序列数据,而 Organization 用于隔离和管理不同的用户或应用程序。
  4. 新的用户界面(UI): InfluxDB 2.x 提供了全新的仪表板和可视化工具,使用户能够轻松创建、定制和共享漂亮的图表和仪表板,以直观地展示时间序列数据。
  5. API 密钥和访问令牌: 为了实现更安全的访问和操作,InfluxDB 2.x 引入了 API 密钥和访问令牌。API 密钥用于身份验证,访问令牌用于授权对数据的访问。
  6. 支持多租户: InfluxDB 2.x 提供更好的多租户支持,允许在同一实例中隔离和管理多个不同的组织和数据。
  7. 新的存储结构: InfluxDB 2.x 采用新的存储结构,支持更灵活的标签和更好的查询性能,同时改进了存储效率。
  8. 云原生和容器化: InfluxDB 2.x 被设计用于云原生环境和容器化部署,支持在 Kubernetes 或其他容器编排工具中运行。
  9. 更好的持久性查询支持: Flux 查询语言支持对查询结果进行持久性存储,使用户可以创建并定期执行持久性的计算任务。

基本概念

  1. Bucket(桶): Bucket 是 InfluxDB 中的基本存储单元,用于组织和存储时间序列数据。它是数据的逻辑容器,用于区分和隔离不同类型或来源的数据。
  2. Organization(组织): Organization 是 InfluxDB 中的组织概念,用于隔离和管理用户、应用程序或项目。每个用户可以属于一个或多个组织,Bucket 也属于一个组织。
  3. Measurement(测量值): Measurement 是 InfluxDB 中的数据表的概念。它类似于关系型数据库中的表,用于存储时间序列数据。每个 Measurement 包含一组字段和标签。
  4. Field(字段): Field 是 Measurement 中的一种数据类型,用于存储实际的数值数据。例如,温度、湿度等是字段的例子。
  5. Tag(标签): Tag 是 Measurement 中的一种索引类型,用于标识和过滤数据。标签通常用于存储维度信息,例如地理位置、设备 ID 等。
  6. Point(数据点): Point 是 InfluxDB 中时间序列数据的基本单位,它包含了时间戳、字段和标签。每个数据点都关联到一个 Measurement。
  7. API 密钥和访问令牌: 为了进行安全的访问和操作,InfluxDB 2.x 引入了 API 密钥和访问令牌。API 密钥用于身份验证,而访问令牌用于授权对数据的访问。
  8. Flux 查询语言: Flux 是 InfluxDB 2.x 中的查询语言,用于执行强大的数据处理和分析操作。它支持更灵活的查询、过滤、聚合和转换操作。
  9. 仪表板和可视化: InfluxDB 2.x 提供了仪表板和可视化工具,允许用户创建、定制和共享图表和仪表板,以直观地展示时间序列数据。
    Bucket类似于关系型数据库中的库的概念。Measurement类似于数据库中表。

安装环境

安装

尝试过使用docker安装,不过没找到资源

wget https://dl.influxdata.com/influxdb/releases/influxdb2-2.1.1-linux-amd64.tar.gz

tar xvzf influxdb2-2.1.1-linux-amd64.tar.gz

sudo cp influxdb2-2.1.1-linux-amd64/influxd /usr/local/bin/

nohup influxd &

配置

打开游览器 输入127.0.0.1:8086,点击“Get Started”
进行初始化信息填写(账号、密码、桶、组织),并点击Continue
这个buckets和token在influxdb2的版本后续跟springboot集成有用
在这里插入图片描述

语法

Flux 是一种功能强大的查询语言,特别适用于处理时间序列数据。Flux 具有丰富的操作和函数,使用户能够执行复杂的数据处理、过滤、聚合和计算任务。其中bucket 和 range 是必填的。
buckets
buckets()返回当前组中所有的桶

from
指定从那个bucket查询数据

from(bucket:"bucket名称")

range
指定时间区间,range接收两个参数,start和stop 其中stop可以省略,缺省值是当前时间。start不能省略,否则会报语法错误。
start和stop 既可以使用相对的时间区间,也可以使用绝对的时间戳。相对时间区间格式为 时间间隔h/m/s例如 -1h,-5m。时间戳格式2021-01-01T00:00:00Z

#示例1
from(bucket:"bucket名称")
	|> range(start: -1h)

#示例2
from(bucket:"bucket名称")
	|> range(start: 2021-01-01T00:00:00Z, stop: 2021-01-01T12:00:00Z)

filter
对数据进行过滤,接收一个判断函数。类似于java中的lamda,它看起来像是下面这样
® => (r.recordProperty comparisonOperator comparisonExpression)
判断函数返回一个boolean类型值。只有符合条件的记录才会被返回。

#示例
from(bucket: "wxm-influx")
	|> range(start: -24h)
	|> filter(fn:(r)=>(r.owner=="wxm"))
#取最近24小时,含有owner标签且值为wxm的记录
当filter内含有多个条件时可用 and 或 or 连接各个条件

#示例
from(bucket: "wxm-influx")
	|> range(start: -24h)
	|> filter(fn:(r)=>(r.owner=="wxm" or r.key=="indoor"))
#取最近24小时,含有owner标签且值为wx或含有标签key且值为indoor的记录

其他

 from(bucket: "your_bucket")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "your_measurement")
  |> filter(fn: (r) => r._field == "your_field")
  |> mean()
# 计算平均值


from(bucket: "your_bucket")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "your_measurement")
  |> filter(fn: (r) => r._field == "your_field")
  |> sum()
  # 计算总和

集成springboot

配置

pom

<dependency>
   <groupId>com.influxdb</groupId>
   <artifactId>influxdb-client-java</artifactId>
   <version>6.7.0</version>
</dependency>

yml配置文件

influx:
  url: http://127.0.0.1:8086
  token: 你的token
  bucket: 你需要的桶
  org: 你设置的组织

config文件

@Data
@Configuration
public class InfluxValues {
    @Value("${influx.url}")
    private String url;
    @Value("${influx.token}")
    private String token;
    @Value("${influx.org}")
    private String org;
    @Value("${influx.bucket}")
    private String bucket;
}
@Data
@Configuration
public class InfluxConfig {
    @Autowired
    private InfluxValues influxValues;


    /**
     * 创建 InfluxDBClient 客户端
     * @return
     */
    @Bean
    public InfluxDBClient influxDBClient(){
        return InfluxDBClientFactory.create(influxDBClientOptions());
    }

    private InfluxDBClientOptions influxDBClientOptions() {
        return InfluxDBClientOptions.builder()
                .url(influxValues.getUrl())
                .org(influxValues.getOrg())
                .bucket(influxValues.getBucket())
                .authenticateToken(influxValues.getToken().toCharArray())
                .build();
    }

    @Bean
    public WriteApi writeApi() {
        InfluxDBClient influxDBClient = influxDBClient();
        return influxDBClient.makeWriteApi();
    }
}

@Service
@Slf4j
public class InfluxDBService {

    @Autowired
    private InfluxDBClient influxDBClient;

    @Autowired
    private InfluxValues influxValues;

    @Autowired
    private WriteApi writeApi;

    /**
     * 获取表90天数据
     *
     * @param measurement 表
     * @param bucket      桶
     * @return
     */
    public List<FluxTable> getList(String bucket, String measurement) {
        StringBuffer buffer = new StringBuffer();
        appendBucketFlux(buffer, bucket);
        appendTimeRangeLastFlux(buffer, 2160, "h");
        appendTableFlux(buffer, measurement);
        return influxDBClient.getQueryApi().query(buffer.toString(), influxValues.getOrg());
    }

    /**
     * 获取指定时间段内的数据
     *
     * @param hour 小时
     * @return
     */
    public List<FluxTable> getList(String bucket, int hour) {
        StringBuffer buffer = new StringBuffer();
        appendBucketFlux(buffer, bucket);
        appendTimeRangeLastFlux(buffer, hour, "h");

        return influxDBClient.getQueryApi().query(buffer.toString(), influxValues.getOrg());
    }

    /**
     * 获取指定时间段内表的数据
     *
     * @param hour 小时
     * @return
     */
    public List<FluxTable> getList(String bucket, String measurement, int hour) {
        StringBuffer buffer = new StringBuffer();
        appendBucketFlux(buffer, bucket);
        appendTimeRangeLastFlux(buffer, hour, "h");
        if (measurement != null) {
            appendTableFlux(buffer, measurement);
        }
        return influxDBClient.getQueryApi().query(buffer.toString(), influxValues.getOrg());
    }

    /**
     * 获取表数据(时间筛选)
     *
     * @param measurement 表
     * @return
     */
    public List<FluxTable> getList(String bucket, String measurement, String start, String stop) {
        StringBuffer buffer = new StringBuffer();
        appendBucketFlux(buffer, bucket);
        appendTimeRangeFlux(buffer, start, stop);
        appendTableFlux(buffer, measurement);
        return influxDBClient.getQueryApi().query(buffer.toString(), influxValues.getOrg());
    }

    /**
     * 获取表数据(时间筛选)
     *
     * @param bucket      桶
     * @param measurement 表
     * @param start       开始时间
     * @param stop        结束时间
     * @param limit       限制几个
     * @return
     */
//    public List<FluxTable> getList(String bucket, String measurement, String start, String stop) {
//        StringBuffer buffer = new StringBuffer();
//        appendBucketFlux(buffer, bucket);
//        appendTimeRangeFlux(buffer, start, stop);
//        appendTableFlux(buffer, measurement);
//        return influxDBClient.getQueryApi().query(buffer.toString(), influxValues.getOrg());
//    }

    /**
     * 写入数据
     *
     * @param measurement 表
     * @param map         map键值对
     */
    public void writeData(String measurement, Map<String, Object> map) {
        Point point = Point
                .measurement(measurement)
                .addTag("diff", measurement + DateUtil.formatDate(new Date(), DateUtil.ssFormat))
                .addFields(map)
                .time(Instant.now(), WritePrecision.NS);

        writeApi.writePoint(influxValues.getBucket(), influxValues.getOrg(), point);
    }

    /**
     * 写入数据
     * @param bucket 桶
     * @param measurement 表
     * @param map 参数
     */
    public void writeData(String bucket,String measurement, Map<String, Object> map) {
        Point point = Point
                .measurement(measurement)
                .addTag("diff", measurement + DateUtil.formatDate(new Date(), DateUtil.ssFormat))
                .addFields(map)
                .time(Instant.now(), WritePrecision.NS);

        writeApi.writePoint(bucket, influxValues.getOrg(), point);
    }

    /**
     * 数据源()表达式
     *
     * @param buffer     buffer
     * @param bucketName 名称
     */
    public static void appendBucketFlux(StringBuffer buffer, String bucketName) {
        buffer.append("from(bucket: \"").append(bucketName).append("\") ");
    }

    /**
     * 表名表达式
     *
     * @param buffer    buffer
     * @param tableName 名称
     */
    public static void appendTableFlux(StringBuffer buffer, String tableName) {
        buffer.append("|> filter(fn: (r) => r._measurement == \"").append(tableName).append("\") ");
    }

    /**
     * 表名表达式
     *
     * @param buffer buffer
     * @param tag    名称
     */
    public static void appendTagFlux(StringBuffer buffer, String tag) {
        buffer.append("|> filter(fn: (r) => r.tag == \"").append(tag).append("\") ");
    }

    /**
     * field表达式
     *
     * @param buffer buffer
     * @param field  名称
     */
    public static void appendTagField(StringBuffer buffer, String field) {
        buffer.append("|> filter(fn: (r) => r._field == \"").append(field).append("\") ");
    }


    /**
     * 时间范围表达式  UTC时间
     *
     * @param buffer buffer
     * @param start  开始时间
     * @param stop   结束时间
     */
    public static void appendTimeRangeFlux(StringBuffer buffer, String start, String stop) {
        if (StringUtils.isEmpty(start)) {
            start = "2000-01-01T00:00:00.000Z";
        }
        if (StringUtils.isEmpty(stop)) {
            buffer.append("|> range(start:").append(start).append(") ");
        } else {
            buffer.append("|> range(start:").append(start).append(", stop:").append(stop).append(") ");
        }
    }

    /**
     * 最近多少时间
     *
     * @param buffer 参数
     * @param time   时间
     * @param unit   时间单位
     */
    public static void appendTimeRangeLastFlux(StringBuffer buffer, int time, String unit) {
        buffer.append("|> range(start: -").append(time).append(unit).append(" )");
    }
    
}

测试写入

@ApiOperation(value = "write", notes = "write")
@GetMapping(value = "/write")
public Result<?> write(@ApiParam("用电1/用水2/用气3") @RequestParam(name = "type") Integer type) {
    HashMap<String, Object> map = new HashMap<>();
    if (type == 1) {
        map.put("D2", "7");
        map.put("D1", "8");
        influxDBService.writeData("device1", map);
    }
    if (type == 2) {
        map.put("S1", "47");
        map.put("S2", "35");
        influxDBService.writeData("device2", map);
    }
    if (type == 3) {
        map.put("Q1", "3");
        map.put("Q2", "3");
        influxDBService.writeData("device3", map);
    }
    return Result.OK();
}

测试读取

    @ApiOperation(value = "test", notes = "test")
    @GetMapping(value = "/test")
    public Result<?> test() {
        List<FluxTable> record1 = influxDBService.getList(CollectConstants.BUCKET_ELECTRIC, null, "D1", DateUtil.dateToInFlux(new Date()), null);
        return Result.OK(record1);
    }

在这里插入图片描述

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值