IoTDB Java 原生 API 实战:SessionPool 从入门到精通

IoTDB Java 原生 API 实战:SessionPool 从入门到精通
在这里插入图片描述

IoTDB Java原生API实战:SessionPool从入门到精通

在这里插入图片描述

做IoTDB开发的小伙伴都知道,原生API里的Session是和数据库交互的核心,但它有个关键问题——非线程安全,多线程环境下直接用很容易出问题。而SessionPool作为Session的连接池,能完美解决这个问题,在并发场景下合理管理连接资源,大幅提升系统性能和资源利用率,也是官方推荐的编程方式。今天就从基础用法到实战案例,再到全量接口说明,把SessionPool的使用彻底讲透,新手也能直接上手开发。

一、核心概念与开发步骤概览

首先先理清两个核心对象的关系:Session是IoTDB交互的核心接口,集成了写数据、查数据、元数据操作等所有功能,实例化后就能建立和服务端的连接,但切记不能多线程同时调用;SessionPool是Session的连接池,专门为多线程并发设计,能统一管理多个Session实例,避免频繁创建和关闭连接的性能损耗。

用SessionPool开发的核心步骤就三步,特别简单:

  1. 创建连接池实例:初始化SessionPool对象,配置连接信息和池大小;
  2. 执行数据库操作:直接从连接池获取Session执行操作,不用手动管连接的开闭;
  3. 关闭连接池资源:业务操作完成后,关闭SessionPool释放所有资源。

接下来就一步步讲具体的开发流程,文中只演示核心参数和接口,想了解全部功能可以参考IoTDB的全量接口说明或源码。

二、详细开发步骤

2.1 搭建Maven项目,引入依赖

首先创建一个Maven项目,要求JDK≥1.8、Maven≥3.6,然后在pom.xml中添加IoTDB Session的依赖,注意版本号要和数据库服务端的版本完全一致,避免版本兼容问题。

<dependencies><dependency><groupId>org.apache.iotdb</groupId><artifactId>iotdb-session</artifactId><!-- 版本号与数据库版本号相同 --><version>${project.version}</version></dependency></dependencies>

2.2 初始化SessionPool连接池

创建连接池的核心是通过SessionPool.Builder构建对象,配置节点地址、账号密码、连接池最大大小等信息。这里推荐配置多个节点URL,这样当其中一个节点宕机时,客户端会自动连接其他节点重试,提升服务可用性。

核心代码示例:

importjava.util.ArrayList;importjava.util.List;importorg.apache.iotdb.session.pool.SessionPool;publicclassIoTDBSessionPoolExample{privatestaticSessionPool sessionPool;publicstaticvoidmain(String[] args){// 配置数据库节点URL,支持多节点容灾List<String> nodeUrls =newArrayList<>(); nodeUrls.add("127.0.0.1:6667"); nodeUrls.add("127.0.0.1:6668");// 构建SessionPool sessionPool =newSessionPool.Builder().nodeUrls(nodeUrls)// 节点列表.user("root")// 用户名.password("root")// 密码.maxSize(3)// 连接池最大大小.build();}}

2.3 执行各类数据库操作

SessionPool支持IoTDB所有的核心操作,主要分为数据写入SQL操作两大类,下面结合工业场景的实际需求,讲具体的接口用法和代码案例,所有操作都直接通过SessionPool调用,无需手动操作Session。

2.3.1 数据写入

工业场景中数据写入主要分多行数据写入(多设备/单设备多时间戳)和单设备多行数据写入两种,IoTDB提供了对应的专属接口,适配不同的采集场景,下面分别讲用法。

(1)多行数据写入:insertRecords

这个接口支持一次写入多行数据,每一行对应一个设备、一个时间戳的多个测点值,适合不同测点独立采集的场景,批量写入能大幅提升写入效率。

完整代码案例:

importjava.util.ArrayList;importjava.util.List;importorg.apache.iotdb.rpc.IoTDBConnectionException;importorg.apache.iotdb.rpc.StatementExecutionException;importorg.apache.iotdb.session.pool.SessionPool;importorg.apache.tsfile.enums.TSDataType;publicclassSessionPoolExample{privatestaticSessionPool sessionPool;publicstaticvoidmain(String[] args)throwsIoTDBConnectionException,StatementExecutionException{// 1. 初始化连接池constructSessionPool();// 2. 执行批量插入insertRecordsExample();// 3. 关闭连接池closeSessionPool();}// 构建连接池privatestaticvoidconstructSessionPool(){List<String> nodeUrls =newArrayList<>(); nodeUrls.add("127.0.0.1:6667"); nodeUrls.add("127.0.0.1:6668"); sessionPool =newSessionPool.Builder().nodeUrls(nodeUrls).user("root").password("root").maxSize(3).build();}// 批量插入多行数据publicstaticvoidinsertRecordsExample()throwsIoTDBConnectionException,StatementExecutionException{String deviceId ="root.sg1.d1";// 定义测点列表List<String> measurements =newArrayList<>(); measurements.add("s1"); measurements.add("s2"); measurements.add("s3");// 初始化批量写入的参数集合List<String> deviceIds =newArrayList<>();List<List<String>> measurementsList =newArrayList<>();List<List<Object>> valuesList =newArrayList<>();List<Long> timestamps =newArrayList<>();List<List<TSDataType>> typesList =newArrayList<>();// 模拟生成500条数据,每100条批量写入一次for(long time =0; time <500; time++){List<Object> values =newArrayList<>();List<TSDataType> types =newArrayList<>();// 模拟测点值 values.add(1L); values.add(2L); values.add(3L);// 定义测点数据类型 types.add(TSDataType.INT64); types.add(TSDataType.INT64); types.add(TSDataType.INT64);// 添加到批量集合 deviceIds.add(deviceId); measurementsList.add(measurements); valuesList.add(values); typesList.add(types); timestamps.add(time);// 每100条执行一次写入,避免集合过大if(time !=0&& time %100==0){try{ sessionPool.insertRecords(deviceIds, timestamps, measurementsList, typesList, valuesList);}catch(IoTDBConnectionException|StatementExecutionException e){// 异常处理,如重试、日志记录}// 清空集合,准备下一批数据 deviceIds.clear(); measurementsList.clear(); valuesList.clear(); typesList.clear(); timestamps.clear();}}// 写入最后一批不足100条的数据try{ sessionPool.insertRecords(deviceIds, timestamps, measurementsList, typesList, valuesList);}catch(IoTDBConnectionException|StatementExecutionException e){// 异常处理}}// 关闭连接池publicstaticvoidcloseSessionPool(){ sessionPool.close();}}
(2)单设备多行数据写入:insertTablet

这个接口专门用于单个设备的多行数据写入,每一行对应一个时间戳的多个测点值,是IoTDB推荐的高效写入方式,底层做了优化,写入性能比普通批量写入更高。

使用该接口需要先创建Tablet对象(封装设备、测点、数据的核心对象),再调用insertTablet写入,完整代码案例:

importjava.util.ArrayList;importjava.util.List;importjava.util.Random;importorg.apache.iotdb.rpc.IoTDBConnectionException;importorg.apache.iotdb.rpc.StatementExecutionException;importorg.apache.iotdb.session.pool.SessionPool;importorg.apache.tsfile.enums.TSDataType;importorg.apache.tsfile.write.record.Tablet;importorg.apache.tsfile.write.schema.IMeasurementSchema;importorg.apache.tsfile.write.schema.MeasurementSchema;publicclassSessionPoolExample{privatestaticSessionPool sessionPool;publicstaticvoidmain(String[] args)throwsIoTDBConnectionException,StatementExecutionException{// 1. 初始化连接池constructSessionPool();// 2. 执行Tablet写入insertTabletExample();// 3. 关闭连接池closeSessionPool();}// 构建连接池privatestaticvoidconstructSessionPool(){List<String> nodeUrls =newArrayList<>(); nodeUrls.add("127.0.0.1:6667"); sessionPool =newSessionPool.Builder().nodeUrls(nodeUrls).user("root").password("root").maxSize(3).build();}// 单设备Tablet高效写入privatestaticvoidinsertTabletExample()throwsIoTDBConnectionException,StatementExecutionException{// 定义设备的测点模式(测点名称+数据类型)List<IMeasurementSchema> schemaList =newArrayList<>(); schemaList.add(newMeasurementSchema("s1",TSDataType.INT64)); schemaList.add(newMeasurementSchema("s2",TSDataType.INT64)); schemaList.add(newMeasurementSchema("s3",TSDataType.INT64));// 创建Tablet对象:设备ID + 测点模式 + 最大行数量Tablet tablet =newTablet("root.sg.d1",schemaList,100);// 模拟生成数据并写入Tabletlong timestamp =System.currentTimeMillis();Random random =newRandom();for(long row =0; row <100; row++){int rowIndex = tablet.getRowSize();// 添加时间戳 tablet.addTimestamp(rowIndex, timestamp);// 为每个测点添加值for(int s =0; s <3; s++){long value = random.nextLong(); tablet.addValue(schemaList.get(s).getMeasurementName(), rowIndex, value);}// 当Tablet达到最大行数量时,执行写入并重置if(tablet.getRowSize()== tablet.getMaxRowNumber()){ sessionPool.insertTablet(tablet); tablet.reset();} timestamp++;}// 写入最后一批不足最大行数量的数据if(tablet.getRowSize()!=0){ sessionPool.insertTablet(tablet); tablet.reset();}}// 关闭连接池publicstaticvoidcloseSessionPool(){ sessionPool.close();}}
2.3.2 SQL操作

SessionPool支持所有IoTDB的SQL操作,分为查询操作非查询操作两类,对应两个核心接口:

  • executeNonQueryStatement:执行非查询SQL(DDL/DML,如创建时间序列、删除数据、设置TTL),无返回结果;
  • executeQueryStatement:执行查询SQL(如普通查询、聚合查询),返回结果集SessionDataSetWrapper,可通过迭代器遍历结果。

完整代码案例,包含两种操作的用法,还有结果集的遍历方式:

importjava.util.ArrayList;importjava.util.List;importorg.apache.iotdb.isession.pool.SessionDataSetWrapper;importorg.apache.iotdb.rpc.IoTDBConnectionException;importorg.apache.iotdb.rpc.StatementExecutionException;importorg.apache.iotdb.session.pool.SessionPool;importorg.apache.iotdb.isession.SessionDataSet.DataIterator;publicclassSessionPoolExample{privatestaticSessionPool sessionPool;publicstaticvoidmain(String[] args)throwsIoTDBConnectionException,StatementExecutionException{// 1. 初始化连接池constructSessionPool();// 2. 执行非查询SQL(DDL/DML)executeNonQueryExample();// 3. 执行查询SQL,遍历结果集executeQueryExample();// 4. 关闭连接池closeSessionPool();}// 非查询SQL操作:创建时间序列、设置TTL、删除时间序列等privatestaticvoidexecuteNonQueryExample()throwsIoTDBConnectionException,StatementExecutionException{// 创建非对齐时间序列 sessionPool.executeNonQueryStatement("create timeseries root.test.d1.s1 with dataType = int32");// 为指定路径设置TTL(过期时间) sessionPool.executeNonQueryStatement("set TTL to root.test.** 10000");// 删除时间序列 sessionPool.executeNonQueryStatement("delete timeseries root.test.d1.s1");}// 查询SQL操作:普通查询 + 聚合查询,遍历结果集privatestaticvoidexecuteQueryExample()throwsIoTDBConnectionException,StatementExecutionException{// 1. 普通查询:查询前10条数据try(SessionDataSetWrapper wrapper = sessionPool.executeQueryStatement("select s1 from root.sg1.d1 limit 10")){DataIterator dataIterator = wrapper.iterator();// 打印列名和列类型System.out.println(wrapper.getColumnNames());System.out.println(wrapper.getColumnTypes());// 遍历结果集while(dataIterator.next()){StringBuilder builder =newStringBuilder();for(String columnName : wrapper.getColumnNames()){ builder.append(dataIterator.getString(columnName)+" ");}System.out.println(builder);}}// 2. 聚合查询:按5ms窗口分组统计s1的数量try(SessionDataSetWrapper wrapper = sessionPool.executeQueryStatement("select count(s1) from root.sg1.d1 group by ([0, 40), 5ms) ")){DataIterator dataIterator = wrapper.iterator();System.out.println(wrapper.getColumnNames());System.out.println(wrapper.getColumnTypes());while(dataIterator.next()){StringBuilder builder =newStringBuilder();for(String columnName : wrapper.getColumnNames()){ builder.append(dataIterator.getString(columnName)+" ");}System.out.println(builder);}}}// 构建连接池privatestaticvoidconstructSessionPool(){List<String> nodeUrls =newArrayList<>(); nodeUrls.add("127.0.0.1:6667"); nodeUrls.add("127.0.0.1:6668"); sessionPool =newSessionPool.Builder().nodeUrls(nodeUrls).user("root").password("root").maxSize(3).build();}// 关闭连接池publicstaticvoidcloseSessionPool(){ sessionPool.close();}}
结果集高级遍历:多数据类型取值

实际开发中会遇到多种数据类型的测点(int32、int64、float、text、blob等),需要用对应的方法取值,DataIterator提供了专属的取值方法,其中getBlobgetDate从V2.0.4版本开始支持。

核心示例(包含所有常见数据类型的取值和空值判断):

importorg.apache.iotdb.isession.SessionDataSet;importorg.apache.iotdb.isession.pool.SessionDataSetWrapper;importorg.apache.iotdb.rpc.IoTDBConnectionException;importorg.apache.iotdb.rpc.StatementExecutionException;importorg.apache.iotdb.session.pool.SessionPool;importorg.apache.tsfile.enums.TSDataType;importorg.apache.tsfile.utils.Binary;importorg.apache.tsfile.utils.DateUtils;importorg.apache.tsfile.write.record.Tablet;importorg.apache.tsfile.write.schema.MeasurementSchema;importorg.junit.Assert;importjava.sql.Timestamp;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.List;publicclassSessionExample{privatestaticSessionPool sessionPool;publicstaticvoidmain(String[] args)throwsIoTDBConnectionException,StatementExecutionException{// 1. 初始化连接池constructSessionPool();// 2. 执行查询并遍历多类型结果集executeQueryExample();// 3. 关闭连接池closeSessionPool();}privatestaticvoidexecuteQueryExample()throwsIoTDBConnectionException,StatementExecutionException{// 先插入一条多数据类型的测试数据Tablet tablet =newTablet("root.sg.d1",Arrays.asList(newMeasurementSchema("s1",TSDataType.INT32),newMeasurementSchema("s2",TSDataType.INT64),newMeasurementSchema("s3",TSDataType.FLOAT),newMeasurementSchema("s4",TSDataType.DOUBLE),newMeasurementSchema("s5",TSDataType.TEXT),newMeasurementSchema("s6",TSDataType.BOOLEAN),newMeasurementSchema("s7",TSDataType.TIMESTAMP),newMeasurementSchema("s8",TSDataType.BLOB),newMeasurementSchema("s9",TSDataType.STRING),newMeasurementSchema("s10",TSDataType.DATE),newMeasurementSchema("s11",TSDataType.TIMESTAMP)),10); tablet.addTimestamp(0,0L); tablet.addValue("s1",0,1); tablet.addValue("s2",0,1L); tablet.addValue("s3",0,0f); tablet.addValue("s4",0,0d); tablet.addValue("s5",0,"text_value"); tablet.addValue("s6",0,true); tablet.addValue("s7",0,1L); tablet.addValue("s8",0,newBinary(newbyte[]{1})); tablet.addValue("s9",0,"string_value"); tablet.addValue("s10",0,DateUtils.parseIntToLocalDate(20250403)); tablet.initBitMaps(); tablet.bitMaps[10].mark(0);// 标记s11为null tablet.rowSize =1; sessionPool.insertAlignedTablet(tablet);// 查询并遍历多类型结果集try(SessionDataSetWrapper dataSet = sessionPool.executeQueryStatement("select * from root.sg.d1")){SessionDataSet.DataIterator iterator = dataSet.iterator();int count =0;while(iterator.next()){ count++;// 各种数据类型的取值 + 空值判断Assert.assertFalse(iterator.isNull("root.sg.d1.s1"));Assert.assertEquals(1, iterator.getInt("root.sg.d1.s1"));// 整型Assert.assertFalse(iterator.isNull("root.sg.d1.s2"));Assert.assertEquals(1L, iterator.getLong("root.sg.d1.s2"));// 长整型Assert.assertFalse(iterator.isNull("root.sg.d1.s3"));Assert.assertEquals(0, iterator.getFloat("root.sg.d1.s3"),0.01);// 浮点型Assert.assertFalse(iterator.isNull("root.sg.d1.s4"));Assert.assertEquals(0, iterator.getDouble("root.sg.d1.s4"),0.01);// 双精度Assert.assertFalse(iterator.isNull("root.sg.d1.s5"));Assert.assertEquals("text_value", iterator.getString("root.sg.d1.s5"));// 文本Assert.assertFalse(iterator.isNull("root.sg.d1.s6"));Assert.assertTrue(iterator.getBoolean("root.sg.d1.s6"));// 布尔值Assert.assertFalse(iterator.isNull("root.sg.d1.s7"));Assert.assertEquals(newTimestamp(1), iterator.getTimestamp("root.sg.d1.s7"));// 时间戳Assert.assertFalse(iterator.isNull("root.sg.d1.s8"));Assert.assertEquals(newBinary(newbyte[]{1}), iterator.getBlob("root.sg.d1.s8"));// 二进制Assert.assertFalse(iterator.isNull("root.sg.d1.s10"));Assert.assertEquals(DateUtils.parseIntToLocalDate(20250403), iterator.getDate("root.sg.d1.s10"));// 日期Assert.assertTrue(iterator.isNull("root.sg.d1.s11"));// 空值判断Assert.assertNull(iterator.getTimestamp("root.sg.d1.s11"));}Assert.assertEquals(tablet.rowSize, count);}}privatestaticvoidconstructSessionPool(){List<String> nodeUrls =newArrayList<>(); nodeUrls.add("127.0.0.1:6667"); sessionPool =newSessionPool.Builder().nodeUrls(nodeUrls).user("root").password("root").maxSize(3).build();}publicstaticvoidcloseSessionPool(){ sessionPool.close();}}

三、SessionPool全量接口说明

上面讲的是核心用法,实际开发中还会用到元数据管理、数据删除、聚合查询等更多功能,下面整理了SessionPool的核心参数全量接口列表,按功能分类,方便大家开发时查阅。

3.1 核心配置参数

Session/SessionPool的所有参数都可以通过构造函数或Builder方式设置,核心参数如下,涵盖连接、超时、性能、容灾等所有维度:

字段名类型说明
nodeUrlsList数据库节点的 URL 列表,支持多节点连接,实现容灾重试
usernameString连接IoTDB的用户名
passwordString连接IoTDB的密码
fetchSizeint查询结果的默认批量返回大小
useSSLboolean是否启用 SSL 加密连接
queryTimeoutInMslong查询的超时时间,单位:毫秒
connectionTimeoutInMsint连接建立的超时时间,单位:毫秒
maxRetryCountint连接失败后的最大重试次数
retryIntervalInMslong重试的间隔时间,单位:毫秒
enableRPCCompressionboolean是否启用 RPC 传输压缩,提升传输效率

3.2 全量功能接口列表

所有接口都可通过SessionPool直接调用,按功能分类,包含参数解释,开发时按需选用即可。

3.2.1 元数据管理

用于创建/删除数据库、时间序列,管理模式模板等,是IoTDB的基础配置操作:

方法名功能描述参数解释
createDatabase(String database)创建数据库database: 数据库名称
deleteDatabase(String database)删除指定数据库database: 要删除的数据库名称
createTimeseries(…)创建单个时间序列path: 时间序列路径,dataType: 数据类型,encoding: 编码类型,compressor: 压缩类型
createAlignedTimeseries(…)创建对齐时间序列设备ID、测点列表、数据类型列表、编码列表、压缩类型列表
createMultiTimeseries(…)批量创建时间序列多个路径、数据类型、编码、压缩类型、属性、标签等
deleteTimeseries(String path)删除单个时间序列path: 要删除的时间序列路径
createSchemaTemplate(Template template)创建模式模板template: 模板对象
dropSchemaTemplate(String templateName)删除模式模板templateName: 要删除的模板名称
showAllTemplates()显示所有已创建的模板无参数
3.2.2 数据写入

包含所有写入接口,覆盖单条/批量、对齐/非对齐、Tablet高效写入等所有场景,是工业采集的核心接口:

方法名功能描述参数解释
insertRecord(…)插入单条记录deviceId: 设备ID,time: 时间戳,measurements: 测点列表,values: 值列表
insertRecords(…)插入多条记录(多设备)deviceIds: 设备ID列表,times: 时间戳列表,measurementsList: 测点列表集合
insertRecordsOfOneDevice(…)插入单设备的多条记录deviceId: 设备ID,times: 时间戳列表,measurementsList: 测点列表集合
insertAlignedRecord(…)插入单条对齐记录deviceId: 设备ID,time: 时间戳,measurements: 测点列表,values: 值列表
insertTablet(Tablet tablet)插入单个Tablet数据(高效)tablet: 封装好的设备数据对象
insertAlignedTablet(Tablet tablet)插入对齐的Tablet数据(高效)tablet: 封装好的设备对齐数据对象
insertTablets(Map<String, Tablet> tablets)批量插入多个Tablet数据tablets: 设备ID到Tablet的映射表
3.2.3 数据删除

用于删除时间序列或指定时间范围的历史数据,清理过期数据:

方法名功能描述参数解释
deleteTimeseries(List paths)批量删除时间序列paths: 要删除的时间序列路径列表
deleteData(String path, long endTime)删除指定路径的历史数据(截止到endTime)path: 路径,endTime: 结束时间戳
deleteData(List paths, long startTime, long endTime)删除时间范围内的历史数据paths: 路径列表,startTime/endTime: 时间范围
3.2.4 数据查询

包含普通查询、聚合查询、原始数据查询、最新数据查询等所有查询方式,支持超时配置和窗口聚合:

方法名功能描述参数解释
executeQueryStatement(String sql)执行自定义查询SQLsql: 任意合法的IoTDB查询语句
executeRawDataQuery(…)查询指定路径的原始数据paths: 路径列表,startTime/endTime: 时间范围
executeLastDataQuery(List paths)查询指定路径的最新数据paths: 要查询的测点/设备路径列表
executeAggregationQuery(…)执行聚合查询(count/sum/max等)paths: 路径列表,aggregations: 聚合类型列表
executeAggregationQuery(…)执行滑动窗口聚合查询增加interval: 窗口间隔,slidingStep: 滑动步长
3.2.5 系统状态与备份

用于获取系统状态、备份配置、活动连接等信息,辅助运维排查:

方法名功能描述参数解释
getBackupConfiguration()获取数据库的备份配置信息无参数
fetchAllConnections()获取当前客户端的所有活动连接信息无参数
getSystemStatus()获取系统状态(已废弃,默认返回NORMAL)无参数

四、开发注意事项与最佳实践

  1. 版本一致性:客户端依赖版本必须和IoTDB服务端版本完全一致,否则会出现RPC通信、接口不兼容等问题;
  2. 多节点容灾:创建SessionPool时一定要配置多个nodeUrls,实现节点宕机后的自动重试,提升客户端可用性;
  3. 连接池大小maxSize根据业务并发量设置,不宜过大(避免服务端连接数过多),也不宜过小(避免并发等待),建议根据实际压测结果调整;
  4. 批量写入:数据写入优先使用insertRecords(批量)和insertTablet(高效),避免单条循环写入,大幅提升写入性能;
  5. 资源释放:业务操作完成后,必须调用sessionPool.close()关闭连接池,释放所有Session连接和资源;
  6. 异常处理:所有数据库操作都要捕获IoTDBConnectionException(连接异常)和StatementExecutionException(SQL执行异常),并做重试、日志记录等处理;
  7. 结果集关闭:使用executeQueryStatement查询时,建议用try-with-resources语法包裹SessionDataSetWrapper,自动释放结果集资源。

五、总结

IoTDB的Java原生API中,SessionPool是多线程并发场景下的最优选择,相比直接使用Session,它解决了线程安全问题,还能管理连接资源,提升系统性能。本文从基础搭建、连接池初始化,到数据写入、SQL操作的实战案例,再到全量接口说明和开发最佳实践,把SessionPool的核心用法全部覆盖了。

其实核心开发思路很简单:建好连接池,直接调接口,用完关池,只要遵循这个思路,再结合本文的案例和接口列表,就能轻松实现IoTDB的各类开发需求。日常开发中建议优先使用Tablet高效写入和批量操作,配合多节点容灾配置,既能保证性能,又能提升服务的稳定性。

🌐 附:IoTDB的各大版本

📄 Apache IoTDB 是一款工业物联网时序数据库管理系统,采用端边云协同的轻量化架构,支持一体化的物联网时序数据收集、存储、管理与分析 ,具有多协议兼容、超高压缩比、高通量读写、工业级稳定、极简运维等特点。

版本IoTDB 二进制包IoTDB 源代码发布说明
2.0.5- All-in-one
- AINode
- SHA512
- ASC
- 源代码
- SHA512
- ASC
release notes
1.3.5- All-in-one
- AINode
- SHA512
- ASC
- 源代码
- SHA512
- ASC
release notes
0.13.4- All-in-one
- Grafana 连接器
- Grafana 插件
- SHA512
- ASC
- 源代码
- SHA512
- ASC
release notes

✨ 目前最新版本为2.0.6,去获取:https://archive.apache.org/dist/iotdb/

联系博主

    xcLeigh 博主,全栈领域优质创作者,博客专家,目前,活跃在ZEEKLOG、微信公众号、小红书、知乎、掘金、快手、思否、微博、51CTO、B站、腾讯云开发者社区、阿里云开发者社区等平台,全网拥有几十万的粉丝,全网统一IP为 xcLeigh。希望通过我的分享,让大家能在喜悦的情况下收获到有用的知识。主要分享编程、开发工具、算法、技术学习心得等内容。很多读者评价他的文章简洁易懂,尤其对于一些复杂的技术话题,他能通过通俗的语言来解释,帮助初学者更好地理解。博客通常也会涉及一些实践经验,项目分享以及解决实际开发中遇到的问题。如果你是开发领域的初学者,或者在学习一些新的编程语言或框架,关注他的文章对你有很大帮助。

    亲爱的朋友,无论前路如何漫长与崎岖,都请怀揣梦想的火种,因为在生活的广袤星空中,总有一颗属于你的璀璨星辰在熠熠生辉,静候你抵达。

     愿你在这纷繁世间,能时常收获微小而确定的幸福,如春日微风轻拂面庞,所有的疲惫与烦恼都能被温柔以待,内心永远充盈着安宁与慰藉。

    至此,文章已至尾声,而您的故事仍在续写,不知您对文中所叙有何独特见解?期待您在心中与我对话,开启思想的新交流。


     💞 关注博主 🌀 带你实现畅游前后端!

     🏰 大屏可视化 🌀 带你体验酷炫大屏!

     💯 神秘个人简介 🌀 带你体验不一样得介绍!

     🥇 从零到一学习Python 🌀 带你玩转Python技术流!

     🏆 前沿应用深度测评 🌀 前沿AI产品热门应用在线等你来发掘!

     💦 :本文撰写于ZEEKLOG平台,作者:xcLeigh所有权归作者所有)https://xcleigh.blog.ZEEKLOG.net/,如果相关下载没有跳转,请查看这个地址,相关链接没有跳转,皆是抄袭本文,转载请备注本文原地址。


在这里插入图片描述

     📣 亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏,如 🈶 问题请留言(或者关注下方公众号,看见后第一时间回复,还有海量编程资料等你来领!),博主看见后一定及时给您答复 💌💌💌

Read more

Flutter 组件 r_flutter 的适配 鸿蒙Harmony 实战 - 驾驭资源映射自动化、实现鸿蒙端资产强类型引用与资产冲突静态校验方案

Flutter 组件 r_flutter 的适配 鸿蒙Harmony 实战 - 驾驭资源映射自动化、实现鸿蒙端资产强类型引用与资产冲突静态校验方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 r_flutter 的适配 鸿蒙Harmony 实战 - 驾驭资源映射自动化、实现鸿蒙端资产强类型引用与资产冲突静态校验方案 前言 在鸿蒙(OpenHarmony)的大型 UI 工程开发中,“资源管理”是一个极易产生低级错误的重灾区。面对动辄几百个图标(PNG/SVG)、各种自定义字体文件以及多层级的资源目录。如果我们依然使用硬编码字符串(如 Image.asset('assets/images/home_icon_v2_final.png')),那么不仅毫无代码提示可言,由于文件名拼写错误引发的运行期资源丢失(Missing Asset)更是家常便饭。 我们需要一种“代码即资产”的强类型保护。 r_flutter

By Ne0inhk
【Linux指南】进程控制系列(二)进程终止 —— 退出场景、方法与退出码详解

【Linux指南】进程控制系列(二)进程终止 —— 退出场景、方法与退出码详解

文章目录 * 一、先想明白:进程终止不是 “消失”,而是 “释放资源” * 二、进程退出的三大场景:正常与异常的边界 * 场景 1:正常退出(代码执行完毕,结果正确) * 场景 2:正常退出(代码执行完毕,结果不正确) * 场景 3:异常退出(代码崩溃,被迫终止) * 三、三种进程退出方法:return、exit、_exit 的核心差异 * 3.1 方法 1:return—— 仅在 main 函数中有效 * 核心逻辑: * 3.2 方法 2:exit 函数 —— 带清理操作的库函数退出 * 核心逻辑与清理操作: * 函数原型: * 3.

By Ne0inhk
Flutter 组件 mock_client 的适配 鸿蒙Harmony 实战 - 驾驭 HTTP 协议级测试模拟、实现鸿蒙端离线环境下的接口断言与质量门禁方案

Flutter 组件 mock_client 的适配 鸿蒙Harmony 实战 - 驾驭 HTTP 协议级测试模拟、实现鸿蒙端离线环境下的接口断言与质量门禁方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 mock_client 的适配 鸿蒙Harmony 实战 - 驾驭 HTTP 协议级测试模拟、实现鸿蒙端离线环境下的接口断言与质量门禁方案 前言 在鸿蒙(OpenHarmony)生态的大型分布式政务办公系统、极繁金融交易内核以及对交互逻辑边界有极致审计要求的各种工业级应用开发中,“测试的确定性”是架构设计的定海神针。面对包含多级鉴权、动态速率限制(Rate Limiting)且环境依赖极重的后端 API。如果仅仅依靠真实的沙箱网络环境进行逻辑验收。那么不仅会导致测试套件由于网络波动引发由于非预期超时导致的频繁“假失败(Flaky Tests)”,更会因为无法模拟极端错误分位(如:服务器 500 时特定的 Payload 反馈)产生严重的代码覆盖率黑洞。 我们需要一种“契约自洽、逻辑伪造”的协议审计艺术。 mock_client(通常作为

By Ne0inhk