InfluxDB:时序型数据库学习笔记,就这一篇吧o(╥﹏╥)o

一、什么是时序型数据库

​时序数据库全称为时间序列数据库。时间序列数据库指主要用于处理带时间标签(按照时间的顺序变化,即时间序列化)的数据,带时间标签的数据也称为时间序列数据。

时间序列数据主要由电力行业、化工行业、气象行业、地理信息等各类型实时监测、检查与分析设备所采集、产生的数据,这些工业数据的典型特点是:产生频率快(每一个监测点一秒钟内可产生多条数据)、严重依赖于采集时间(每一条数据均要求对应唯一的时间)、测点多信息量大(常规的实时监测系统均有成千上万的监测点,监测点每秒钟都产生数据,每天产生几十GB的数据量)。基于时间序列数据的特点,关系型数据库无法满足对时间序列数据的有效存储与处理,因此迫切需要一种专门针对时间序列数据来做优化的数据库系统,即时间序列数据库。

InfluxDB是一个开源的、高性能的时序型数据库,在时序型数据库DB-Engines Ranking上排名第一。

InfluxDB:时序型数据库学习笔记,就这一篇吧o(╥﹏╥)o_第1张图片

二、InfluxDB 相关概念

InfluxDB是一个由InfluxData开发的开源时序型数据。它由Go写成,着力于高性能地查询与存储时序型数据。

名称 说明
organization 组织
Member 用户,可设置权限
API TOKEN 调用API时使用的token
bucket 数据桶(数据库)
measurement 数据表
point 数据点,表示单条数据记录,point由时间戳(time)、数据(field)、标签(tag)三类字段组成
retention policy 数据保留策略,可以定义数据保留的时长,每个数据库可以有多个数据保留策略,但只能有一个默认策略
time 代表每条数据的时间字段,是measurement中的数据主键,因此time字段具有索引属性。一条point只能有一个time
field 代表各种数据的字段,例如气温、压力、股价等。field字段没有索引属性,一条point可以包括多个field
tag 代表各类非数据字段,例如设备编码、地区、姓名等。tag字段有索引属性,一条point可以包括多个tag(tag只能为字符串类型)

InfluxDB与常用的关系型数据库(MySQL)的概念对比:

MySQL InfluxDB
数据库 database bucket
表名 table measurement
记录 rows point
字段 columns time+tag+field

三、Linux环境下安装InfluxDB

 本人使用的是influxDB V2.3.0版本,想下载的朋友点这里:influxDB V2.3.0 镜像包

1、镜像包拷贝到Linux服务器上,加载镜像

docker load -i influx.tar.gz >/dev/null

2、启动容器

docker run -d --name influxdb \
-p 8086:8086 \
--restart=always \
-v /mnt/influxdb/data:/var/lib/influxdb2 \
-v /etc/localtime:/etc/localtime \
influxdb >/dev/null

接下来是重点喽!!!

(1)influxDB 1.x 版本,配置文件在 etc/influxdb/influxdb.conf,而到了 2.x 版本,进入容器中,通过执行 influxd print-config 命令查看 influxdb 的默认配置。当然也可以手动创建一个名为 config.*的文件,config支持json,toml,yaml格式,将config.*文件放到 etc/influxdb2/文件夹下,启动容器时修改环境变量,指定配置文件读取的路径 --env INFLUXD_CONFIG_PATH=/etc/influxdb2,influxdb启动时会自动检测这个文件。同样可以进入容器,执行 influxd print-config 查看你自定义的配置是否生效;

docker run -d --name influxdb \
-p 8086:8086 \
--restart=always \
--env INFLUXD_CONFIG_PATH=/etc/influxdb2 \
-v /opt/mountdir/influxdb/config/:/etc/influxdb2 \
-v /mnt/influxdb/data:/var/lib/influxdb2 \
-v /etc/localtime:/etc/localtime \
influxdb >/dev/null

四、Springboot 整合 InfluxDB

1、pom.xml引入依赖包 

        
        
            com.influxdb
            influxdb-client-java
            3.1.0
        

        
        
            org.jetbrains.kotlin
            kotlin-stdlib
            1.3.70
        

2、yml中添加配置

spring:
  influx:
    ip: 192.3.1.21
    port: 8086
    user: admin
    password: admin
    database: text
    token: oTC_PvFCAnojh8xjX7Rz53B2O9ogneggDWNTZ76VkWS9fgveUODgpOFiFvmoDLoxK7vuSNPstA0SJOWKbvlLsw==

【注】该 token 值来源:安装 InfluxDB 后,浏览器登录 http://ip:8086 ,找到 [API Tokens]

--> [ admin's Token] 中复制出来;

3、启动时注入

@Component
@Slf4j
@Data
public class InfluxDbConfig {

    @Value("${spring.influx.ip:''}")
    private String ip;

    @Value("${spring.influx.port:''}")
    private Integer port;

    @Value("${spring.influx.user:''}")
    private String userName;

    @Value("${spring.influx.password:''}")
    private String password;

    @Value("${spring.influx.database:''}")
    private String database;

    @Value("${spring.influx.token}")
    private String token;

    public static final String MY_BUCKET = "my_bucket";

    public static final String ORG_NAME = "my_org";

    public static final int TIME_OUT = 60;

    public static  String ORGANIZATION_ID= "";


    public static final ConnectionPool CONNECTION_POOL = new ConnectionPool(10, 3L, TimeUnit.MINUTES);

    public static OkHttpClient getHttpClient() {
        return new OkHttpClient().newBuilder()
                .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(TIME_OUT, TimeUnit.SECONDS)
                .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .connectionPool(CONNECTION_POOL)
                .addInterceptor(new NetInterceptor()).build();
    }


    /**
     * 创建连接
     *
     * @return
     */
    @Bean
    public InfluxDBClient influxDBClient() {
        InfluxDBClientOptions influxDBClientOptions = new InfluxDBClientOptions.Builder()
                .url(getInfluxDBUrl(ip, port))
                .authenticateToken(token.toCharArray())
                .bucket(ORG_NAME)
                .okHttpClient(getHttpClient().newBuilder()).build();
        InfluxDBClient influxDBClient = InfluxDBClientFactory.create(influxDBClientOptions);
        if (checkHealth(influxDBClient)) {
            log.info("【influxdb】connect influxdb success!");
        }
        return influxDBClient;
    }


    /**
     * 组合 influxdb 的 URL
     *
     * @param ip
     * @param port
     * @return
     */

    public String getInfluxDBUrl(String ip, Integer port) {
        StringBuilder stringBuilder = new StringBuilder();
        return stringBuilder.append("http://").append(ip).append(":").append(port).toString();
    }


    /**
     * 检查健康
     *
     * @param influxDBClient
     * @return
     */
    public boolean checkHealth(InfluxDBClient influxDBClient) {
        HealthCheck health = influxDBClient.health();
        return "pass".equals(health.getStatus().getValue());
    }



    /**
     * 获取 organizationId
     *
     * @param influxDBClient
     * @param orgName
     * @return
     */
    public static String getOrganizationId(InfluxDBClient influxDBClient, String orgName) {
        List organizations = influxDBClient.getOrganizationsApi().findOrganizations();
        String orgId = "";
        for (Organization organization : organizations) {
            if (organization.getName().equals(orgName)) {
                orgId = organization.getId();
            }
        }
        return orgId;
    }

}

4、代码太多,粘贴些关键的API

(1)创建bucket

public BaseResult createDataBase(InfluxDBClient influxDBClient) {
       // 这里先按名称查询 MY_BUCKET 数据库,如果存在就不创建
        Bucket bucket = influxDBClient.getBucketsApi().findBucketByName(MY_BUCKET);
        if (ObjectUtils.isEmpty(bucket)) {
       // 创建 bucket 并设置数据保留策略为1年
            bucket = influxDBClient.getBucketsApi().createBucket(MY_BUCKET, new BucketRetentionRules().everySeconds(3600 * 24 * 365), ORGANIZATION_ID);
           if (ObjectUtils.isEmpty(bucket)) {
                return BaseResult.fail("influxdb create measurement failed……");
            }
        }
        return BaseResult.success();
    }

(2)写入数据

    /**
     * 数据插入
     *
     * @param bucket      数据库名称
     * @param orgName     组织名称
     * @param measurement 表名
     * @param tag         索引字段
     * @param fields      字段
     * @param time        查询事件
     */

    public void insert(String bucket, String orgName, String measurement, String tag, Map fields, long time) {
        Point point = Point.measurement(measurement);
        point.addTag("tag", tag);
        point.addFields(fields);
        // 纳秒值
        point.time(TimeUnit.MILLISECONDS.toNanos(time), WritePrecision.NS);

        writeApi.writePoint(bucket, ORGANIZATION_ID, point);
    }

(3)数据查询,得到List后,再根据自己的业务,转成需要的实体对象。值得一提的是:influxDB从2.0版本之后,就使用了 Flux 语法来查询数据。

   /**
     * 数据查询
     *
     * @param bucket
     * @param orgName
     * @param measurement
     * @param flux
     * @return
     */
     public static List query(String bucket, String orgName, String measurement, String flux) {
        // 构建FLUX语句
        List fluxTables = new ArrayList<>();
        try {
            String organizationId = getOrganizationId(influxDBClient, orgName);
            fluxTables = influxDBClient.getQueryApi().query(flux, organizationId);
        } catch (Exception e) {
            log.error("【influxdb】 query influxdb data failed:", e);
        }
        return fluxTables;
    }

五、FLUX语法

Flux 是 InfluxData 的功能性数据脚本语言,设计用于查询、分析和处理数据,它是InfluxQL 和其他类似 SQL 的查询语言的替代品。

1、from() :选择数据源 bucket

from(bucket: "hrecord_bucket")

2、range():限定时间范围

// 配合InfluxDB客户端中的时间控件使用 
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)

//查询具体时间段
|> range(start: 2022-09-26T01:14:00.000Z, stop: 2022-09-30T01:14:00.000Z)

// 查询过去一小时
|> range(start: -1h)

3.filter():条件筛选

// 筛选数据表 
|> filter(fn: (r) => r["_measurement"] == "tbl_hrecord")

//筛选车牌号
|> filter(fn: (r) => r["plate_code"] == "京FGS002")

4. sort():排序

// 按照时间降序排列,desc:false 为升序 
|> sort(columns:["_time"], desc: true)

5.limit():限制返回结果条数,可用于分页查询

//查询前十条
|> limit(n: 10, offset: 0) 

6.pivot():将列值转为行

  |> pivot(columnKey: ["_field"], rowKey: ["recordId","_time"], valueColumn: "_value")

7.group():分组

// 按车牌号码和车牌颜色分组
|> group(columns:["plate_code","plate_color"] , mode: "by")

8.更多查看:官方文档:Flux的基本使用


InfluxDB:时序型数据库学习笔记,就这一篇吧o(╥﹏╥)o_第2张图片

你可能感兴趣的:(JAVA进阶,数据库,java,开发语言)