在实习过程中,接到一个需求,要查询某一个时间段中InfluxDB的时序数据,并且要求必须按照时间有序进行排列,更重要的是快。然后将数据以CSV文件导出
传统做法:
influxDB中的数据本身就是按照时间排序的,所以可以查询该时间段的时序数据;为了提高查询效率,influxDB可以开启Gzip压缩机制,可以减少1/3的耗时。但是经过测试,如果要查询某一台设备两年内的时序数据,数据量至少为百万起步,甚至达到千万;测试显示直接查询该时间段数据需要耗时2-3小时。
优化方案(采用线程池+CountDownLanch实现):
这个业务场景下可以基于时间段进行拆分,划分为多个子任务,任务异步执行提高效率,然后用CountDownLanch计数器计数,保证所有数据查询完成后进行数据导出。为保证数据有序,在时间段分割过程中,我给每个时间段标上索引位,保证后面数据是有序的,代码如下:
线程池的配置:
package com.ren.mqtt.config;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @ClassName: ThreadPoolConfig
* @Description: TODO
* @Author: RZY
* @DATE: 2022/8/18 12:31
* @Version: v1.0
*/
@Configuration
public class ThreadPoolConfig {
//核心线程数
@Value("${ThreadPool.corePoolSize}")
private int corePoolSize;
//最大线程数
@Value("${ThreadPool.maxPoolSize}")
private int maxPoolSize;
//工作线程活跃时间
@Value("${ThreadPool.keepAliveTime}")
private int keepAliveTime;
//阻塞队列容量
@Value("${ThreadPool.BlockingQueueCapacity}")
private int BlockingQueueCapacity;
@Bean("influxDBThreadPool")
public ThreadPoolTaskExecutor threadPoolTaskExecutor(ThreadFactory threadFactory) {
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(corePoolSize);
threadPool.setMaxPoolSize(maxPoolSize);
threadPool.setKeepAliveSeconds(k