package com.xlkh.kafka;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.pool.SessionPool;
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.write.record.Tablet;
import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors; @Slf4j
@Component("com.xlkh.kafka.DataLoaderKafkaConsumer")
public class DataLoaderKafkaConsumer { @Autowired
private SessionPool sessionPool; /**
* 保存已经创建的时间序列
*/
private final static Set<String> STATIC_PATHS = Sets.newConcurrentHashSet(); /**
* fluent_data,批量消费
*/
@KafkaListener(topics = "fluent_data", groupId = "fluent_data_demo", containerFactory = "batchFactory")
@SneakyThrows
public void listenBatchByFluent(List<ConsumerRecord<String, String>> records) {
log.error("从kafka消费fluent数据" + records.size() + "条,当前偏移量:" + records.get(0).offset()); //创建时间序列,如果序列已经存在,不再重新创建
createTimeseriesIfNotExist(records); log.info("开始把数据放到iotdb-----------------------"); insertIotdbByKafka(records); } private void insertIotdbByKafka(List<ConsumerRecord<String, String>> records) throws ParseException, IoTDBConnectionException, StatementExecutionException { //key为kks的路径,value是时间戳集合
Map<String, List<Long>> timeStampMap = new HashMap<>(); //key为kks路径,value是具体的数据
Map<String, List<Float>> values = new HashMap<>(); //保存kks编码
Set<String> kksSet = new HashSet<>(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (ConsumerRecord<String, String> record : records) {
String valueData = record.value();
JSONArray jsonArray = JSON.parseArray(valueData);
for (int i = 0; i < jsonArray.size(); i++) {
Map map = JSON.parseObject(String.valueOf(jsonArray.get(i)), Map.class);
JSONArray jsonArray1 = JSON.parseArray(String.valueOf(map.get("msg")));
for (int j = 0; j < jsonArray1.size(); j++) {
Map map1 = JSON.parseObject(String.valueOf(jsonArray1.get(j)), Map.class);
if (map1.containsKey("big_v")){
String kks = map1.get("kks").toString();
Date date = dateFormat.parse(map1.get("time").toString());
Float val = Float.parseFloat(String.valueOf(map1.get("big_v")));
if(!kksSet.contains(kks)){
timeStampMap.put(kks, new ArrayList<>());
values.put(kks, new ArrayList<>());
kksSet.add(kks);
}
timeStampMap.get(kks).add(date.getTime());
values.get(kks).add(val);
}
}
}
} //遍历批量插入每个设备的数据
for (String kks : kksSet) {
List<Long> longs = timeStampMap.get(kks); //声明Tablet对象设备属性
List<MeasurementSchema> schemas = new ArrayList<>();
schemas.add(new MeasurementSchema(kks,TSDataType.FLOAT));
Tablet tablet = new Tablet("root.param.demo", schemas, longs.size());
for (int row = 0; row < longs.size(); row++) {
int rowIndex = tablet.rowSize++;
//设备时间戳值
tablet.addTimestamp(rowIndex, longs.get(row));
//设置对应的值
tablet.addValue(schemas.get(0).getMeasurementId(), rowIndex, values.get(kks).get(row));
}
//批量插入数据
sessionPool.insertTablet(tablet);
}
log.info("数据成功插入到iotdb-----------------------"+"插入的数据量大小为:"+records.size()); } /**
* 创建时间序列,如果序列已经存在,不再重新创建
*
* @param records 批量数据
*/
private void createTimeseriesIfNotExist(List<ConsumerRecord<String, String>> records) {
try {
List<String> data = records.stream().map(ConsumerRecord::value).collect(Collectors.toList());
HashSet<String> paths = Sets.newHashSetWithExpectedSize(250);
for (String msg : data) { JSONArray jsonArray = JSON.parseArray(msg); for (int i = 0; i <jsonArray.size() ; i++) {
Map map = JSON.parseObject(String.valueOf(jsonArray.get(i)), Map.class);
JSONArray jsonArray1 = JSON.parseArray(String.valueOf(map.get("msg")));
for (int j = 0; j < jsonArray1.size(); j++){
Map map1 = JSON.parseObject(String.valueOf(jsonArray1.get(j)), Map.class);
String kks = map1.get("kks").toString();
String path = "root.param.demo." + kks;
paths.add(path);
}
}
} List<String> notExistPaths = Lists.newArrayList();
List<TSDataType> tsDataTypes = Lists.newArrayList();
List<TSEncoding> tsEncodings = Lists.newArrayList();
List<CompressionType> compressionTypes = Lists.newArrayList();
// List<Map<String, String>> propsList = Lists.newArrayList();
for (String path : paths) {
if (!STATIC_PATHS.contains(path)) {
if (sessionPool.checkTimeseriesExists(path)) {
STATIC_PATHS.add(path);
} else {
notExistPaths.add(path);
tsDataTypes.add(TSDataType.FLOAT);
tsEncodings.add(TSEncoding.RLE);
compressionTypes.add(CompressionType.SNAPPY);
}
}
}
if (CollectionUtil.isNotEmpty(notExistPaths)) {
//批量创建时间序列
sessionPool.createMultiTimeseries(notExistPaths, tsDataTypes, tsEncodings, compressionTypes, null, null, null, null);
//缓存时间序列
STATIC_PATHS.addAll(notExistPaths);
}
} catch (IoTDBConnectionException | StatementExecutionException e) {
log.error(e.getMessage(), e);
}
} }

 切记:对于iotdb来说,节点的第一层一直到倒数第二层,都属于设备id,只有最后一层才是你的属性

java把数据批量插入iotdb的更多相关文章

  1. Java使用iBatis批量插入数据到Oracle数据库

    Java使用iBatis批量插入数据到Oracle数据库 因为我们的数据跨库(mysql,oracle),单独取数据的话需要遍历好多遍,所以就想着先从mysql数据库中取出来的数据然后在oracle数 ...

  2. 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】

    多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...

  3. 使用事务操作SQLite数据批量插入,提高数据批量写入速度,源码讲解

    SQLite数据库作为一般单机版软件的数据库,是非常优秀的,我目前单机版的软件产品线基本上全部替换Access作为优选的数据库了,在开发过程中,有时候需要批量写入数据的情况,发现传统的插入数据模式非常 ...

  4. C#中几种数据库的大数据批量插入

    C#语言中对SqlServer.Oracle.SQLite和MySql中的数据批量插入是支持的,不过Oracle需要使用Orace.DataAccess驱动. IProvider里有一个用于实现批量插 ...

  5. SQL SERVER 使用BULK Insert将txt文件中的数据批量插入表中(1)

    1/首先建立数据表 CREATE TABLE BasicMsg( RecvTime FLOAT NOT NULL , --接收时间,不存在时间相同的数据 AA INT NOT NULL, --24位地 ...

  6. C#:几种数据库的大数据批量插入

    在之前只知道SqlServer支持数据批量插入,殊不知道Oracle.SQLite和MySql也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解 ...

  7. c#数据批量插入

    由于之前面试中经常被问到有关EF的数据批量插入问题,今天以Sqlserver数据库为例,对.net中处理数据批量处理的方案进行了测试对比. 1.四种测试方案 (1)普通的EF数据批量插入:即调用DbS ...

  8. C#:几种数据库的大数据批量插入(转)

    在之前只知道SqlServer支持数据批量插入,殊不知道Oracle.SQLite和MySql也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解 ...

  9. C#:几种数据库的大数据批量插入 - faib

    在之前只知道SqlServer支持数据批量插入,殊不知道Oracle.SQLite和MySql也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种数据库的批量插入解 ...

  10. PHP如何将多维数组中的数据批量插入数据库?

    PHP将多维数组中的数据批量插入到数据库中,顾名思义,需要用循环来插入. 1.循环insert into 语句,逐渐查询 <?php /* www.qSyz.net */ @mysql_conn ...

随机推荐

  1. python excel 07版本转换为03版本

    需要安装pywin32模块 pip install pywin32 主程序: import win32com.client as win32 import os.path import glob cl ...

  2. nlp入门(二) :商品信息可视化与文本分析实战

    源码请到:自然语言处理练习: 学习自然语言处理时候写的一些代码 (gitee.com) 数据来源:麦卡里价格建议挑战Mercari Price Suggestion Challenge | Kaggl ...

  3. Ubuntu20.04 下编译和运行 FreeSWITCH的问题汇总

    1. Ubuntu20.04 下编译和运行 FreeSWITCH的问题汇总 1.1. 环境 Ubuntu20.04.2 LTS (Linux 5.4.0-152-generic x86_64 GNU/ ...

  4. buu-(ACTF新生赛2020)usualCrypt

    base64的常用套路了 文件直接给base,我大胆盲猜base64: 先进sub-401080函数康康: 先看byte-40e0a0 这个很明显了,然后看上面的函数 进这连个地址发现是base64加 ...

  5. mybatis-plus+nacos配置中心和服务发现保姆级教程

    默认你已经看了我的Mybatis-Plus+Mysql的教程,现在有了一个简单的项目如下(之前的教程:  https://www.cnblogs.com/leafstar/p/17638741.htm ...

  6. 「学习笔记」扩展 KMP(Z 函数)

    对于个长度为 \(n\) 的字符串 \(s\).定义 \(z[i]\) 表示 \(s\) 和 \(s[i,n-1]\)(即以 \(s[i]\) 开头的后缀)的最长公共前缀(LCP)的长度.\(z\) ...

  7. Redis从入门到放弃(11):雪崩、击穿、穿透

    1.前言 Redis作为一款高性能的缓存数据库,为许多应用提供了快速的数据访问和存储能力.然而,在使用Redis时,我们不可避免地会面对一些常见的问题,如缓存雪崩.缓存穿透和缓存击穿.本文将深入探讨这 ...

  8. torch.nn基础学习教程 | PyTorch nn Basic Tutorial

    基于torch.nn搭建神经网络的基础教程大纲: 1. 引言 在我们开始深入探讨torch.nn之前,我们首先需要理解PyTorch及其神经网络库的基础知识.这一部分的内容将帮助你对PyTorch有一 ...

  9. LeetCode952三部曲之一:解题思路和初级解法(137ms,超39%)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 题目描述 难度:困难 编程语言:Java 给定一个由不 ...

  10. 如何使用Java + React计算个人所得税?

    前言 在报表数据处理中,Excel公式拥有强大而多样的功能,广泛应用于各个业务领域.无论是投资收益计算.财务报表编制还是保险收益估算,Excel公式都扮演着不可或缺的角色.传统的做法是直接依赖Exce ...