Netty采集数据高效写入TDengine

2024-09-03 14:52

本文主要是介绍Netty采集数据高效写入TDengine,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在现代数据处理应用中,高效的数据采集与存储至关重要。Netty 是一个高性能的异步事件驱动的网络应用程序框架,非常适合用于构建高效的数据采集服务。本文将介绍如何使用 Netty 搭建一个数据采集服务,并通过优化的方式将数据高效地写入 TDengine 数据库。

设计思路

我们的目标是构建一个高效的数据采集服务,该服务能够接收来自多个客户端的数据,并在数据量达到一定阈值或经过一定时间后批量写入 TDengine 数据库。为了实现这一目标,我们需要解决以下几个关键问题:

  1. 数据缓冲:需要一个高效的缓存结构来暂存接收到的数据。

  2. 批量处理:当数据量达到一定阈值或经过一定时间后,应将数据批量写入数据库。

  3. 并发控制:确保在多线程环境下数据处理的安全性。

  4. 配置动态调整:允许配置参数如批量大小和最大等待时间的动态调整。

实现过程

1. 数据缓冲

为了高效地暂存数据,我们使用 ConcurrentLinkedQueue 作为数据缓冲区。这种队列是线程安全的,并且提供了高效的插入和删除操作。

private final ConcurrentLinkedQueue<String> buffer = new ConcurrentLinkedQueue<>();

2. 批量处理

当数据达到一定数量或经过一定时间后,我们将启动一个批量插入操作。为了实现这一点,我们使用了两个主要的组件:

  • 计数器:用于跟踪当前缓存中的数据数量。

  • 定时任务:如果数据没有达到阈值,则设置一个定时任务来处理数据。

private final AtomicInteger counter = new AtomicInteger(0);
private ScheduledFuture<?> scheduledFuture = null;

3. 并发控制

为了确保数据处理的安全性,我们使用 ReentrantLock 来保护批量插入操作。此外,我们还使用 AtomicBoolean 来标识当前是否有线程正在进行批量插入操作。

private final ReentrantLock lock = new ReentrantLock();
private final AtomicBoolean isBatchInserting = new AtomicBoolean(false);

4. 配置动态调整

我们使用 Nacos 配置中心来动态调整批量大小和最大等待时间。这样可以在不重启服务的情况下调整这些参数。

@NacosValue(value = "${batchSize:1000}", autoRefreshed = true)
private volatile int batchSize;  // 阈值
​
@NacosValue(value = "${maxWaitTime:500}", autoRefreshed = true)
private volatile long maxWaitTime;  // 最大延迟时间(毫秒)

5. 核心方法

channelRead 方法

每当从客户端接收到一条数据时,都会调用此方法。在此方法中,我们将数据添加到缓冲区,并更新计数器。如果数据达到阈值,则立即执行批量插入。

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String data = (String) msg;buffer.add(data);int currentCount = counter.incrementAndGet();
​if (currentCount == 1) {scheduleBatchInsert();}
​if (currentCount >= batchSize) {batchInsert();}
}
scheduleBatchInsert 方法

计数器为1的时候,我们会安排一个定时任务来预备处理数据,以保证即便数据条目没有达到设定的阈值,也会被及时批量写入数据库中。

private void scheduleBatchInsert() {scheduledFuture = scheduler.schedule(this::batchInsert, maxWaitTime, TimeUnit.MILLISECONDS);
}
batchInsert 方法

此方法负责实际的批量插入操作。首先,它会检查是否已经有线程正在进行批量插入。如果是,则直接返回。如果不是,则获取锁,并开始处理数据。

private void batchInsert() {if (isBatchInserting.compareAndSet(false, true)) {lock.lock();try {if (counter.get() == 0) {return;}
​List<String> dataToInsert = new ArrayList<>();while (!buffer.isEmpty()) {String data = buffer.poll();if (data != null) {dataToInsert.add(data);}}
​counter.set(0);
​if (scheduledFuture != null && !scheduledFuture.isDone()) {scheduledFuture.cancel(false);}
​if (!dataToInsert.isEmpty()) {try {insertIntoTDengine(dataToInsert);} catch (Exception e) {logger.error("Failed to insert data into TDengine", e);}}} finally {lock.unlock();isBatchInserting.set(false);  // 设置标志位为 false}}
}
insertIntoTDengine 方法

此方法实现了将数据写入 TDengine 的逻辑。具体实现取决于 TDengine 的 API 或者使用的 ORM 框架。

private void insertIntoTDengine(List<String> dataToInsert) {// 实现使用 MyBatisPlus 写入 TDengine 的逻辑,可以参照https://blog.csdn.net/qq_47741012/article/details/141181396
}

6. 生命周期管理

为了确保服务的健壮性,我们需要处理通道关闭和异常捕获事件。此外,还需要提供关闭服务的方法来释放资源。

// 客户端断开连接
@Override
public void channelInactive(ChannelHandlerContext ctx) {cancelScheduledTask();super.channelInactive(ctx);
}
​
Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {logger.error("Exception caught in DataCollectionHandler", cause);ctx.close();
}
​
public void cancelScheduledTask() {if (scheduledFuture != null && !scheduledFuture.isCancelled()) {scheduledFuture.cancel(false);}
}

总结

通过上述设计和实现,我们构建了一个高效的数据采集服务,能够实时接收数据并在数据量达到阈值或经过一定时间后批量写入 TDengine 数据库。这种设计不仅提高了数据处理的效率,还确保了在高并发环境下的数据安全性和一致性。

这篇关于Netty采集数据高效写入TDengine的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1133271

相关文章

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Redis 中的热点键和数据倾斜示例详解

《Redis中的热点键和数据倾斜示例详解》热点键是指在Redis中被频繁访问的特定键,这些键由于其高访问频率,可能导致Redis服务器的性能问题,尤其是在高并发场景下,本文给大家介绍Redis中的热... 目录Redis 中的热点键和数据倾斜热点键(Hot Key)定义特点应对策略示例数据倾斜(Data S

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

SpringBoot整合jasypt实现重要数据加密

《SpringBoot整合jasypt实现重要数据加密》Jasypt是一个专注于简化Java加密操作的开源工具,:本文主要介绍详细介绍了如何使用jasypt实现重要数据加密,感兴趣的小伙伴可... 目录jasypt简介 jasypt的优点SpringBoot使用jasypt创建mapper接口配置文件加密

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

Oracle存储过程里操作BLOB的字节数据的办法

《Oracle存储过程里操作BLOB的字节数据的办法》该篇文章介绍了如何在Oracle存储过程中操作BLOB的字节数据,作者研究了如何获取BLOB的字节长度、如何使用DBMS_LOB包进行BLOB操作... 目录一、缘由二、办法2.1 基本操作2.2 DBMS_LOB包2.3 字节级操作与RAW数据类型2.