• Apache HTTP Server 和 Apache tomcat 区别
    Apache HTTP Server(简称Apache)和Apache Tomcat(简称Tomcat)虽然同属Apache软件基金会项目,但二者在设计目标、功能定位和技术架构上有显著差异。以下是两者的核心区别及适用场景的详细对比:一、核心定位与功能差异维度Apache HTTP ServerApache Tomcat本质静态内容服务器 + 反向代理Java Web应用服务器(Servlet/JSP容器)核心协议HTTP/1.1、HTTP/2HTTP/1.1、AJP(Apache JServ Protocol)主要功能托管静态文件(HTML/CSS/JS)、反向代理、负载均衡执行Java Servlet/JSP、处理动态请求、会话管理处理能力高并发静态请求(10K+ QPS)动态请求处理(依赖JVM性能,通常500-2K QPS)二、技术架构对比1. Apache HTTP Server架构特点:多进程/多线程模型:默认使用prefork(多进程)或worker(多线程)MPM(Multi-Processing Module)。模块化设计:通过动态加载模块(如mod_proxy、mod_rewrite)扩展功能。无应用层逻辑:仅处理HTTP协议层面的请求转发,不解析应用代码。典型工作流:静态文件动态请求客户端请求Apache返回HTML/CSS转发至Tomcat/PHP-FPM2. Apache Tomcat架构特点:单线程+NIO模型:基于Java NIO实现非阻塞I/O,支持高并发连接。Servlet容器核心:实现JSR-369(Servlet 4.0)规范,管理Servlet生命周期。内置HTTP服务器:可独立运行,但通常与Apache/Nginx配合使用。典型工作流:客户端请求Tomcat解析Servlet/JSP执行业务逻辑返回动态内容三、关键差异详解1. 静态 vs 动态内容处理Apache:优势场景:托管图片、视频、CSS等静态资源,通过mod_cache缓存提升性能。性能指标:单核可处理10K+静态请求/秒(如Nginx对比测试中Apache静态性能约为其1/3)。Tomcat:优势场景:执行Java EE应用(如Spring Boot、Struts),处理数据库查询、业务逻辑。性能指标:动态请求处理延迟约50-200ms(依赖JVM调优和代码质量)。2. 协议支持Apache:支持HTTP/2(需mod_http2)、WebSocket(mod_proxy_wstunnel)。可通过mod_ssl实现TLS终止。Tomcat:原生支持HTTP/1.1,HTTP/2需Java 9+和配置<Connector>。通过AJP协议与Apache集成(端口8009),减少网络开销。3. 集群与高可用Apache:通过mod_proxy_balancer实现负载均衡,支持权重、健康检查。典型配置:<Proxy balancer://mycluster> BalancerMember http://app1:8080 route=app1 BalancerMember http://app2:8080 route=app2 </Proxy> Tomcat:集群需配置<Cluster>和<Manager>(如DeltaManager)。会话复制开销较大,建议使用Redis等外部存储。四、典型部署方案1. 独立部署Apache适用场景:纯静态网站(如企业官网、文档站)。需高并发静态资源访问(如CDN边缘节点)。Tomcat适用场景:开发测试环境(快速部署Java Web应用)。内部工具系统(如管理后台、API服务)。2. 组合部署(推荐方案)Apache + Tomcat:架构:Apache处理静态请求,通过AJP/HTTP转发动态请求至Tomcat。优势:静态资源性能提升3-5倍(Apache优化静态文件传输)。动态请求隔离,避免Tomcat阻塞。配置示例:# Apache配置 ProxyPass /app ajp://localhost:8009/ ProxyPassReverse /app ajp://localhost:8009/ Nginx + Tomcat:架构:Nginx作为反向代理,Tomcat处理Java逻辑。优势:Nginx静态性能优于Apache(约2倍)。配置更简洁,适合容器化部署。五、选型建议场景推荐方案理由纯静态网站Apache/Nginx无需Java支持,资源占用低Java Web应用(低并发)Tomcat独立部署简化架构,快速开发Java Web应用(高并发)Nginx + TomcatNginx处理静态/代理,Tomcat专注动态请求混合负载(静态+动态)Apache + TomcatApache模块化配置灵活,适合传统企业环境微服务架构Spring Boot内嵌Tomcat + API网关去除中间代理层,降低延迟六、性能优化关键点1. Apache优化MPM选择:高并发静态:event MPM(Linux 2.6+)。兼容旧系统:worker MPM。模块禁用:仅加载必要模块(如mod_status、mod_info用于监控)。缓存配置:<IfModule mod_cache.c> CacheRoot "/var/cache/apache2/mod_cache" CacheEnable disk / </IfModule> 2. Tomcat优化JVM调优:JAVA_OPTS="-Xms2g -Xmx2g -XX:+UseG1GC" 连接器配置:<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" maxThreads="200" acceptCount="100" redirectPort="8443" /> 会话管理:禁用URL重写会话跟踪(<session-config cookie-less="true">)。使用Redis替代内存会话存储。七、发展趋势Apache:向轻量化发展(如httpd 2.5计划支持异步I/O),强化HTTPS/HTTP/2支持。Tomcat:与Jakarta EE 9+兼容,支持Servlet 5.0和响应式编程模型(如Spring WebFlux集成)。替代方案:静态资源:Nginx、Caddy(自动HTTPS)。Java应用:Undertow(轻量级)、Jetty(嵌入式友好)。
  • [技术干货] Apache lucene 项目介绍
    Apache Lucene 是一个由 Apache 软件基金会维护的开源高性能、全功能信息检索库,专为文本搜索和索引设计,广泛应用于搜索引擎、内容管理系统和企业级应用中。以下从核心架构、功能特性、适用场景及优缺点四个方面进行详细介绍:一、核心架构倒排索引(Inverted Index):Lucene 的核心数据结构,记录每个词项(Term)与包含该词项的文档(Document)之间的映射关系,实现快速检索。分析器(Analyzer):负责文本处理,包括分词(Tokenization)、词干提取(Stemming)、停用词过滤(Stop Word Filtering)、大小写转换(Case Folding)等。查询解析器(Query Parser):将用户输入的查询字符串转换为 Lucene 内部的查询对象,如精确匹配(TermQuery)、布尔查询(BooleanQuery)、短语查询(PhraseQuery)等。查询执行器(Query Executor):在倒排索引中执行查询,返回匹配的文档列表。段(Segment):索引的物理存储单元,每个段是一个独立的倒排索引,支持合并策略以优化索引大小和查询性能。二、功能特性高性能索引:支持增量索引与批量索引,写入速度超过 800GB/小时。索引大小约为原始文本大小的 20-30%,内存占用低(仅需 1MB 堆)。丰富查询类型:基础查询:精确匹配(TermQuery)、短语匹配(PhraseQuery)、通配符查询(WildcardQuery)。布尔查询:支持 AND/OR/NOT 逻辑组合(BooleanQuery)。范围查询:词项范围(TermRangeQuery)、数值范围(NumericRangeQuery)。模糊查询:近似匹配(FuzzyQuery),支持编辑距离。高级功能:相似度算法:支持 TF-IDF、BM25 等经典算法,可通过 Similarity 类自定义评分逻辑。高亮显示:通过 Highlighter 类实现查询关键词高亮,支持 HTML 标签、自定义样式。拼写纠正:通过 SpellChecker 类实现基于编辑距离或 N-gram 模型的拼写检查。输入补全:通过 AnalyzingInfixSuggester 或 FuzzySuggester 实现前缀匹配、模糊匹配等补全策略。多语言支持:通过 ICUAnalyzer 或 SmartChineseAnalyzer 实现中文、日文、阿拉伯文等复杂文本处理。支持自定义分词规则、停用词表、同义词扩展。可扩展性:支持水平扩展(通过分布式架构)和垂直扩展(优化硬件资源)。提供 Codec 接口实现自定义索引格式和存储策略。三、适用场景搜索引擎开发:为 Google、Bing 等搜索引擎提供底层索引和查询功能。构建独立的搜索引擎服务或系统。企业内容管理:为 SharePoint、Confluence 等内容管理系统提供索引和搜索功能。实现内部文档、邮件、代码库的全文检索。大数据分析:为 Splunk、ELK Stack 等日志分析工具提供索引和查询支持。存储和处理学术文献、电子书等元数据。电商搜索:为 Amazon、eBay 等电商平台提供关键词搜索、分类过滤、排序等功能。支持商品检索和个性化推荐引擎的用户行为日志索引。日志与监控:存储和分析服务器日志、应用监控数据,支持快速检索和故障排查。四、优缺点分析维度优点缺点性能高并发查询支持,缓存机制(如 FieldCache、FilterCache)优化性能。索引更新存在延迟,需通过 Near Real-Time 搜索优化。扩展性支持水平扩展(结合 Elasticsearch、Solr 等分布式框架)和垂直扩展。单机模式适合开发测试,生产环境需依赖分布式架构。灵活性提供丰富的 API 和扩展点,支持自定义分词、查询解析、评分逻辑等。配置复杂(如 Mapping 设计、分词策略),需深入理解信息检索原理。资源消耗内存占用较低(仅需缓存索引数据),硬件资源要求适中。高并发场景下内存占用可能较高,需优化 JVM 参数(如 -Xms4g、-Xmx4g)。学习曲线API 设计简洁,文档完善,社区活跃。需掌握信息检索原理,配置和调优难度较大。实时性支持 Near Real-Time 搜索,索引更新后立即查询。实时性依赖 NRT 索引和 Change API,实现复杂度较高。
  • [技术干货] Apache IoTDB:大数据时代时序数据库选型的技术突围与实践指-转载
    一、时序数据库的崛起1.1 大数据时代的数据洪流在当今这个数字化飞速发展的大数据时代,数据正以前所未有的速度和规模爆发式增长。从互联网应用到传统工业领域,从智能设备到金融交易,各行各业都在源源不断地产生海量数据。以物联网(IoT)领域为例,据国际数据公司(IDC)预测,到 2025 年,全球物联网设备数量将达到 295 亿,这些设备产生的数据量将达到 79.4ZB ,其中绝大部分都是时序数据。在智能家居场景中,智能传感器实时采集室内温度、湿度、空气质量等数据,每个传感器每天可能产生数千条数据记录。而在智能工厂里,生产线上的各类设备更是不停地生成设备运行状态、生产进度、质量检测等时序数据,一个中等规模的工厂每天产生的数据量就能轻松达到 TB 级别。金融行业同样是数据的高产领域。股票市场每秒钟都在产生海量的交易数据,包括股票价格的波动、成交量的变化、投资者的买卖行为等。据统计,全球主要证券交易所每天的交易数据量高达 PB 级别。以我国的 A 股市场为例,每天的交易数据记录数以亿计,这些数据不仅反映了市场的实时动态,还蕴含着丰富的投资决策信息。再看能源领域,随着智能电网的建设和普及,电网中的各类设备,如变压器、开关、电表等,都在持续产生大量的运行状态数据和电力计量数据。这些数据对于电网的安全稳定运行、电力调度和能源管理至关重要。一个省级电网每天产生的时序数据量可达数十 TB,并且随着电网规模的扩大和智能化程度的提高,数据量还在不断攀升。 1.2 传统数据库的困境面对如此海量的时序数据,传统的关系型数据库逐渐显露出诸多困境。在写入性能方面,传统关系型数据库采用的是行式存储结构,每次写入操作都需要对整行数据进行更新和存储,这在处理高频写入的时序数据时效率极低。例如,在物联网场景中,大量传感器的数据需要实时写入数据库,如果使用传统关系型数据库,很容易出现写入延迟甚至写入失败的情况,无法满足数据实时性的要求。据测试,在高并发写入场景下,传统关系型数据库的写入吞吐量仅为时序数据库的几十分之一。 存储成本也是传统关系型数据库的一大痛点。由于时序数据具有高频采集、数据量大的特点,使用传统关系型数据库存储会占用大量的存储空间。而且,传统关系型数据库对时序数据的压缩效果较差,进一步增加了存储成本。以某智能工厂为例,使用传统关系型数据库存储一年的设备运行数据,所需的存储成本是使用时序数据库的 5 倍以上。查询效率同样不尽人意。当需要对大量时序数据进行复杂查询,如时间窗口查询、聚合查询时,传统关系型数据库需要扫描大量的数据行,查询速度极慢。在金融市场的实时交易分析中,对交易数据的查询要求毫秒级响应,而传统关系型数据库往往需要数秒甚至数十秒才能返回结果,根本无法满足金融交易的实时性需求。1.3 时序数据库应运而生为了应对传统数据库在处理时序数据时的种种困境,时序数据库应运而生。时序数据库是一种专门为处理时间序列数据而设计的数据库,它针对时序数据的特点进行了优化,在写入性能、存储效率和查询速度等方面都具有显著优势。 在写入性能上,时序数据库采用了优化的写入算法和存储结构,如 LSM 树(Log-Structured Merge Tree),能够实现高效的批量写入和快速的写入响应。在物联网场景中,时序数据库可以轻松应对每秒数百万条数据的写入压力,确保数据的实时采集和存储。存储效率方面,时序数据库利用数据的时序相关性,采用了高效的压缩算法,如差分编码、游程编码等,能够将数据压缩到原来的几分之一甚至几十分之一,大大降低了存储成本。同时,时序数据库还支持数据的分级存储,将热数据存储在高速存储介质中,冷数据存储在低成本的存储介质中,进一步优化了存储资源的利用。查询速度上,时序数据库针对时序数据的查询特点,建立了高效的索引结构,如时间索引、标签索引等,能够快速定位和查询所需的数据。在进行时间窗口查询和聚合查询时,时序数据库可以在毫秒级甚至微秒级内返回结果,满足了实时监控和数据分析的需求。 1.4 时序数据库下载与安装使用如果你已经被 IoTDB 的魅力所吸引,迫不及待地想要亲自体验一番,那么接下来就为你详细介绍 IoTDB 的下载与使用方法。(一)下载 IoTDB你可以通过 IoTDB 官方下载链接:发行版本 | IoTDB Website ,获取最新版本的 IoTDB。在下载页面,你会看到针对不同操作系统的下载选项,包括 Windows、Linux 等。根据你的系统类型,选择对应的压缩包进行下载。  (二)安装 IoTDBWindows 系统安装:下载完成后,解压下载的压缩包到你希望安装的目录,比如 C:\IoTDB\apache-iotdb-x.x.x-all-bin 。为了方便后续操作,你可以设置 %IoTDB_HOME% 环境变量,指向解压后的根目录,并将其添加到系统的 PATH 变量中。这样,你就可以在任意命令行位置调用 IoTDB 的相关脚本。进入 IoTDB 的 sbin 子目录,执行 start-standalone.bat 脚本,即可启动 IoTDB 独立模式服务。启动过程中,你可以在控制台看到服务器初始化的相关信息,这表明 IoTDB 正在正常启动。Linux 系统安装:在 Linux 系统中,同样先解压下载的压缩包。使用命令 unzip apache-iotdb-x.x.x-all-bin.zip (如果是 tar.gz 格式,则使用 tar -zxvf apache-iotdb-x.x.x-all-bin.tar.gz )。解压后,进入解压目录,执行启动脚本 bash sbin/start-standalone.sh 来启动 IoTDB 服务。启动完成后,你可以使用命令 netstat -nplt 检查默认端口(6667 和 10710)是否正常开启,以确保 IoTDB 服务已经成功启动。Windows 单机版 IoTDB 安装全流程(2025-05 官方版)一、准备系统:Windows 10/11 64 bit依赖:JDK 8u211+ 或 JDK 11(官网推荐),已配置 JAVA_HOME 并加入 PATH路径:安装目录 不能含空格或中文,例如:D:\iotdb\apache-iotdb-1.3.0-all-bin二、下载官网最新包:IoTDB Website → Download → 选 apache-iotdb-1.3.0-all-bin.zip解压到 D:\iotdb\ 得到 D:\iotdb\apache-iotdb-1.3.0-all-bin三、配置(单机 1C1D 可跳过,默认即可)如要调内存:用文本编辑器打开conf\confignode-env.bat 与 conf\datanode-env.bat把 MEMORY_SIZE 改成想要的堆大小,例如:set MEMORY_SIZE=2G四、启动启动 ConfigNode打开 CMD(以管理员身份),依次执行:cd /d D:\iotdb\apache-iotdb-1.3.0-all-binsbin\start-confignode.bat -dAI写代码bash启动 DataNodesbin\start-datanode.bat -d验证sbin\start-cli.bat -h 127.0.0.1 -p 6667CLI 出现 IoTDB> 提示符后执行:SHOW CLUSTER;看到两个节点状态都是 Running 即安装成功 。五、常见快捷命令停止所有节点sbin\stop-standalone.bat重启sbin\stop-standalone.batsbin\start-confignode.bat -dsbin\start-datanode.bat -dAI写代码六、访问CLI:如上Workbench(可选):解压 iotdb-workbench-*.zip,双击 sbin\start.bat -d,浏览器打开 http://127.0.0.1:9190 即可图形化操作 。至此,Windows 单机版 IoTDB 已就绪,可开始建库、写数据、跑查询。(三)使用 IoTDB连接数据库:IoTDB 启动成功后,你可以通过命令行界面(CLI)连接到数据库。在 sbin 目录下,执行 start-cli.sh -h 127.0.0.1 -p 6667 -u root -pw root (Windows 下为 start-cli.bat -h 127.0.0.1 -p 6667 -u root -pw root ),其中 -h 表示主机地址, -p 表示端口号, -u 表示用户名, -pw 表示密码。默认情况下,主机地址为 127.0.0.1 ,端口号为 6667 ,用户名和密码均为 root 。成功连接后,你将看到 IoTDB 的命令行提示符 IoTDB> ,此时你就可以开始执行各种 IoTDB 命令了。创建数据库:在 IoTDB 中,使用 CREATE DATABASE 语句来创建数据库。例如,要创建一个名为 test_db 的数据库,可以执行 CREATE DATABASE test_db 。创建成功后,你可以使用 SHOW DATABASES 命令查看当前所有的数据库,确认 test_db 已经被创建。插入数据:插入数据是使用 IoTDB 的重要操作之一。IoTDB 支持多种插入数据的方式,这里介绍一种常用的基于 SQL 的插入方式。假设你已经创建了一个数据库 test_db ,并且在该数据库下有一个设备 device1 ,设备上有一个测量点 temperature ,你可以使用以下语句插入数据:INSERT INTO root.test_db.device1(timestamp, temperature) VALUES(1630000000000, 25.5) ,其中 1630000000000 是时间戳(单位为毫秒), 25.5 是温度值。你可以根据实际需求,插入不同时间戳和测量值的数据。查询数据:数据插入后,就可以进行查询操作了。使用 SELECT 语句可以查询 IoTDB 中的数据。例如,要查询 root.test_db.device1 设备在某个时间范围内的温度数据,可以执行 SELECT temperature FROM root.test_db.device1 WHERE timestamp >= 1630000000000 AND timestamp <= 1630000010000 ,这条语句将返回指定时间范围内的温度数据。你还可以使用聚合函数,如 AVG (求平均值)、 SUM (求和)、 MAX (求最大值)、 MIN (求最小值)等,对查询结果进行统计分析。例如, SELECT AVG(temperature) FROM root.test_db.device1 可以查询该设备所有温度数据的平均值。如果你对 IoTDB 的企业版感兴趣,想要了解更多关于企业版的功能、优势以及应用案例等信息,可以访问企业版官网:Apache IoTDB_国产开源时序数据库_时序数据管理服务商-天谋科技Timecho 。在官网上,你将获取到关于 IoTDB 企业版的详细资料,包括产品介绍、技术文档、客户案例等,帮助你更好地评估 IoTDB 企业版是否适合你的企业需求。通过以上步骤,你已经初步掌握了 IoTDB 的下载、安装和基本使用方法。在实际应用中,你可以根据具体的业务场景和需求,进一步探索 IoTDB 的更多功能和特性,让 IoTDB 为你的数据管理和分析工作提供强大的支持。二、深入剖析时序数据库2.1 什么是时序数据时序数据,简单来说,就是按照时间顺序排列的数据点序列。每一个数据点都带有一个时间戳,用于标记数据产生的时间。这些数据点通常反映了某个实体或现象在不同时间点上的状态或变化。 以智能工厂中的设备监控为例,生产线上的传感器会实时采集设备的运行参数,如温度、压力、转速等。这些参数随着时间不断变化,形成了一系列的时序数据。假设一台工业机器人的关节温度传感器,每 5 秒采集一次温度数据,在一天的生产过程中,就会产生 17280 个温度数据点,这些数据按照采集时间的先后顺序排列,就构成了该机器人关节温度的时序数据。通过分析这些时序数据,工程师可以及时发现设备是否存在过热等异常情况,提前进行维护,避免生产故障的发生。在能源领域,电力系统中的电表会实时记录用户的用电量。每一分钟,电表都会将当前的用电量数据上传到电力公司的数据库中。这些用电量数据随着时间的推移不断积累,形成了用户用电量的时序数据。电力公司可以根据这些时序数据,分析用户的用电习惯,进行电力调度和需求响应,提高电力系统的运行效率。金融市场中的股票价格也是典型的时序数据。股票的价格在每个交易日内不断波动,证券交易所会实时记录股票的开盘价、收盘价、最高价、最低价等数据。这些数据按照时间顺序排列,反映了股票价格的走势。投资者可以通过分析股票价格的时序数据,预测股票价格的未来变化,制定投资策略。2.2 时序数据库的独特之处时序数据库与传统数据库相比,在多个方面具有独特之处。在设计理念上,传统数据库注重数据的完整性、一致性和事务处理能力,以满足企业级应用中复杂的业务逻辑和数据关系。而时序数据库则专注于时间序列数据的高效处理,强调高写入性能、高效存储和快速查询,以满足对实时数据的处理需求。数据模型方面,传统关系型数据库采用的是二维表结构,将数据存储在表中,每一行代表一个记录,每一列代表一个属性。这种数据模型适合处理结构化数据,但对于时序数据的处理并不高效。时序数据库则采用了更适合时序数据的模型,通常以时间戳作为主键,将数据按照时间顺序进行存储。例如,InfluxDB 采用的是时间线模型,将数据按照时间序列进行组织,每个时间序列由一个或多个标签进行标识,方便对数据进行分类和查询。存储方式上,传统数据库多采用行式存储,将同一记录的所有数据存储在同一行中。这种存储方式在处理结构化数据时效率较高,但在处理大量时序数据时,由于查询通常需要跨多个记录检索数据,效率较低。时序数据库则多采用列式存储,将相同时间戳的数据存储在同一列中。这样在进行时间范围查询或聚合查询时,可以大大减少数据的扫描范围,提高查询效率。同时,时序数据库还利用数据的时序相关性,采用高效的压缩算法,如差分编码、游程编码等,将数据压缩到原来的几分之一甚至几十分之一,大大降低了存储成本。2.3 关键特性大揭秘高写入性能时序数据库专为高频写入设计,采用了优化的写入算法和存储结构,如 LSM 树(Log-Structured Merge Tree)。LSM 树通过将写入操作先记录在内存中的日志结构中,然后再异步地将日志合并到磁盘上,大大减少了磁盘 I/O 操作,提高了写入性能。在物联网场景中,大量传感器的数据需要实时写入数据库,时序数据库可以轻松应对每秒数百万条数据的写入压力,确保数据的实时采集和存储。例如,在一个拥有 10 万个传感器的智能城市项目中,每个传感器每秒产生 10 条数据,使用时序数据库可以在短时间内完成这些数据的写入,而传统数据库则可能因为写入性能不足而导致数据丢失或延迟。高效压缩由于时序数据具有高频采集、数据量大的特点,存储成本是一个重要的考虑因素。时序数据库利用数据的时序相关性,采用了高效的压缩算法。以差分编码为例,它通过记录相邻数据点之间的差值来减少数据的存储空间。假设一个传感器采集的温度数据序列为 25、25.5、26、26.2,使用差分编码后,存储的数据为 25、0.5、0.5、0.2,大大减少了数据量。游程编码则是对于连续重复的数据,只记录数据和重复的次数。如对于连续出现 10 次的温度值 25,使用游程编码只需要记录 25 和 10,进一步降低了存储成本。通过这些压缩算法,时序数据库能够将数据压缩到原来的几分之一甚至几十分之一,大大降低了存储成本。灵活查询时序数据库针对时序数据的查询特点,建立了高效的索引结构,如时间索引、标签索引等,能够快速定位和查询所需的数据。在进行时间窗口查询时,例如查询某一天内设备的运行数据,时序数据库可以利用时间索引快速定位到该时间范围内的数据,而不需要扫描整个数据库。在进行聚合查询时,如计算某段时间内设备的平均温度,时序数据库可以通过预先计算好的聚合索引,快速得出结果。同时,时序数据库还支持各种复杂的查询操作,如滑动窗口分析、数据插值等,满足了不同用户对于时序数据的分析需求。分布式架构随着数据量的不断增长和应用场景的不断扩展,分布式架构成为了时序数据库的重要特性。分布式架构可以将数据分布存储在多个节点上,实现数据的水平扩展,提高系统的吞吐量和容量。例如,在一个大规模的工业物联网项目中,可能需要存储和处理来自数百万个设备的时序数据,单机的时序数据库无法满足这样的需求。采用分布式架构的时序数据库可以将这些数据分布存储在多个服务器节点上,每个节点负责存储和处理一部分数据,从而实现数据的高效存储和查询。同时,分布式架构还具有高可用性和容错性,当某个节点出现故障时,系统可以自动将请求转发到其他正常节点上,确保数据的可靠性和系统的稳定性。三、选型的关键维度3.1 性能指标是核心性能指标无疑是选择时序数据库时最为关键的考量因素之一,它直接关乎系统在实际应用中的表现和效率。在写入性能方面,时序数据的产生往往具有高频、连续的特点。以智能电网中的电表数据采集为例,每个电表可能每隔 15 分钟就会上传一次用电量数据,一个中等规模的城市电网可能拥有数百万个电表,这就意味着每秒都有大量的数据需要写入数据库。如果时序数据库的写入性能不足,就会导致数据积压、丢失,无法满足实时监控和分析的需求。在这种高并发写入场景下,优秀的时序数据库应具备高效的写入算法和存储结构,能够实现每秒数十万甚至数百万条数据的写入,确保数据的及时存储。查询性能同样至关重要。当企业需要对历史数据进行分析,如查询某段时间内设备的运行状态、统计用户的用电习惯时,快速的查询响应是必不可少的。在金融领域,对股票交易数据的查询要求毫秒级响应,以便投资者能够及时做出决策。一个高效的时序数据库应具备优化的查询引擎和索引机制,能够在短时间内返回复杂查询的结果,满足用户对数据实时分析的需求。例如,在处理海量的物联网设备数据时,能够在秒级甚至毫秒级内完成时间窗口查询和聚合查询,为企业的决策提供有力支持。压缩性能则直接关系到存储成本。由于时序数据具有高频采集、数据量大的特点,如果不进行有效的压缩,将会占用大量的存储空间。以某智能工厂为例,其设备运行数据在未压缩的情况下,每月需要占用数 TB 的存储空间,而使用具有高效压缩性能的时序数据库后,通过差分编码、游程编码等压缩算法,能够将数据压缩到原来的几分之一甚至几十分之一,大大降低了存储成本。同时,良好的压缩性能还能减少数据传输的带宽需求,提高系统的整体性能。3.2 数据模型要适配不同的时序数据库采用了不同的数据模型,选择适配业务场景的数据模型对于系统的性能和易用性至关重要。IoTDB 采用的是树形数据模型,这种模型将设备和测点以树形结构进行组织,非常贴合工业物联网中设备的层级管理体系。在一个大型工厂中,设备通常按照车间、生产线、设备单元等层级进行组织,每个设备又包含多个测点,如温度、压力、转速等。使用 IoTDB 的树形模型,可以直观地对这些设备和测点进行管理和查询。例如,通过简单的路径表达式 “root.factory.area1.line1.device1.temperature”,就可以快速定位到特定设备的温度测点,方便进行数据的存储和查询。这种模型还支持通配符查询,如 “root.factory..device1.”,可以查询所有工厂中设备 1 的所有测点数据,大大提高了查询的灵活性。InfluxDB 则采用了 Tag - Set 模型,数据点由时间戳、测量名称、标签集和字段集组成。标签集用于对数据进行分类和索引,字段集则存储实际的数值数据。这种模型在处理具有丰富标签信息的数据时具有优势,能够方便地进行多维度的查询和分析。在监控系统中,可以通过标签对不同的服务器、服务进行分类,然后根据标签查询特定服务器或服务的性能指标。但是,当标签的基数过高,即标签的取值种类过多时,会导致索引膨胀,影响查询性能。在选择数据模型时,需要根据业务场景的特点进行权衡。如果业务场景中设备的层级关系明显,如工业物联网、智能建筑等领域,IoTDB 的树形模型可能更为合适;如果数据具有丰富的标签信息,且需要进行多维度的分析,如监控系统、金融数据分析等领域,InfluxDB 的 Tag - Set 模型可能更能发挥其优势。3.3 扩展性决定未来随着业务的发展和数据量的不断增长,系统的扩展性成为了时序数据库选型中不可忽视的因素。一个具有良好扩展性的时序数据库能够轻松应对数据量的爆发式增长,保证系统的性能和可用性。在物联网领域,随着设备数量的不断增加,数据量会呈现指数级增长。在一个智能城市项目中,可能会涉及数百万个传感器,每天产生的数据量可达 PB 级别。如果时序数据库不具备良好的扩展性,当数据量超过系统的承载能力时,就会出现性能下降、服务中断等问题。因此,选择具有分布式架构的时序数据库至关重要。IoTDB 的端边云协同架构在扩展性方面具有显著优势。在边缘端,IoTDB 可以部署在资源受限的设备上,实现数据的本地存储和初步处理,减少数据传输的压力。边缘设备产生的数据可以通过异步同步的方式传输到云端的 IoTDB 集群中。云端的 IoTDB 集群采用分布式架构,通过增加节点可以实现水平扩展,轻松应对海量数据的存储和处理需求。这种架构不仅保证了现场控制的实时性,又满足了中心化分析的需求,为企业的数字化转型提供了有力的支持。3.4 生态兼容性不可少生态兼容性是指时序数据库与其他相关技术和工具的集成能力,它对于提高系统的整体效能和降低开发成本具有重要意义。在大数据生态系统中,IoTDB 与 Hadoop、Spark、Flink 等大数据处理框架实现了良好的集成。IoTDB 可以作为 Hadoop 的数据源,将存储在 IoTDB 中的时序数据导入到 Hadoop 中进行大规模的数据处理和分析。通过与 Spark 的集成,可以利用 Spark 强大的计算能力对 IoTDB 中的数据进行实时分析和机器学习模型训练。在能源领域,电力公司可以将电网设备的运行数据存储在 IoTDB 中,然后通过与 Spark 的集成,对这些数据进行实时分析,预测设备故障,优化电力调度。IoTDB 与可视化工具的兼容性也为数据的展示和监控提供了便利。以 Grafana 为例,它是一款广泛使用的开源可视化工具,IoTDB 与 Grafana 实现了无缝集成。用户可以通过 Grafana 轻松地连接到 IoTDB,将存储在 IoTDB 中的时序数据以各种图表的形式展示出来,如折线图、柱状图、饼图等,直观地监控设备的运行状态和数据趋势。在智能工厂中,管理人员可以通过 Grafana 实时监控生产线上设备的运行参数,及时发现异常情况,提高生产效率和质量。3.5 运维复杂度需考量运维复杂度是影响项目成功实施和长期稳定运行的重要因素之一。一个复杂的运维环境不仅会增加运维成本,还会提高系统出现故障的风险,影响业务的正常开展。在传统的数据库系统中,复杂的配置、繁琐的管理操作以及难以排查的故障往往给运维人员带来巨大的挑战。在一些大型企业中,运维人员需要花费大量的时间和精力来维护数据库系统,一旦出现问题,可能需要数小时甚至数天才能恢复,给企业带来严重的损失。IoTDB 在设计上充分考虑了降低运维复杂度的需求。它采用了类 SQL 语法,对于熟悉 SQL 的开发人员和运维人员来说,几乎不需要额外的学习成本,就能够轻松地进行数据的操作和管理。IoTDB 还提供了一体化监控平台,内置了 300 多个监控指标,涵盖了数据库的性能、资源使用情况、数据存储等各个方面。运维人员可以通过监控平台实时了解数据库的运行状态,及时发现潜在的问题。当数据库出现性能下降时,运维人员可以通过监控平台查看 CPU 使用率、内存使用情况、磁盘 I/O 等指标,快速定位问题的根源。IoTDB 还提供了智能调参工具,能够根据系统的运行状态自动优化内存、线程等配置,进一步降低了运维的难度。四、IoTDB 的独特优势4.1 强大的性能表现IoTDB 在性能方面表现卓越,其写入、查询和压缩等关键性能指标展现出显著优势。在写入性能上,IoTDB 单机版可达千万级数据点 / 秒,这一数据令人惊叹。在一个拥有 10 万个传感器的智能城市项目中,每个传感器每秒产生 10 条数据,IoTDB 可以轻松应对这样的高并发写入场景,确保数据的实时采集和存储,而不会出现数据积压或丢失的情况。分布式版本的 IoTDB 支持水平扩展,能够满足超大规模数据采集需求。通过增加节点,可以线性地提升系统的写入吞吐量,轻松应对数据量的爆发式增长。查询性能同样出色。IoTDB 支持按时间范围、设备 ID、指标标签快速检索。在处理海量的物联网设备数据时,能够在秒级甚至毫秒级内完成时间窗口查询和聚合查询。例如,在查询某一天内所有设备的运行数据时,IoTDB 可以利用高效的索引机制,快速定位到所需的数据,大大提高了查询效率,为企业的实时监控和决策提供了有力支持。IoTDB 采用了自研的时序文件格式 TsFile,结合先进的编码技术与时序友好的索引结构,大大提高了数据存储效率。针对不同类型的数据,如整数、浮点数、字符串等,IoTDB 采用了自适应压缩算法,能够将存储空间减少 80% 以上,实现了 10:1 的压缩比 。这意味着在存储相同数量的数据时,IoTDB 所需的存储空间仅为其他数据库的十分之一,大大降低了存储成本。4.2 灵活的数据模型IoTDB 采用了独特的树形时序数据模型,这种模型将设备和测点以树形结构进行组织,非常贴合工业物联网中设备的层级管理体系。在一个大型工厂中,设备通常按照车间、生产线、设备单元等层级进行组织,每个设备又包含多个测点,如温度、压力、转速等。使用 IoTDB 的树形模型,可以直观地对这些设备和测点进行管理和查询。例如,通过简单的路径表达式 “root.factory.area1.line1.device1.temperature”,就可以快速定位到特定设备的温度测点,方便进行数据的存储和查询。这种模型还支持通配符查询,如 “root.factory..device1.”,可以查询所有工厂中设备 1 的所有测点数据,大大提高了查询的灵活性。在智能建筑领域,IoTDB 的树形数据模型同样发挥着重要作用。一座大型商业建筑中,包含多个楼层,每个楼层又有多个房间,每个房间内配备了各种智能设备,如空调、照明、安防传感器等。使用 IoTDB,我们可以将建筑的楼层、房间和设备构建成一个树形结构。通过路径表达式 “root.building.floor1.room1.airConditioner.temperature”,可以轻松获取到特定房间内空调的温度数据。这种直观的模型使得数据管理和查询变得简单高效,提高了建筑智能化管理的效率。4.3 端边云协同架构IoTDB 的端边云协同架构是其一大亮点,这种架构充分考虑了物联网场景中数据处理的多样性和复杂性。在边缘端,IoTDB 可以部署在资源受限的设备上,如树莓派、工业网关等,实现本地数据缓存和预处理。这不仅减少了数据传输的压力,还提高了数据处理的实时性。在工业生产现场,设备产生的数据量巨大,如果全部上传到云端进行处理,不仅会消耗大量的网络带宽,还可能导致数据处理的延迟。通过在边缘端部署 IoTDB,可以对数据进行初步的过滤、聚合和分析,只将关键数据上传到云端,大大降低了数据传输的成本和延迟。云端的 IoTDB 集群采用分布式架构,支持水平扩展,可以轻松应对海量数据的存储和处理需求。IoTDB 可以与 HDFS、对象存储(如 S3)集成,实现海量数据的长期存储。在智能电网中,电力公司需要存储和分析大量的电力数据,包括电网设备的运行状态、用户的用电量等。通过 IoTDB 的端边云协同架构,边缘端的设备可以实时采集电力数据,并进行初步处理,然后将处理后的数据同步到云端的 IoTDB 集群中。云端的 IoTDB 集群可以利用其强大的计算能力和存储能力,对这些数据进行深度分析,为电力调度、设备维护等提供决策支持。在工业断网场景下,IoTDB 的端边云协同架构也能发挥重要作用。当工厂与云端的网络连接中断时,边缘端的 IoTDB 可以继续存储和处理本地设备产生的数据。一旦网络恢复,边缘端的 IoTDB 可以将缓存的数据同步到云端,确保数据的完整性和一致性。4.4 丰富的生态集成IoTDB 与大数据生态系统、可视化工具、工业协议等实现了丰富的集成,展现了强大的生态兼容性。在大数据生态系统方面,IoTDB 与 Hadoop、Spark、Flink 等大数据处理框架实现了无缝集成。IoTDB 可以作为 Hadoop 的数据源,将存储在 IoTDB 中的时序数据导入到 Hadoop 中进行大规模的数据处理和分析。通过与 Spark 的集成,可以利用 Spark 强大的计算能力对 IoTDB 中的数据进行实时分析和机器学习模型训练。在能源领域,电力公司可以将电网设备的运行数据存储在 IoTDB 中,然后通过与 Spark 的集成,对这些数据进行实时分析,预测设备故障,优化电力调度。IoTDB 与可视化工具的集成也为数据的展示和监控提供了便利。以 Grafana 为例,它是一款广泛使用的开源可视化工具,IoTDB 与 Grafana 实现了无缝集成。用户可以通过 Grafana 轻松地连接到 IoTDB,将存储在 IoTDB 中的时序数据以各种图表的形式展示出来,如折线图、柱状图、饼图等,直观地监控设备的运行状态和数据趋势。在智能工厂中,管理人员可以通过 Grafana 实时监控生产线上设备的运行参数,及时发现异常情况,提高生产效率和质量。IoTDB 还支持多种工业协议,如 OPC-UA、MQTT 等,方便与工业设备进行对接。在智能制造场景中,IoTDB 可以通过 OPC-UA 协议与工业自动化设备进行通信,实时采集设备的运行数据,实现对生产过程的实时监控和优化。4.5 开源与社区支持IoTDB 是 Apache 顶级项目,这意味着它具有完全开源的优势,企业可以自由使用和定制,无需担心商业限制。IoTDB 拥有一个活跃的社区,由清华大学团队和全球开发者共同维护。社区的活跃性体现在多个方面,首先是版本迭代速度快,能够及时推出新的功能和优化性能。其次,社区对用户的问题响应迅速,用户在使用 IoTDB 的过程中遇到问题,可以通过社区的邮件列表、论坛等渠道寻求帮助,通常能够得到及时的解答和支持。社区还积极开展各种活动,如技术交流、代码贡献等,鼓励开发者参与到 IoTDB 的开发和改进中来。通过社区的力量,IoTDB 不断完善和发展,为用户提供更好的服务和体验。五、与国外产品的全面对比5.1 架构设计对比IoTDB 采用树状数据模型与分布式时序引擎架构,专为工业设备层级化管理设计。树状数据模型将设备和测点以树形结构进行组织,非常贴合工业物联网中设备的层级管理体系。在一个大型工厂中,设备通常按照车间、生产线、设备单元等层级进行组织,每个设备又包含多个测点,如温度、压力、转速等。使用 IoTDB 的树形模型,可以直观地对这些设备和测点进行管理和查询。通过简单的路径表达式 “root.factory.area1.line1.device1.temperature”,就可以快速定位到特定设备的温度测点,方便进行数据的存储和查询。这种模型还支持通配符查询,如 “root.factory..device1.”,可以查询所有工厂中设备 1 的所有测点数据,大大提高了查询的灵活性。InfluxDB 采用基于标签(Tag)的扁平化结构,数据点由时间戳(Timestamp)、测量(Measurement)、标签集(Tag Set)和字段集(Field Set)组成。这种结构在处理具有丰富标签信息的数据时具有优势,能够方便地进行多维度的查询和分析。在监控系统中,可以通过标签对不同的服务器、服务进行分类,然后根据标签查询特定服务器或服务的性能指标。但是,当标签的基数过高,即标签的取值种类过多时,会导致索引膨胀,影响查询性能。InfluxDB 开源版仅支持单机部署,企业版虽提供集群功能,但元数据管理依赖独立节点,运维复杂度较高。TimescaleDB 基于 PostgreSQL 扩展,采用 Hypertables 实现时间分片。这种架构使得 TimescaleDB 能够兼容 PostgreSQL 的生态,支持 SQL 语法,适合需要关系型数据库功能的场景。但是,由于其是在 PostgreSQL 基础上的扩展,在处理亿级测点时易出现索引膨胀问题,对时序数据的深度优化不足。5.2 核心性能实测在核心性能方面,我们通过实际测试来对比 IoTDB 与其他产品的差异。在相同硬件配置(8C/32G/SSD)下,对 IoTDB、InfluxDB 和 TimescaleDB 进行性能测试,结果如下:写入性能:IoTDB 单机写入性能表现出色,可达 50 万 TPS ,能够满足高并发写入的需求。在物联网场景中,大量传感器的数据需要实时写入数据库,IoTDB 的高写入性能可以确保数据的及时存储,不会出现数据积压或丢失的情况。InfluxDB 2.7 版的写入性能为 10 万 TPS ,在高并发场景下可能会出现写入延迟的问题。TimescaleDB 的写入性能为 15 万 TPS ,相对来说也无法与 IoTDB 的高写入性能相媲美。压缩效率:IoTDB 通过 Gorilla 编码 + 二阶差分算法实现了 18:1 的高压缩比,能够将存储空间减少到原来的十八分之一,大大降低了存储成本。在某储能电站案例中,IoTDB 将 4.8TB 原始数据压缩至 267GB,月度存储成本从 5760 元降至 1015 元 。InfluxDB 的压缩比为 8:1 ,在存储大量数据时,存储成本相对较高。TimescaleDB 的压缩比为 12:1 ,虽然也有一定的压缩效果,但与 IoTDB 相比仍有差距。查询延迟:在 10 万测点、10 年跨度数据查询中,IoTDB P99 延迟小于 500ms,能够快速响应用户的查询请求,满足实时监控和分析的需求。InfluxDB 的查询延迟为 3.2s ,在需要快速获取数据的场景下,可能无法满足用户的需求。TimescaleDB 的查询延迟为 1.1s ,虽然比 InfluxDB 有所改善,但与 IoTDB 相比,查询速度仍较慢。5.3 生态集成差异IoTDB 与大数据生态系统、可视化工具、工业协议等实现了丰富的集成,展现了强大的生态兼容性。在大数据生态系统方面,IoTDB 与 Hadoop、Spark、Flink 等大数据处理框架实现了无缝集成。IoTDB 可以作为 Hadoop 的数据源,将存储在 IoTDB 中的时序数据导入到 Hadoop 中进行大规模的数据处理和分析。通过与 Spark 的集成,可以利用 Spark 强大的计算能力对 IoTDB 中的数据进行实时分析和机器学习模型训练。在能源领域,电力公司可以将电网设备的运行数据存储在 IoTDB 中,然后通过与 Spark 的集成,对这些数据进行实时分析,预测设备故障,优化电力调度。IoTDB 与可视化工具的集成也为数据的展示和监控提供了便利。以 Grafana 为例,它是一款广泛使用的开源可视化工具,IoTDB 与 Grafana 实现了无缝集成。用户可以通过 Grafana 轻松地连接到 IoTDB,将存储在 IoTDB 中的时序数据以各种图表的形式展示出来,如折线图、柱状图、饼图等,直观地监控设备的运行状态和数据趋势。在智能工厂中,管理人员可以通过 Grafana 实时监控生产线上设备的运行参数,及时发现异常情况,提高生产效率和质量。IoTDB 还支持多种工业协议,如 OPC-UA、MQTT 等,方便与工业设备进行对接。在智能制造场景中,IoTDB 可以通过 OPC-UA 协议与工业自动化设备进行通信,实时采集设备的运行数据,实现对生产过程的实时监控和优化。InfluxDB 的生态聚焦监控领域,与 Prometheus、Grafana 无缝集成,在监控场景中具有广泛的应用。但是,InfluxDB 缺乏工业协议(如 OPC UA)原生支持,在工业物联网场景中,需要额外开发插件或进行复杂的配置才能与工业设备进行对接。TimescaleDB 依赖 PostgreSQL 生态,适合混合分析场景,但在处理时序数据时,需要额外开发时序数据预处理模块,以满足时序数据处理的特殊需求。5.4 代码案例分享(1)javapackage org.apache.iotdb; import org.apache.iotdb.isession.SessionDataSet;import org.apache.iotdb.rpc.IoTDBConnectionException;import org.apache.iotdb.rpc.StatementExecutionException;import org.apache.iotdb.session.Session;import org.apache.iotdb.tsfile.write.record.Tablet;import org.apache.iotdb.tsfile.write.schema.MeasurementSchema; import java.util.ArrayList;import java.util.List; public class SessionExample {   private static Session session;   public static void main(String[] args)          throws IoTDBConnectionException, StatementExecutionException {    session =            new Session.Builder()                    .host("172.0.0.1")                    .port(6667)                    .username("root")                    .password("root")                    .build();    session.open(false);    List<MeasurementSchema> schemaList = new ArrayList<>();    schemaList.add(new MeasurementSchema("s1", TSDataType.FLOAT));    schemaList.add(new MeasurementSchema("s2", TSDataType.FLOAT));    schemaList.add(new MeasurementSchema("s3", TSDataType.FLOAT));    Tablet tablet = new Tablet("root.db.d1", schemaList, 10);     tablet.addTimestamp(0, 1);    tablet.addValue("s1", 0, 1.23f);    tablet.addValue("s2", 0, 1.23f);    tablet.addValue("s3", 0, 1.23f);    tablet.rowSize++;    session.insertTablet(tablet);    tablet.reset();    try (SessionDataSet dataSet = session.executeQueryStatement("select ** from root.db")) {      while (dataSet.hasNext()) {        System.out.println(dataSet.next());      }    }    session.close();  }}AI写代码java运行(2)pythonfrom iotdb.Session import Sessionfrom iotdb.utils.IoTDBConstants import TSDataTypefrom iotdb.utils.Tablet import Tablet ip = "127.0.0.1"port = "6667"username = "root"password = "root"session = Session(ip, port, username, password)session.open(False) measurements = ["s_01", "s_02", "s_03", "s_04", "s_05", "s_06"]data_types = [    TSDataType.BOOLEAN,    TSDataType.INT32,    TSDataType.INT64,    TSDataType.FLOAT,    TSDataType.DOUBLE,    TSDataType.TEXT,]values = [    [False, 10, 11, 1.1, 10011.1, "test01"],    [True, 100, 11111, 1.25, 101.0, "test02"],    [False, 100, 1, 188.1, 688.25, "test03"],    [True, 0, 0, 0, 6.25, "test04"],]timestamps = [1, 2, 3, 4]tablet = Tablet(    "root.db.d_03", measurements, data_types, values, timestamps)session.insert_tablet(tablet) with session.execute_statement(    "select ** from root.db") as session_data_set:    while session_data_set.has_next():        print(session_data_set.next()) session.close()AI写代码python运行(3)C++#include "Session.h"#include <iostream>#include <string>#include <vector>#include <sstream> int main(int argc, char **argv) {  Session *session = new Session("127.0.0.1", 6667, "root", "root");  session->open();   std::vector<std::pair<std::string, TSDataType::TSDataType>> schemas;  schemas.push_back({"s0", TSDataType::INT64});  schemas.push_back({"s1", TSDataType::INT64});  schemas.push_back({"s2", TSDataType::INT64});   int64_t val = 0;  Tablet tablet("root.db.d1", schemas, /*maxRowNum=*/ 10);  tablet.rowSize++;  tablet.timestamps[0] = 0;  val=100; tablet.addValue(/*schemaId=*/ 0, /*rowIndex=*/ 0, /*valAddr=*/ &val);  val=200; tablet.addValue(/*schemaId=*/ 1, /*rowIndex=*/ 0, /*valAddr=*/ &val);  val=300; tablet.addValue(/*schemaId=*/ 2, /*rowIndex=*/ 0, /*valAddr=*/ &val);   session->insertTablet(tablet);  tablet.reset();   std::unique_ptr<SessionDataSet> res = session->executeQueryStatement("select ** from root.db");  while (res->hasNext()) {    std::cout << res->next()->toString() << std::endl;  }   res.reset();  session->close();  delete session;  return 0;}AI写代码cpp运行(4) Gopackage main import (        "fmt"        "log"         "github.com/apache/iotdb-client-go/client") func main() {         config := &client.Config{                Host:     "127.0.0.1",                Port:     "6667",                UserName: "root",                Password: "root",        }        session := client.NewSession(config)        if err := session.Open(false, 0); err != nil {                log.Fatal(err)        }        defer session.Close() // close session at end of main()                rowCount := 3        tablet, err := client.NewTablet("root.db.d1", []*client.MeasurementSchema{                {                        Measurement: "restart_count",                        DataType:    client.INT32,                        Encoding:    client.RLE,                        Compressor:  client.SNAPPY,                }, {                        Measurement: "price",                        DataType:    client.DOUBLE,                        Encoding:    client.GORILLA,                        Compressor:  client.SNAPPY,                }, {                        Measurement: "description",                        DataType:    client.TEXT,                        Encoding:    client.PLAIN,                        Compressor:  client.SNAPPY,                },        }, rowCount)         if err != nil {                fmt.Errorf("Tablet create error:", err)                return        }         timestampList := []int64{0, 1, 2}        valuesInt32List := []int32{5, -99999, 123456}        valuesDoubleList := []float64{-0.001, 10e5, 54321.0}        valuesTextList := []string{"test1", "test2", "test3"}        for row := 0; row < rowCount; row++ {                tablet.SetTimestamp(timestampList[row], row)                tablet.SetValueAt(valuesInt32List[row], 0, row)                tablet.SetValueAt(valuesDoubleList[row], 1, row)                tablet.SetValueAt(valuesTextList[row], 2, row)        }        session.InsertTablet(tablet, false)         var timeoutInMs int64        timeoutInMs = 1000        sql := "select ** from root.db"        dataset, err := session.ExecuteQueryStatement(sql, &timeoutInMs)        defer dataset.Close()         if err == nil {                for next, err := dataset.Next(); err == nil && next; next, err = dataset.Next() {                        record, _ := dataset.GetRowRecord()                        fields := record.GetFields()                        for _, field := range fields {                                fmt.Print(field.GetValue(), "\t")                        }                        fmt.Println()                }        } else {                log.Println(err)        }}AI写代码Go运行六、行业应用案例6.1 能源电力行业在能源电力行业,IoTDB 展现出了强大的实力,为省级电网的高效运行提供了有力支持。以某省级电网为例,该电网采用 IoTDB 后,取得了显著的成效。在数据规模方面,成功接入了 200 万 + 采集点,日新增数据量高达 50TB 。如此庞大的数据规模,对数据库的存储和处理能力提出了极高的挑战。IoTDB 凭借其高效的存储结构和强大的处理能力,轻松应对了这一挑战,确保了数据的稳定存储和高效处理。查询性能上,IoTDB 的表现同样出色。以往,该省级电网在进行故障追溯时,需要花费数小时才能完成数据的查询和分析,这对于及时发现和解决电网故障来说,时间成本过高。而采用 IoTDB 后,故障追溯时间从小时级降至秒级 。这意味着当电网出现故障时,运维人员可以在极短的时间内获取相关数据,快速定位故障点,采取有效的解决措施,大大提高了电网的可靠性和稳定性。IoTDB 还具备网闸穿透、断点续传等工业特性,有效解决了能源电力行业中数据传输和安全隔离的难题。在电力系统中,为了确保生产网和办公网的安全,通常会架设网闸进行隔离。IoTDB 通过协议优化、网闸适配等方式,实现了跨网数据传输,确保了数据的安全和高效流转。在数据传输过程中,当出现网络中断等异常情况时,IoTDB 的断点续传功能能够保证数据的完整性,避免数据丢失。6.2 智能制造行业在智能制造行业,IoTDB 也发挥着重要作用,为汽车工厂的智能化生产提供了关键支持。以某汽车工厂为例,该工厂拥有 5000 + 设备,这些设备的采样频率高达 100ms ,每天产生的数据量巨大。 在采用 IoTDB 之前,该汽车工厂面临着存储成本高昂、数据处理效率低下等问题。而引入 IoTDB 后,这些问题得到了有效解决。IoTDB 通过其高效的压缩算法,实现了存储成本降低 82% ,为企业节省了大量的资金。在数据处理方面,IoTDB 支持边缘预处理,能够在设备端对数据进行初步处理和分析,减少了 90% 的网络传输 。这不仅降低了网络带宽的压力,还提高了数据处理的实时性,使得工厂能够及时获取设备的运行状态,做出相应的生产决策。IoTDB 的树形数据模型与汽车工厂的设备层级管理体系完美契合。在汽车生产线上,设备通常按照生产线、工位、设备等层级进行组织,每个设备又包含多个测点,如温度、压力、转速等。使用 IoTDB 的树形模型,可以直观地对这些设备和测点进行管理和查询。通过简单的路径表达式 “root.factory.productionLine1.workstation1.device1.temperature”,就可以快速定位到特定设备的温度测点,方便进行数据的存储和查询。这种模型还支持通配符查询,如 “root.factory..workstation1.device1.”,可以查询所有生产线中工位 1 上设备 1 的所有测点数据,大大提高了查询的灵活性。6.3 其他行业应用车联网在车联网领域,长安汽车选择 IoTDB 作为车联网平台的核心数据存储引擎,实现了千万级车辆的稳定接入和千万点每秒的数据并发处理 。IoTDB 的高并发处理能力和强大的存储功能,确保了车辆实时数据的高效采集和存储,为车辆的远程控制、故障预警等功能提供了有力支持。通过 IoTDB,长安汽车能够实时获取车辆的位置、行驶状态、故障信息等数据,及时为用户提供服务,提升了用户的用车体验。智慧城市北斗智慧物联在智慧城市建设中,利用 IoTDB 构建了智慧环卫、智慧园林、智慧市政等多个应用平台 。IoTDB 用于存储和处理环卫车辆的位置、状态、作业数据等时序数据,以及园林传感器的数据、市政设施的运行数据等。通过 IoTDB 的高效写入和快速查询功能,实现了对城市设施的实时监控和智能化管理,提高了城市管理的效率和质量。在智慧环卫平台中,IoTDB 能够实时跟踪环卫车辆的行驶路线和垃圾清运情况,优化垃圾转运和处理流程,提升环卫工作的效率和效果。边缘计算EdgeX Foundry 与 IoTDB 集成,实现了边缘侧持久化存储 。IoTDB 的边缘版本具有体量更轻、性能高、易使用的特点,适用于工业物联网应用中海量时间序列数据高速写入和复杂分析查询的需求。通过与 EdgeX Foundry 的集成,IoTDB 能够将采集到的数据自动转储到边缘版实例中,实现了数据的本地存储和初步处理,减少了数据传输的压力,提高了数据处理的实时性。在工业生产现场,IoTDB 的边缘版本可以实时采集设备数据,并进行初步的分析和处理,为现场控制提供了有力支持。七、选型实践建议7.1 需求分析是基础在进行时序数据库选型之前,深入的需求分析是至关重要的基础步骤。首先,需要准确评估数据规模,这包括设备数、测点数以及数据采集频率。在一个大型的智能工厂中,可能拥有数千台设备,每台设备又包含数十个甚至数百个测点,且数据采集频率可能达到毫秒级。通过计算设备数 × 测点数 × 频率,能够预估出数据的产生量和增长趋势,以便选择能够承载相应数据规模的时序数据库。明确查询模式也是关键。查询模式主要包括实时监控和历史分析。在实时监控场景中,需要数据库能够快速返回最新的数据,以满足对设备运行状态的即时了解。例如,在电力系统中,监控人员需要实时获取电网设备的电压、电流等参数,以便及时发现异常情况。而历史分析则侧重于对过去一段时间内的数据进行统计和分析,以发现数据的趋势和规律。在工业生产中,通过对历史生产数据的分析,可以优化生产流程,提高生产效率。确定 SLA(服务级别协议)要求同样不可或缺。SLA 要求包括可用性、延迟指标等。对于一些关键业务系统,如金融交易系统、航空交通管制系统等,对数据库的可用性要求极高,需要保证系统能够 7×24 小时不间断运行,且延迟指标要控制在毫秒级甚至微秒级。在选择时序数据库时,需要确保其能够满足这些严格的 SLA 要求,以保障业务的正常运行。7.2 概念验证要点在确定候选的时序数据库后,进行概念验证(POC)是确保其满足实际需求的重要环节。首先,要测试真实数据集的压缩率。由于时序数据量通常较大,高效的压缩能够显著降低存储成本。通过使用真实的业务数据集进行测试,可以准确了解数据库在实际数据特征下的压缩效果。以某风电企业为例,在测试不同时序数据库时,发现 IoTDB 通过自适应编码算法和列式存储结构,实现了极高的压缩比,存储空间仅为原方案的 1/20,年节省存储成本超 300 万元。模拟峰值写入压力也是 POC 的要点之一。在实际应用中,可能会出现数据突发增长的情况,如在智能城市项目中,当遇到重大活动或突发事件时,传感器的数据采集量可能会瞬间大幅增加。通过模拟峰值写入压力,能够测试数据库在高并发写入场景下的性能表现,确保其能够稳定运行,不会出现写入延迟或数据丢失的情况。验证关键查询性能同样重要。根据业务需求,确定关键的查询场景,如时间窗口查询、聚合查询等,并对这些查询进行性能测试。在一个监控系统中,经常需要查询某段时间内设备的平均性能指标,通过对不同时序数据库的查询性能测试,可以选择出能够快速响应这类查询的数据库,提高系统的实时性和分析效率。7.3 部署策略规划在部署时序数据库时,合理的部署策略规划能够确保系统的稳定运行和高效扩展。首先,可以进行小规模试点,在一个较小的业务范围内部署时序数据库,如在一个车间或一个部门内部,对数据库的性能、功能和兼容性进行初步验证。通过小规模试点,可以及时发现问题并进行调整,降低大规模部署的风险。随着业务的发展和对数据库性能的信心增强,可以逐步扩展部署范围。在扩展过程中,要建立多级存储机制,将热数据存储在高速的 SSD 中,以满足高频访问的需求;将温数据存储在 SATA 硬盘中,平衡存储成本和访问速度;将冷数据存储在对象存储中,如 AWS S3、MinIO 等,以实现低成本的长期存储。在能源电力行业,电网设备的近期运行数据属于热数据,需要快速查询和分析,可存储在 SSD 中;而过去几年的历史数据访问频率较低,可存储在对象存储中。规划备份恢复策略也是部署策略的重要组成部分。可以采用跨机房备份的方式,将数据备份到不同地理位置的机房,以防止因自然灾害、火灾等不可抗力因素导致的数据丢失。设置 TTL(Time-To-Live)自动转存机制,根据数据的重要性和使用频率,自动将过期的数据转存到低成本的存储介质中,同时删除原始数据,以节省存储空间和管理成本。7.4 长期演进考虑在选择时序数据库时,不仅要考虑当前的业务需求,还要关注长期演进的可能性。随着业务的发展,时序数据分析需求可能会不断变化和深化。在工业物联网领域,最初可能只需要对设备的运行状态进行简单的监控和报警,而随着数字化转型的推进,可能需要进行更深入的数据分析,如设备故障预测、生产效率优化等。因此,选择的时序数据库应具备良好的扩展性和灵活性,能够支持未来可能出现的复杂数据分析需求。预留 AI 集成能力也十分重要。人工智能技术在数据分析和预测方面具有强大的能力,未来许多业务场景都可能会引入 AI 技术。在智能电网中,通过将 AI 技术与时序数据库相结合,可以实现对电力负荷的精准预测,优化电力调度。因此,选择的时序数据库应能够方便地与 AI 框架进行集成,如 TensorFlow、PyTorch 等,为未来的 AI 应用提供支持。考虑多云部署可能性也是长期演进的重要因素。随着云计算技术的发展,多云部署逐渐成为一种趋势。多云部署可以提高系统的可用性和灵活性,降低对单一云服务提供商的依赖。在选择时序数据库时,应考虑其是否支持多云部署,以及在多云环境下的性能和兼容性。一些时序数据库提供了云原生的解决方案,能够轻松地在不同的云平台上进行部署和管理,满足企业对多云部署的需求。八、总结与展望8.1 IoTDB 的价值总结在时序数据库的选型中,IoTDB 展现出了多方面的独特价值。其强大的性能表现,无论是高并发写入、高效压缩还是快速查询,都能满足各类复杂业务场景的需求。灵活的数据模型与工业物联网中设备的层级管理体系完美契合,使得数据的组织和查询更加直观高效。端边云协同架构充分考虑了物联网场景中数据处理的多样性和复杂性,实现了数据的高效流转和处理。丰富的生态集成能力让 IoTDB 能够与多种大数据处理框架、可视化工具以及工业协议无缝对接,拓展了其应用边界。作为 Apache 顶级项目,IoTDB 的开源性质和活跃的社区支持,为用户提供了自由定制和持续优化的空间。8.2 未来发展趋势展望展望未来,时序数据库将朝着更加智能化、高效化和专业化的方向发展。随着物联网、工业互联网等技术的不断普及,数据量将持续爆发式增长,对时序数据库的性能和扩展性提出了更高的要求。人工智能与时序数据库的融合也将成为重要趋势,通过 AI 技术实现数据的智能分析、预测和决策,将为各行业带来更大的价值。在这样的发展趋势下,IoTDB 凭借其强大的技术实力和不断创新的精神,有望在未来的时序数据库市场中占据重要地位。IoTDB 将继续优化其性能,提升数据处理能力,拓展生态集成,加强与 AI 技术的融合,为用户提供更加全面、高效的时序数据管理解决方案。8.3 行动呼吁如果你的业务涉及海量时序数据的处理,无论是工业物联网、智能电网、车联网还是智慧城市等领域,IoTDB 都值得你尝试。你可以通过下载链接:发行版本 | IoTDB Website 获取 IoTDB,体验其强大的功能。如果你有企业级的需求,也可以访问企业版官网链接:Apache IoTDB_国产开源时序数据库_时序数据管理服务商-天谋科技Timecho ,了解更多企业版的优势和服务。相信 IoTDB 会成为你时序数据管理的得力助手,助力你的业务发展。————————————————                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                        原文链接:https://blog.csdn.net/beautifulmemory/article/details/150499714
  • [技术干货] Apache IoTDB(3):时序数据库 IoTDB Docker部署从单机到集群的全场景部署与实践指南-转载
    引言如今,高效存储和管理海量时序数据成为企业数字化转型的关键。Apache IoTDB作为一款专为物联网场景设计的时序数据库,凭借其高性能、轻量级和生态集成能力,在工业监测、智慧城市、智能农业等领域得到广泛应用。本文将深入解析IoTDB的核心特性,并详细说明单机版与集群版在Docker环境下的部署实践。虚拟机测试节点【单机版安装】和【集群版安装】学习之前文章单机版安装:Apache IoTDB(1):时序数据库介绍与单机版安装部署指南集群版安装:Apache IoTDB(2):时序数据库 IoTDB 集群安装部署的技术优势与适用场景分析一、Apache IoTDB产品解析1.1 架构设计IoTDB采用"存储-计算"分离的架构,通过LSM-tree存储引擎与列式存储格式,实现高并发写入与低延迟查询的平衡。其核心组件包括:ConfigNode:集群元数据管理中心,负责节点协调与路由DataNode:数据存储与计算节点,支持水平扩展CLI工具:命令行交互界面,支持SQL与InfluxDB协议想要详细了解IoTDB数据库:3ConfigNode+3DataNode请查看上篇文章:[Apache IoTDB(2):时序数据库 IoTDB 集群安装部署的技术优势与适用场景分析]1.2 核心功能1.2.1 时序数据专属优化对齐时间序列:支持多设备、多传感器的同步数据建模连续查询:通过物化视图实现实时数据聚合(如每小时平均值计算)触发器机制:数据变更时自动触发预设逻辑(需v0.13+)1.2.2 生态兼容多语言SDK:提供Java/Python/Go等语言驱动大数据集成:支持Spark/Flink实时计算,与Grafana深度整合协议适配:兼容MQTT、HTTP、JDBC等多种接入方式1.3 典型场景对比Apache IoTDB 针对不同的场景,这边统计出了对比表,便于伙伴们查看应用场景    数据特点    IoTDB优势    典型案例工业物联网    高频传感器数据(1ms~10s间隔),设备多元(万级节点),强时序性    1. 列式存储+时间分区优化压缩率(10:1)2. 原生支持工业协议(OPC-UA/Modbus)3. 边缘-云端协同架构    某汽车厂20000+设备监控,存储成本降低70%能源电力    带质量标签的时序数据,需实时计算(如线损分析),数据生命周期管理(冷热分层)    1. 内置TsFile格式支持数据标记2. 内置聚合函数(avg/max等)3. TTL自动过期机制    某电网公司存储5TB/天的智能电表数据智慧城市    多源异构数据(交通/环境等),空间-时间双维度查询    1. 支持时空联合索引2. 与GIS系统集成3. 毫秒级响应千万级数据点查询    某城市交通管理系统处理2000+路口的实时流量数据车联网    高并发写入(10000+TPS),轨迹数据需要压缩存储    1. 基于内存的写入缓冲2. 专有编码算法(Gorilla/RLBE)3. 支持SQL扩展    某新能源车企存储车辆每秒20个传感器的行驶数据医疗健康    非均匀采样数据(ECG等),需要模式匹配查询    1. 支持非对齐时间序列存储2. 提供相似性搜索UDF3. 医疗设备SDK集成    某三甲医院存储2000+病床的实时生命体征数据航空航天    超高精度数据(ns级时间戳),需要故障预测    1. 纳秒级时间精度2. 内置异常检测算法3. 支持联邦查询    某卫星系统每秒处理10万+遥测数据点智能制造    多维度质量分析,需与MES系统集成    1. 提供质量分析工具包2. 支持Kafka/PLC4X连接器3. 可视化API    某半导体厂实现生产设备全生命周期数字化二、Docker安装部署(附具体的操作命令)博主这里以ubuntu来安装部署,其他操作系统可以去搜索对应安装方法,需要博主来帮忙也可2.1 安装依赖的工具sudo apt-get updatesudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common2.2 安装证书curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -2.3 写入源信息sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"2.4 安装Docker-CEsudo apt-get -y updatesudo apt-get -y install docker-ce2.5 设置docker开机自启动sudo systemctl enable docker2.6 验证docker安装是否成功docker --version  #显示版本信息,即安装成功三、Docker环境下单机版部署3.1 拉取镜像IoTDB的Docker镜像在这个链接:https://hub.docker.com/r/apache/iotdb博主这里是1.3.2版本拉取镜像命令:docker pull apache/iotdb:1.3.2-standalone查看镜像:docker images效果:3.2 创建docker bridge网络命令:docker network create --driver=bridge --subnet=172.18.0.0/16 --gateway=172.18.0.1  iotdb3.3 docker-compose的yml文件把IoTDB安装目录和yml文件都放在下面这个文件目录里面,文件需要自己写(我这里有提供模版)文件目录是:/docker-iotdb/iotdb单机版docker-compose的文件是:/docker-iotdb/docker-compose-standalone.yml文件内容:version: "3"services:  iotdb-service:    image: apache/iotdb:1.3.2-standalone #使用的镜像    hostname: iotdb    container_name: iotdb    restart: always           ports:      - "6667:6667"    environment:      - cn_internal_address=iotdb      - cn_internal_port=10710      - cn_consensus_port=10720      - cn_seed_config_node=iotdb:10710      - dn_rpc_address=iotdb      - dn_internal_address=iotdb      - dn_rpc_port=6667      - dn_internal_port=10730      - dn_mpp_data_exchange_port=10740      - dn_schema_region_consensus_port=10750      - dn_data_region_consensus_port=10760      - dn_seed_config_node=iotdb:10710    privileged: true    volumes:        - ./iotdb/data:/iotdb/data        - ./iotdb/logs:/iotdb/logs    networks:      iotdb:        ipv4_address: 172.18.0.6networks:  iotdb:    external: true3.4 启动IoTDB后台启动docker-compose -f docker-compose-standalone.yml up  -d 3.5 验证是否启动成功第一种验证方式:查看日志命令docker logs -f iotdb-datanode是下面这样,就是启动成功了 第二种验证方式:进入容器,查看服务运行状态查看所有启动的容器命令docker ps登录数据库./start-cli.sh -h iotdb使用show cluster命令查看服务状态show cluster                      #查看服务状态看到服务状态都是running正在运行,这样IoTDB就已经部署成功了 3.6 修改配置文件后续如果想直接修改配置文件,可以把容器中的/conf文件夹映射出来进行修改步骤一:拷贝容器中的/conf目录到/docker-iotdb/iotdb/confdocker cp iotdb:/iotdb/conf /docker-iotdb/iotdb/confAI生成项目bash1步骤二:在docker-compose-standalone.yml中添加映射volumes:        - ./iotdb/conf:/iotdb/conf步骤三:重新启动IoTDBdocker-compose  -f docker-compose-standalone.yml  up  -d四、Docker环境下集群版部署4.1 集群架构设计(简述)因篇幅有限,集群版集体架构(3ConfigNode+3DataNode)及优势见:Apache IoTDB(2):时序数据库 IoTDB 集群安装部署的技术优势与适用场景分析 采用3ConfigNode+3DataNode的经典架构,博主这里为3台linux服务器,详细信息如下:节点IP    主机名    服务192.168.1.3    iotdb-1    ConfigNode、DataNode192.168.1.4    iotdb-2    ConfigNode、DataNode192.168.1.5    iotdb-3    ConfigNode、DataNode4.2 拉取镜像IoTDB的Docker镜像在这个链接:https://hub.docker.com/r/apache/iotdb博主这里是1.3.2版本在3台服务器上分别拉取IoTDB镜像拉取镜像命令:docker pull apache/iotdb:1.3.2-standaloneAI生成项目bash1查看镜像:docker images效果:4.3 yml文件创建把IoTDB安装目录和yml文件都放在下面这个文件目录里面,文件需要自己写(我这里有提供模版)文件目录是:/docker-iotdb/iotdbconfignode的文件是:/docker-iotdb/confignode.ymldatanode的文件是:/docker-iotdb/datanode.ymlconfignode.yml文件(示例):version: "3"services:  iotdb-confignode:    image: apache/iotdb:latest #使用的镜像    hostname: iotdb-1|iotdb-2|iotdb-3    #根据实际情况选择,三选一    container_name: iotdb-confignode    command: ["bash", "-c", "entrypoint.sh confignode"]    restart: always    environment:      - cn_internal_address=iotdb-1|iotdb-2|iotdb-3 #根据实际情况选择,三选一      - cn_internal_port=10710      - cn_consensus_port=10720      - cn_seed_config_node=iotdb-1:10710   #默认第一台为seed节点      - schema_replication_factor=3         #元数据副本数      - data_replication_factor=2           #数据副本数    privileged: true    volumes:      - ./iotdb/data:/iotdb/data      - ./iotdb/logs:/iotdb/logs    network_mode: "host"    #使用host网络datanode.yml文件(示例):version: "3"services:  iotdb-datanode:    image: iotdb-enterprise:1.3.2.3-standalone #使用的镜像    hostname: iotdb-1|iotdb-2|iotdb-3 #根据实际情况选择,三选一    container_name: iotdb-datanode    command: ["bash", "-c", "entrypoint.sh datanode"]    restart: always    ports:      - "6667:6667"    privileged: true    environment:      - dn_rpc_address=iotdb-1|iotdb-2|iotdb-3  #根据实际情况选择,三选一      - dn_internal_address=iotdb-1|iotdb-2|iotdb-3 #根据实际情况选择,三选一      - dn_seed_config_node=iotdb-1:10710      #默认第1台为seed节点      - dn_rpc_port=6667      - dn_internal_port=10730      - dn_mpp_data_exchange_port=10740      - dn_schema_region_consensus_port=10750      - dn_data_region_consensus_port=10760      - schema_replication_factor=3         #元数据副本数      - data_replication_factor=2           #数据副本数    volumes:      - ./iotdb/data:/iotdb/data      - ./iotdb/logs:/iotdb/logs    network_mode: "host"      #使用host网络4.4 启动confignode在3台服务器上分别启动confignode,需要注意启动顺序先启动第1台iotdb-1再启动iotdb-2再启动iotdb-3后台启动命令:docker-compose -f confignode.yml up  -d #4.5 启动datanode在3台服务器上分别启动datanode后台启动命令:docker-compose  -f  datanode.yml  up -d #后台启动4.6 验证是否启动成功查看日志,有如下字样,表示datanode启动成功进入容器,查看服务运行状态查看启动的容器第一种验证方式:查看日志命令docker logs -f iotdb-datanode是下面这样,就是启动成功了 第二种验证方式:进入容器,查看服务运行状态查看所有启动的容器命令docker ps登录数据库./start-cli.sh -h iotdb使用show cluster命令查看服务状态show cluster                      #查看服务状态看到服务状态都是running正在运行,这样IoTDB就已经部署成功了 4.7 修改配置文件后续如果想直接修改配置文件,可以把容器中的/conf文件夹映射出来进行修改步骤一:在3台服务器中分别拷贝容器中的/conf目录到/docker-iotdb/iotdb/confdocker cp iotdb-confignode:/iotdb/conf /docker-iotdb/iotdb/conf或docker cp iotdb-datanode:/iotdb/conf   /docker-iotdb/iotdb/conf步骤二:在3台服务器的confignode.yml和datanode.yml中添加/conf目录映射confignode.yml文件:    volumes:      - ./iotdb/conf:/iotdb/conf datanode.yml文件:    volumes:      - ./iotdb/conf:/iotdb/conf步骤三:在3台服务器上重新启动IoTDBdocker-compose  -f confignode.yml  up  -ddocker-compose  -f datanode.yml    up  -d五、性能调优5.1 版本适配矩阵场景类型    配置调整    效果提升高并发写入    增大memtable_size_threshold至256M    写入延迟降低40%复杂查询    启用enable_parallel_query=true    查询速度提升3倍跨节点查询    调整query_timeout至60000    防止超时中断5.2 内存调优文件配置文件1:confignode-env.shexport MEMORY_SIZE="4G"export JAVA_OPTS="-Xms4G -Xmx4G -XX:+UseG1GC"文件2:datanode-env.shexport MEMORY_SIZE="8G"export JAVA_OPTS="-Xms8G -Xmx8G -XX:+UseConcMarkSweepGC"六、版本适配与应用场景6.1 兼容性矩阵IoTDB版本    JDK版本    Docker版本    推荐场景0.13.x 及以上    JDK8/11/17    19.03+    生产环境0.12.x    JDK8    18.09+    兼容旧系统6.2 滚动升级流程三个步骤轻松完成升级第一步:停止旧节点docker stop datanode1第二步:迁移数据docker run --rm -v /old_data:/source apache/iotdb:1.3.2-standalone \  /iotdb/sbin/migrate-tool.sh -source /source -dest /dest第三步:启动新节点docker run -d --name datanode1_new ... apache/iotdb:1.3.2-standaloneAI生成项目bash16.3 应用场景一图理清Apache IoTDB数据库适用的场景 七、结语Apache IoTDB通过其独特的时序数据管理能力和灵活的部署方式,可针对不同场景进行安装部署。本文提供的部署方案已在多个测试环境验证。Apache IoTDB在触发器、连续查询等高级功能上的突破,能够快速构建起高效可靠的物联网时序数据平台,为数字化转型提供数据支撑,本文详细讲述了Docker安装部署方案,建议小伙伴在实践过程中,结合具体业务场景调整配置参数,小伙伴部署中有任何问题可以私信或VX联系博主,博主会第一时间为你解答。————————————————                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                        原文链接:https://blog.csdn.net/Dreamy_zsy/article/details/149901830
  • Apache httpd 入门实战(2)--简单使用
    本文主要介绍 Apache 的实际使用,文中所使用到的软件版本:Centos 7.9.2009、Httpd 2.4.55。1、反向代理涉及到 Https 站点时,安装 Apache 时需要启用 ssl,可参考 Apache httpd 入门实战(1)--概念及安装。1.1、被代理站点为 Http 站点打开 conf/httpd.conf 文件,修改或新增相应的配置项:Listen 8080ServerName 10.49.196.33:8080LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soinclude conf/extra/my-vhosts.conf新建 conf/extra/my-vhosts.conf 文件:<VirtualHost *:8080> ServerAdmin admin@abc.com ServerName abc.com ServerAlias abc.com ErrorLog "logs/abc.com-error_log" CustomLog "logs/abc.com-access_log" common ProxyPass /qwe http://10.49.196.1:9090/qwe ProxyPassReverse /qwe http://10.49.196.1:9090/qwe</VirtualHost>代理地址为 http://10.49.196.33:8080/qwe,被代理的地址为 http://10.49.196.1:9090/qwe。1.2、被代理站点为 Https 站点打开 conf/httpd.conf 文件,修改或新增相应的配置项:Listen 8080ServerName 10.49.196.33:8080LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule ssl_module modules/mod_ssl.soinclude conf/extra/my-vhosts.conf新建 conf/extra/my-vhosts.conf 文件:<VirtualHost *:8080> ServerAdmin admin@abc.com ServerName abc.com ServerAlias abc.com ErrorLog "logs/abc.com-error_log" CustomLog "logs/abc.com-access_log" common SSLProxyEngine On ProxyPass /asd https://10.49.196.1:9091/asd ProxyPassReverse /asd https://10.49.196.1:9091/asd</VirtualHost>代理地址为 http://10.49.196.33:8080/asd,被代理的地址为 https://10.49.196.1:9091/asd。1.3、代理站点启用 Https1.3.1、生成证书代理站点启用 Https,需要使用 OpenSSL 创建证书。A、生成根证书openssl genrsa -out ca.keyopenssl req -new -key ca.key -out ca.csropenssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.pemB、生成服务端证书openssl genrsa -out server.keyopenssl req -new -key server.key -out server.csropenssl ca -days 3650 -in server.csr -cert ca.pem -keyfile ca.key -out server.pemC、生成客户端证书openssl genrsa -des3 -out client.key 1024openssl req -new -key client.key -out client.csropenssl ca -days 1500 -in client.csr -cert ca.pem -keyfile ca.key -out client.pemopenssl pkcs12 -export -clcerts -in client.pem -inkey client.key -out client.p12使用 OpenSSL 创建证书的详细说明可参考:OpenSSL 介绍(5)--数字证书;这里生成的证书假设都存放在 /home/mongo/ssl 目录下。1.3.2、Apache 中配置 Https打开 conf/httpd.conf 文件,修改或新增相应的配置项:Listen 8443ServerName 10.49.196.33:8443LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule ssl_module modules/mod_ssl.soinclude conf/extra/my-vhosts.conf新建 conf/extra/my-vhosts.conf 文件:<VirtualHost *:8443> ServerAdmin admin@abc.com ServerName abc.com ServerAlias abc.com ErrorLog "logs/abc.com-error_log" CustomLog "logs/abc.com-access_log" common SSLEngine on SSLCertificateFile /home/mongo/ssl/server.pem SSLCertificateKeyFile /home/mongo/ssl/server.key ProxyPass /qwe http://10.49.196.1:9090/qwe ProxyPassReverse /qwe http://10.49.196.1:9090/qwe SSLProxyEngine On ProxyPass /asd https://10.49.196.1:9091/asd ProxyPassReverse /asd https://10.49.196.1:9091/asd</VirtualHost>代理地址为 https://10.49.196.33:8443/qwe、https://10.49.196.33:8443/asd,被代理的分别地址为 http://10.49.196.1:9090/qwe、https://10.49.196.1:9091/asd。如果需要验证客户端,则配置如下:<VirtualHost *:8443> ServerAdmin admin@abc.com ServerName abc.com ServerAlias abc.com ErrorLog "logs/abc.com-error_log" CustomLog "logs/abc.com-access_log" common SSLEngine on SSLCertificateFile /home/mongo/ssl/server.pem SSLCertificateKeyFile /home/mongo/ssl/server.key SSLVerifyClient require SSLCACertificateFile /home/mongo/ssl/ca.pem ProxyPass /qwe http://10.49.196.1:9090/qwe ProxyPassReverse /qwe http://10.49.196.1:9090/qwe SSLProxyEngine On ProxyPass /asd https://10.49.196.1:9091/asd ProxyPassReverse /asd https://10.49.196.1:9091/asd</VirtualHost>2、负载均衡打开 conf/httpd.conf 文件,修改或新增相应的配置项:Listen 8080ServerName 10.49.196.33:8080LoadModule watchdog_module modules/mod_watchdog.soLoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule proxy_balancer_module modules/mod_proxy_balancer.soLoadModule proxy_hcheck_module modules/mod_proxy_hcheck.soLoadModule slotmem_shm_module modules/mod_slotmem_shm.so LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.soLoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.soLoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.soLoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.soinclude conf/extra/my-vhosts.conf2.1、不考虑 session新建 conf/extra/my-vhosts.conf 文件:<VirtualHost *:8080> ServerAdmin admin@abc.com ServerName abc.com ServerAlias abc.com ErrorLog "logs/abc.com-error_log" CustomLog "logs/abc.com-access_log" common <Proxy balancer://mycluster> BalancerMember http://10.49.196.1:9090 loadfactor=2 BalancerMember http://10.49.196.2:9090 loadfactor=3 timeout=3 ProxySet lbmethod=byrequests </Proxy> ProxyPass /xyz balancer://mycluster/xyz ProxyPassReverse /xyz balancer://mycluster/xyz</VirtualHost>lbmethod:负载均衡算法lbmethod=byrequests:按请求次数负载均衡lbmethod=bytraffic:按流量负载均衡lbmethod=bybusyness:按繁忙程度(挂起的请求数)负载均衡lbmethod=heartbeat:按心跳数负载均衡loadfactor:负载因子;timeout:超时时间,单位为秒。代理地址为 http://10.49.196.33:8080/xyz,被代理的地址为 http://10.49.196.1:9090/xyz、http://10.49.196.2:9090/xyz。2.2、session 粘滞对应有 session 的情况,同一客户端需要把请求转发到同一个后端服务。新建 conf/extra/my-vhosts.conf 文件:<VirtualHost *:8080> ServerAdmin admin@abc.com ServerName abc.com ServerAlias abc.com ErrorLog "logs/abc.com-error_log" CustomLog "logs/abc.com-access_log" common <Proxy balancer://mycluster> Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/tsp" env=BALANCER_ROUTE_CHANGED BalancerMember http://10.49.196.1:9090 loadfactor=2 route=server1 BalancerMember http://10.49.196.2:9090 loadfactor=3 route=server2 ProxySet lbmethod=byrequests ProxySet stickysession=ROUTEID </Proxy> ProxyPass /xyz balancer://mycluster/xyz ProxyPassReverse /xyz balancer://mycluster/xyz</VirtualHost>Header add Set-Cookie:设置名称为 ROUTEID 的 cookieProxySet stickysession=ROUTEID:根据 cookie ROUTEID 的值路由到相应的后端服务2.3、failover<Proxy balancer://myset> BalancerMember http://www2.example.com:8080 BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1 BalancerMember http://spare1.example.com:8080 status=+R BalancerMember http://spare2.example.com:8080 status=+R BalancerMember http://hstandby.example.com:8080 status=+H BalancerMember http://bkup1.example.com:8080 lbset=1 BalancerMember http://bkup2.example.com:8080 lbset=1 ProxySet lbmethod=byrequests</Proxy>ProxyPass "/images/" "balancer://myset/"ProxyPassReverse "/images/" "balancer://myset/"A、http://www2.example.com:8080 或 http://www3.example.com:8080 不可用时,才会把流量分配给 http://spare1.example.com:8080 和 http://spare2.example.com:8080。一个备用的节点会替换一个不可用的节点。B、当 http://www2.example.com:8080、http://www2.example.com:8080、http://www2.example.com:8080、http://www2.example.com:8080 都不可用时,才会把流量分配给热备节点:http://hstandby.example.com:8080。C、当所有 lbset=0(后端节点的优先级,默认为 0;数值越低的,优先级越高) 的节点(正常节点、备用节点、热备节点)都不可用时,才会把流量分配给备份节点:http://bkup1.example.com:8080 和 http://bkup2.example.com:8080。2.4、负载均衡管理器<VirtualHost *:8080>... <Location "/balancer-manager"> SetHandler balancer-manager Require ip 10.49.196.35 </Location>...</VirtualHost>Require ip:设置可用访问负载均衡器的 ip。通过负载均衡管理页面(http://10.49.196.33:6060/balancer-manager)可以查看负载均衡的配置和状态,还可以在页面上直接修改配置。参考:https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html。
  • Apache httpd 入门实战(1)--概念及安装
    Apache httpd 是 Apache 软件基金会的一个开源的 Web 服务器,可以在大多数计算机操作系统中运行,由于其跨平台和安全性被广泛使用,是最流行的 Web 服务器端软件之一。本文主要介绍其基本概念及安装,文中所使用到的软件版本:httpd 2.4.55、apr 1.7.2、apr-util 1.6.3、pcre 8.43、CentOS 7.9.2009。1、Apache 概念1.1、简介Apache httpd 起初由伊利诺伊大学香槟分校的国家超级电脑应用中心(NCSA)开发,经过多次修改,成为世界上最流行的 Web 服务器软件之一。Apache取自“a patchy server”的读音,意思是充满补丁的服务器,因为它是自由软件,所以不断有人来为它开发新的功能、新的特性、修改原来的缺陷。Apache 的特点是简单、速度快、性能稳定,并可做代理服务器来使用。本来它只用于小型或试验 Internet 网络,后来逐步扩充到各种 Unix 系统中,尤其对 Linux 的支持相当完美。Apache 有多种特性,可以支持SSL技术,支持多个虚拟主机。Apache 是以进程为基础的结构,进程要比线程消耗更多的系统开支,不太适合于多处理器环境,因此,在一个 Apache Web 站点扩容时,通常是增加服务器或扩充群集节点而不是增加处理器。世界上很多著名的网站如Amazon、Yahoo!、W3 Consortium、Financial Times 等都是 Apache的产物,它的成功之处主要在于它的源代码开放、有一支开放的开发队伍、支持跨平台的应用(可以运行在几乎所有的Unix、Windows、Linux系统平台上)以及它的可移植性等方面。Apache httpd 的诞生极富有戏剧性。当 NCSA WWW 服务器项目停顿后,那些使用 NCSA WWW 服务器的人们开始交换他们用于该服务器的补丁程序,他们也很快认识到成立管理这些补丁程序的组织是必要的。就这样,诞生了Apache Group,后来这个团体在 NCSA 的基础上创建了 Apache httpd。1.2、多处理模块(MPM)Apache httpd 被设计为功能强大且灵活的 Web 服务器,可以在各种不同环境中的多种平台上工作。不同的平台和环境通常需要不同的功能,或者可能具有不同的方式来最有效地实现相同的功能。Apache httpd 通过其模块化设计一直适应各种环境。通过这种设计,网站管理员可以通过选择在编译时或运行时加载哪些模块来选择服务器中将包含哪些功能。Apache httpd 2.0 将此模块化设计扩展到 Web 服务器的最基本功能。该服务器随附了多种选择的多处理模块(MPM),这些模块负责绑定到计算机上的网络端口,接受请求并调度子代来处理请求。将模块化设计扩展到服务器的这一级别有两个重要的好处:Apache httpd 可以更干净,更有效地支持各种操作系统。特别是,服务器的 Windows 版本现在更加高效,因为它 mpm_winnt 可以使用本机联网功能代替 Apache httpd 1.3 中使用的 POSIX 层。此好处还扩展到了实现专用 MPM 的其他操作系统。可以针对特定站点的需求更好地定制服务器。例如,需要大量可伸缩性的站点可以选择使用 worker 或 event,而需要稳定性或与旧版软件兼容的站点可以使用 prefork。下表列出了各种操作系统的默认 MPM。如果您在编译时没有其他选择,则将选择该 MPM。在这里,“Unix” 用于表示类似 Unix 的操作系统,例如 Linux,BSD,Solaris,Mac OS X 等。对于 Unix,关于安装哪个 MPM 的决定基于两个问题:1、系统是否支持线程?2、系统是否支持线程安全轮询(特别是 kqueue 和 epoll 函数)?如果两个问题的答案均​​为“是”,则默认 MPM 为 event。如果#1的答案为“是”,而#2的答案为“否”,则默认值为 worker。如果两个问题的答案均​​为“否”,则默认 MPM 为 prefork。实际上,这意味着默认值几乎始终为 event,因为所有现代操作系统都支持这两个功能。编译的时候可以通过 --with-mpm 参数指定 mpm;安装完成后可通过 bin/httpd -V |grep -i "Server MPM" 命令查看当前使用的 mpm。1.2.1、preforkAapache httpd 在启动之初,就预先派生一些子进程,然后等待请求过来;每个子进程只有一个线程,在一个时间点内,只能处理一个请求。优点:成熟稳定,兼容所有模块,线程安全性高。缺点:不适合处理高并发请求;一个进程相对占用更多的系统资源,消耗更多的内存。1.2.2、worker使用多进程和多线程的混合模式,也预先派生几个子进程(数量远少于 prefork 派生的);每个子进程创建多个线程,包括一个监听线程;每个请求会被分配一个线程来服务。优点:占据更少的内存,适合高并发的场景。缺点:必须考虑线程安全的问题,使用 keep-alive 长连接的时候,某个线程会被一直占用,即使没有收到请求,需要等待到超时才会释放;一个线程出现问题也会导致同一进程下的线程出现问题。1.2.3、event类似于 worker 的工作模式,最大区别是它解决了 keep-alive 场景下,长期被占用的线程的资源的浪费问题;event 模式下,会有一个专门的线程来管理这些 keep-alive 类型的线程,当有真实的请求过来的时候,将请求传递给服务线程,执行完毕又允许它释放。2、安装2.1、依赖软件安装2.1.1、pcre 安装官网(http://www.pcre.org/)下载 pcre,解压并安装:unzip pcre-8.43.zipcd pcre-8.43./configure --prefix=/fop/soft/pcre-8.43makemake install安装完成后需把 pcre 的 bin 目录添加到 PATH 的环境变量中:PATH=$PATH:/home/mongo/soft/pcre-8.43/binexport PATH2.1.2、APR 和 APR-Util 下载官网(https://apr.apache.org/)下载 APR 和 APR-Util,然后解压到 httpd 源码目录的 srclib 目录下,解压后的目录需要把版本号去除:APR 和 APR-Util 只需把源码放到指定目录,不需要单独编译及安装。2.1.3、OpenSSL 安装如果不需要配置 https,则该步不需要;OpenSSL 的安装可参考:OpenSSL 介绍(1)--概念及安装。这里安装在 /home/mongo/soft/openssl-1.1.1s 目录下。2.2、httpd 安装官网(https://httpd.apache.org/download.cgi)下载 httpd,解压后参考 2.1.2 的方法把 APR 和 APR-Util 的源码放到 srclib 目录下;然后编译安装:cd httpd-2.4.55./configure --prefix=/home/mongo/soft/httpd-2.4.55 --with-included-apr --enable-ssl --with-ssl=/home/mongo/soft/openssl-1.1.1smakemake install安装完成后需把 OpenSSL 的 libssl 和 libcrypto 包拷贝到 httpd 安装目录的 lib 下:cp /home/mongo/soft/openssl-1.1.1s/lib/libssl.so.1.1 /home/mongo/soft/httpd-2.4.55/lib/cp /home/mongo/soft/openssl-1.1.1s/lib/libcrypto.so.1.1 /home/mongo/soft/httpd-2.4.55/lib/2.3、启动编辑 conf/httpd.conf 文件:Listen 8080ServerName 10.49.196.33:8080执行命令:bin/apachectl启动后访问 8080 端口:2.4、停止及重启bin/apachectl -k stop #停止bin/apachectl -k restart #重启2.5、错误处理2.5.1、fatal error: expat.h: No such file or directorymake 时可能会报:fatal error: expat.h: No such file or directory这是由于系统中缺少 expat-devel,安装下即可:yum install expat-devel2.5.2、error: Did not find working script at pcre-configconfigure 时可能会报:configure: error: Did not find working script at pcre-config找不到 pcre-config 命令,需把 pcre 的 bin 目录添加到 PATH 的环境变量中:PATH=$PATH:$PCRE_HOME/binexport PATH2.5.3、Cannot load modules/mod_ssl.so into server启动 httpd 时可能会报:httpd: Syntax error on line 133 of /home/mongo/soft/httpd-2.4.55/conf/httpd.conf: Cannot load modules/mod_ssl.so into server: libssl.so.1.1: cannot open shared object file: No such file or directoryOpenSSL 相关的包找不到,需把 OpenSSL 的 libssl 和 libcrypto 包拷贝到 httpd 安装目录的 lib 下:cp $OPNESSL_HOME/lib/libssl.so.1.1 $HTTPD_HOME/lib/cp $OPNESSL_HOME/lib/libcrypto.so.1.1 $HTTPD_HOME/lib/
  • [课程学习] apache学习随笔
    使用apache服务来部署静态网站Apache特点:跨平台,安全性nginx特点:轻量级,高并发 apache的服务名称叫做httpd通过systemctl来实现对http的各种操作httpd服务各个配置文件存放的位置我们可以修改httpd.conf文件下面来实现对访问路径的修改/文件但是在修改之后我们发现界面为这里就是SElinux在起作用了,下面讲讲selinux SElinux安全子系统Security-enhanced LINUX:对资源的访问提供限制的保险,打个比方:防火墙是窗户,那么SELinux就是防护栏服务模式 作用enforcing强制启动安全模式,将拦截的服务不合法请求permissive对于不合法请求只发出警告不会强制拦截disabled对于越权的行为不警告也不拦截如何查看安全模式?/etc/selinux/config里面,修改后重启生效 回归上文,为什么会出现禁止访问呢?因为/home目录是存放用户数据的目录而不是httpd服务的目录,所以SELINUX会禁止访问这个目录下面的文件解决这个问题有几个方法1:关闭Selinux2:修改http.conf,然后将文件复制到原来的路径下面(笨蛋方法3:通过semanage命令来实现添加对访问权限的添加一般来说bash下面不一定有semanage这条命令,需要我们下载安装包yum  install policycoreutils-python之后可以使用semanage命令了semanage fcontext -a -t httpd_sys_content /home/wwwtestsemanage fcontext -a -t httpd_sys_content /home/wwwtest/*向网站数据下面加一条SELINUX上下文,使得目录和里面的数据可以被httpd服务访问到restorecon -Rv /home/wwwtest/对目录进行递归,最后可以访问得到页面内容4:还有可能是selinux域安全策略密钥放行,这里通过getsebool和查找来找到相关服务getsebool -a | grep httpd我们将安全策略修改就可以实现(这里设置的为个人博客,当然做不同的东西可能会碰到不同得到东西就是了,原理相同setsebool httpd_enable_homedirs=on 
  • Struts2框架小知识
      Struts2 是 Apache 软件组织推出的一个相当强大的 Java Web 开源框架,本质上相当于一个 servlet。Struts2 基于 MVC 架构,框架结构清晰。通常作为控制器(Controller)来建立模型与视图的数据交互,用于创建企业级 Java web 应用程序      Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts2是一个基于MVC设计模式的Web应用框架,大家可以看看之前分享过的一篇介绍什么是MVC:cid:link_0Struts2详细工作流程?     a.浏览器发出welcome.action请求     b.请求到达Struts的Filter控制器(由于web.xml配置)c.Struts控制器判断请求类型,如果是/welcome.action或/welcome格式请求,将调用struts.xml配置,寻找对应的Action组件     d.调用Action组件的execute方法处理请求,最后返回一个String视图标识     e.Struts控制器根据视图标识寻找相应的JSP(struts.xml中result配置)     f.调用JSP视图生成响应界面给浏览器显示。Struts2控制流程?         1)请求到来         2)创建ValueStack(Action放栈顶),进行初始化         3)调用拦截器Interceptor,在拦截器中是可以访问ValueStack的         4)调用Action,执行execute()方法         5)调用Result,Result负责把数据显示给用户         6)最后到页面,通过标记库(Taglib)取出数据       Struts2中常用的集中Result组件?    1)JSP响应         dispatcher :采用请求转发方式调用JSP组件响应。         redirect:采用请求重定向方式调用JSP组件响应。(在重定向后,原request和action都被销毁掉,因此在JSP获取不到值)    2)Action响应         redirectAction:采用重定向方式发出一个*.action请求         chain:采用转发方式发出一个*.action请求    3)流响应          典型功能:验证码和下载。          stream:可以将Action中的一个InputStream类型属性以流方式响应输出。    4)JSON响应           负责对Ajax请求进行数据响应。          json:可以将Action中的一个属性或多个属性以json格式响应输出        (注意:使用前需要引入struts-json-plugin.jar,然后将<package>元素的extends设置成"json-default")
  • [技术干货] 使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(5)
    使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(5)在开始使用IoTDB之前,大家需要首先配置配置文件,为了方便起见,已经有部分重要文件设置了默认配置。总的来说,Apache IoTDB为用户提供三种配置模块:环境配置文件(iotdb-env.bat, iotdb-env.sh),环境配置项的默认配置文件。用户可以在文件中配置JAVA-JVM的相关系统配置项系统配置文件(iotdb-engine.properties),iotdb-engine.properties:IoTDB引擎层配置项的默认配置文件。用户可以在文件中配置IoTDB引擎的相关参数,如JDBC服务监听端口(rpc_port),未排序数据存储目录(unsequence_data_dir),等等。此外,用户可以配置关于TsFile的信息,例如每次写入磁盘的数据大小(group_size_in_byte)日志配置文件(logback.xml)三个配置项的配置文件位于IoTDB安装目录中:$IOTDB_HOME/conf文件夹。热修改配置为了方便用户,IoTDB服务器为用户提供了热修改功能,即修改中的一些配置参数iotdb engine. Properties并立即将其应用到系统中。在下面描述的参数中,这些参数Effective是trigger支持热修改。触发方式:客户端发送命令load configurationIoTDB服务器。有关客户端的使用,请参见第4章。IoTDB环境配置文件环境配置文件主要用于配置IoTDB服务器运行时的Java环境相关参数,如JVM相关配置。当IoTDB服务器启动时,这部分配置被传递给JVM。用户可以通过查看iotdb-env.sh(或者iotdb-env.bat)文件。每个变量的细节如下:MAX_HEAP_SIZEHEAP_NEWSIZEJMX_LOCALJMX_PORTJMX_IP
  • [技术干货] 使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(4)
    使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(4)编码为了提高数据存储的效率,需要在数据写入时对数据进行编码,从而减少磁盘空间的使用量。在写入和读取数据的过程中,可以减少I/O操作中涉及的数据量以提高性能。对于不同类型的数据,IoTDB支持四种编码方法:PLAIN:普通编码是默认的编码模式,即不编码,支持多种数据类型。它具有较高的压缩和解压缩效率,但空间存储效率较低。TS_2DIFF:二阶差分编码更适合对单调递增或递减的序列数据进行编码,不推荐对波动较大的序列数据进行编码。RLE:游程编码更适合存储具有连续整数值的序列,不推荐用于大多数时间具有不同值的序列数据。游程编码也可用于对浮点数进行编码,但必须指定保留的十进制数字。比较适合存储浮点值连续出现、单调递增或递减的序列数据,不适合存储小数点后精度要求高或波动较大的序列数据。GORILLA:GORILLA编码更适合值相近的浮点序列,不建议用于波动较大的序列数据。常规编码常规数据编码更适合编码常规序列递增的数据(例如,每个数据点之间经过的时间相同的时间序列),在这种情况下,它比TS_2DIFF更好。规则数据编码方式不适合有波动的数据,即不规则数据,此时建议用TS_2DIFF处理。数据类型和编码之间的对应关系前面描述的四种编码适用于不同的数据类型。如果对应关系是错误的,就不能正确地创建时间序列。下表中详细总结了数据类型及其支持的编码之间的对应关系。**数据类型及其支持的编码之间的对应关系**Data TypeSupported EncodingBOOLEANPLAIN, RLEINT32PLAIN, RLE, TS_2DIFF, REGULARINT64PLAIN, RLE, TS_2DIFF, REGULARFLOATPLAIN, RLE, TS_2DIFF, GORILLADOUBLEPLAIN, RLE, TS_2DIFF, GORILLATEXTPLAIN压缩当时间序列按照指定的类型写成二进制数据编码后,IoTDB使用压缩技术对数据进行压缩,进一步提高空间存储效率。虽然编码和压缩都是为了提高存储效率,但编码技术通常只适用于特定的数据类型。例如,二阶差分编码只适用于INT32或INT64数据类型,存储浮点数需要乘以10m才能转换为整数,之后将数据转换为二进制流。压缩方法(SNAPPY)压缩二进制流,因此压缩方法的使用不再受数据类型的限制。IoTDB允许咱们开发者在创建时间序列时指定列的压缩方法,现在主要支持以下两种压缩方法:UNCOMPRESSEDSNAPPY单节点设置大家可以通过sbin文件夹下的启动服务器脚本来启动IoTDB。# Unix/OS X> nohup sbin/start-server.sh >/dev/null 2>&1 &or> nohup sbin/start-server.sh -c -rpc_port >/dev/null 2>&1 &# Windows> sbin\start-server.bat -c -rpc_port "-c "和"-rpc_port "是可选的选项"-c "指定系统配置文件目录选项“-rpc_port”指定rpc端口如果两个选项都指定了,则rpc _端口将覆盖中的rpc_port配置路径
  • [技术干货] 使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(3)
    使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(3)接下来我给大家继续介绍一下Apache IoTDB的数据类型和相关用法在显示时间戳时,IoTDB可以支持长类型和日期时间显示类型。日期时间显示类型可以支持用户定义的时间格式。自定义时间格式的语法如下表所示:**自定义时间格式的语法**SymbolMeaningPresentationExamplesGeraeraeraCcentury of era (>=0)number20Yyear of era (>=0)year1996xweekyearyear1996wweek of weekyearnumber27eday of weeknumber2Eday of weektextTuesday; Tueyyearyear1996Dday of yearnumber189Mmonth of yearmonthJuly; Jul; 07dday of monthnumber10ahalfday of daytextPMKhour of halfday (0~11)number0hclockhour of halfday (1~12)number12Hhour of day (0~23)number0kclockhour of day (1~24)number24mminute of hournumber30ssecond of minutenumber55Sfraction of secondmillis978ztime zonetextPacific Standard Time; PSTZtime zone offset/idzone-0800; -08:00; America/Los_Angeles‘escape for textdelimiter‘’single quoteliteral‘相对时间戳相对时间是指相对于服务器时间的时间now()和DATETIME时间。用法如下:Duration = (Digit+ ('Y'|'MO'|'W'|'D'|'H'|'M'|'S'|'MS'|'US'|'NS'))+RelativeTime = (now() | DATETIME) ((+|-) Duration)+**持续时间单位的语法**SymbolMeaningPresentationExamplesyyear1y=365 days1ymomonth1mo=30 days1mowweek1w=7 days1wdday1d=1 day1dhhour1h=3600 seconds1hmminute1m=60 seconds1mssecond1s=1 second1smsmillisecond1ms=1000_000 nanoseconds1msusmicrosecond1us=1000 nanoseconds1usnsnanosecond1ns=1 nanosecond1ns用法如下:now() - 1d2h //1 day and 2 hours earlier than the current server timenow() - 1w //1 week earlier than the current server time数据类型IoTDB一共支持以下6种数据类型:BOOLEAN (布尔型)INT32 (整数型)INT64 (长整数型)FLOAT (单精度浮点)DOUBLE (双精度浮点)TEXT (字符串)时间序列float和double类型可以指定最大点数,如果编码方法为,则为浮点数小数点后的位数RLE或者TS_2DIFF,如果未指定最大点数,系统将使用浮点精度在配置文件中iotdb-engine.properties。对于浮点数据值,数据范围是(MAX_VALUE,整数型。MAX_VALUE),而不是Float。MAX_VALUE,而max_point_number是19,这是因为Java中函数Math.round(float)的限制。对于双精度数据值,数据范围为(MAX_VALUE,长整数型。MAX_VALUE),而不是Double。MAX_VALUE,而max_point_number是19,这是因为Java(Long)中函数Math.round(double)的限制,MAX_VALUE=9.22E18。当用户在系统中输入的数据的数据类型与时间序列的数据类型不对应时,系统将报告类型错误。如下所示,二阶差分编码不支持布尔类型:IoTDB> create timeseries root.ln.wf02.wt02.status WITH DATATYPE=BOOLEAN, ENCODING=TS_2DIFFerror: encoding TS_2DIFF does not support BOOLEAN
  • 使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(2)
    使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(2)Apache IoTDB中常见的数据模型和术语通过上图我们可以非常清楚的了解到属性的覆盖范围和它们之间的隶属关系,并且根据属性的覆盖范围和它们之间的隶属关系,将其表达为属性层次结构。其层次关系为:power group layer - power plant layer - device layer - sensor layer。其中,ROOT是根节点,传感器层的每个节点称为一个叶节点。在使用IoTDB的过程中,可以用“.”直接连接从根节点到每个叶节点的路径上的属性,从而形成了IoTDB中一个timeseries的名称。例如,图中最左边的路径可以生成一个名为ROOT.ln.wf01.wt01.status 的路径。1.属性层次结构在获得时间序列的名称后,大家就需要根据数据的实际场景和规模来设置存储组。在一般场景下,数据通常是以组为单位到达的(即数据可能跨越电场和设备),为了避免写数据时频繁切换io,也为了满足用户对以组为单位的数据进行物理隔离的要求,可以在组层设置存储组。接下来我给大家介绍几个IoTDB中涉及的模型的基本概念:设备设备是真实场景中装备有传感器的装置。在IoTDB中,所有的传感器都应该有相应的设备。传感器传感器是实际场景中的检测设备,能够感知待测信息,并将感知到的信息转换成电信号或其他所需形式的信息输出,并发送给IoTDB。在IoTDB中,所有存储的数据和路径都以传感器为单位进行组织。存储组存储组用于让用户定义如何组织和隔离磁盘上不同的时间序列数据。属于同一存储组的时间序列将被连续写入相应文件夹中的同一文件。该文件可能由于用户命令或系统策略而关闭,因此来自这些传感器的下一个数据将存储在同一文件夹的新文件中。属于不同存储组的时间序列存储在不同的文件夹中。用户可以将任何前缀路径设置为存储组。假设有四个时间序列root.vehicle.d1.s1, root.vehicle.d1.s2, root.vehicle.d2.s1, root.vehicle.d2.s2,两个设备d1和d2在小路下面root.vehicle可能属于同一个车主或者同一个厂家,所以d1和d2关系密切。此时,可以将前缀path root.vehicle指定为一个存储组,这将使IoTDB能够将其下的所有设备存储在同一个文件夹中。下新添加的设备root.vehicle也将属于该存储组。其中完整路径(root.vehicle.d1.s1如上例所示)不允许设置为存储组。设置合理数量的存储组可以带来性能的提升:既不会因为存储文件或文件夹过多而导致IO频繁切换,也不会因为占用大量内存,导致内存文件频繁切换而导致系统变慢,也不会因为存储文件或文件夹过少而导致写命令阻塞,起到降低并发的作用。用户应该根据自己的数据大小和使用场景来平衡存储文件的存储组设置,以获得更好的系统性能。(大家如果对于存储组设置非常感兴趣的话,可以自己查询一下官方提供的存储组规模和性能测试报告)。其中时间序列的前缀必须属于一个存储组。在创建时间序列之前,用户必须设置该序列属于哪个存储组。只有设置了存储组的时间序列才能保存到磁盘上。一旦前缀路径被设置为存储组,就不能更改存储组设置。设置存储组后,不允许再次设置相应前缀路径的所有父层和子层(例如,在root.ln设置为存储组、根层和root.ln.wf01不允许设置为存储组。路径在IoTDB中,路径是符合以下约束的表达式:path: LayerName (DOT LayerName)+LayerName: Identifier | STAR我们称两条路径之间的中间部分为“.”作为一个层,因此root.A.B.C是一条有四层的路径。值得注意的是,在路径中,root是一个保留字符,只允许出现在下面提到的时间序列的开头。如果root出现在其他层中,则无法对其进行解析并报告错误。时间序列路径timeseries路径是IoTDB中的核心概念。时间序列路径可以被认为是产生时间序列数据的传感器的完整路径。IoTDB中的所有时间序列路径必须以root开始,以传感器结束。时间序列路径也可以称为完整路径。例如,如果车辆类型的设备1有一个名为sensor1的传感器,则其时间序列路径可表示为:root.vehicle.device1.sensor1.其中当前IoTDB支持的timeseries路径的层数必须大于等于四层(以后会改为两层)。前缀路径前缀路径是指timeseries路径的前缀所在的路径。前缀路径包含以该路径为前缀的所有时间序列路径。例如,假设我们有三个传感器:root.vehicle.device1.sensor1, root.vehicle.device1.sensor2, root.vehicle.device2.sensor1,前缀路径root.vehicle.device1包含两个时间序列路径root.vehicle.device1.sensor1和root.vehicle.device1.sensor,期间root.vehicle.device2.sensor1被排除在外。带星形的路径为了更方便快捷地表示多个时序路径或前缀路径,IoTDB为用户提供了路径指针。*可以出现在路径的任何一层。根据所处的位置*出现时,带有星号的路径可以分为两种类型:*出现在路径的末端;*出现在路径中间;*出现在路径的末尾的时候,它表示(*)+,它是一层或多层*。举个例子,root.vehicle.device1.*表示所有前缀为root.vehicle.device1层数大于或等于4层,如root.vehicle.device1.*,root.vehicle.device1.*.*, root.vehicle.device1.*.*.*等。当...的时候*出现在路径的中间,它代表*本身,即一层。举个例子,root.vehicle.*.sensor1表示前缀为的4层路径root.vehicle后缀是sensor1。在这里我们应该注意:*不能放在路径的开头。路径包含*与前缀路径具有相同的含义,例如,root.vehicle.*和root.vehicle是一样的。时间戳时间戳是产生数据的时间点。它包括绝对时间戳和相对时间戳绝对时间戳IoTDB中的绝对时间戳分为LONG和DATETIME两种(包括DATETIME-INPUT和DATETIME-DISPLAY)。当用户输入时间戳时,他可以使用长类型时间戳或日期时间输入类型时间戳,日期时间输入类型时间戳支持的格式如下表所示:**日期时间输入类型时间戳的支持格式* *Formatyyyy-MM-dd HH:mm:ssyyyy/MM/dd HH:mm:ssyyyy.MM.dd HH:mm:ssyyyy-MM-dd’T’HH:mm:ssyyyy/MM/dd’T’HH:mm:ssyyyy.MM.dd’T’HH:mm:ssyyyy-MM-dd HH:mm:ssZZyyyy/MM/dd HH:mm:ssZZyyyy.MM.dd HH:mm:ssZZyyyy-MM-dd’T’HH:mm:ssZZyyyy/MM/dd’T’HH:mm:ssZZyyyy.MM.dd’T’HH:mm:ssZZyyyy/MM/dd HH:mm:ss.SSSyyyy-MM-dd HH:mm:ss.SSSyyyy.MM.dd HH:mm:ss.SSSyyyy/MM/dd’T’HH:mm:ss.SSSyyyy-MM-dd’T’HH:mm:ss.SSSyyyy.MM.dd’T’HH:mm:ss.SSSyyyy-MM-dd HH:mm:ss.SSSZZyyyy/MM/dd HH:mm:ss.SSSZZyyyy.MM.dd HH:mm:ss.SSSZZyyyy-MM-dd’T’HH:mm:ss.SSSZZyyyy/MM/dd’T’HH:mm:ss.SSSZZyyyy.MM.dd’T’HH:mm:ss.SSSZZISO8601 standard time format这次先给大家介绍到这里,下次再来给小伙伴们介绍时间戳和相对时间戳的数据格式~
  • [技术干货] 使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(1)
    使用Apache IoTDB进行IoT相关开发的架构设计与功能实现(1)当今社会,物联网技术的发展带来了许多繁琐的挑战,尤其是在数据库管理系统领域,比如实时整合海量数据、处理流中的事件以及处理数据的安全性。例如,应用于智能城市的基于物联网的交通传感器可以实时生成大量的交通数据。据估计,未来5年,物联网设备的数量将达数万亿。物联网产生大量的数据,包括流数据、时间序列数据、RFID数据、传感数据等。要有效地管理这些数据,就需要使用数据库。数据库在充分处理物联网数据方面扮演着非常重要的角色。因此,适当的数据库与适当的平台同等重要。由于物联网在世界上不同的环境中运行,选择合适的数据库变得非常重要。1.什么是IoTDB有的小伙伴可能不了解什么是IoTDB,我先来给大家简单介绍一下:IoTDB即物联网数据库,是一个面向时间序列数据的集成数据管理引擎,可以为用户提供特定的数据收集、存储和分析服务。由于其轻量级结构、高性能和可用特性,以及与Hadoop和Spark ecology的紧密集成,IoTDB满足了物联网工业领域的海量数据集存储、高速数据输入和复杂数据分析的要求。2.IoTDB的体系结构IoTDB套件可以提供真实情况下的数据采集、数据写入、数据存储、数据查询、数据可视化和数据分析等一系列功能,下图显示了IoTDB套件的所有组件带来的整体应用程序架构。如图所示呢,咱们广大用户可以使用JDBC将设备上传感器收集的时间序列数据导入本地/远程IoTDB。这些时间序列数据可以是系统状态数据(如服务器负载和CPU内存等)。消息队列数据、来自应用程序的时间序列数据或数据库中的其他时间序列数据。用户也可以将数据直接写入TsFile(本地或HDFS)。对于写入IoTDB和本地TsFile的数据,大家可以使用TsFileSync工具将TsFile同步到HDFS,从而在Hadoop或Spark数据处理平台上实现异常检测、机器学习等数据处理任务。对于写入HDFS或本地TsFile的数据,用户可以使用TsFile-Hadoop-Connector或TsFile-Spark-Connector来允许Hadoop或Spark处理数据。分析的结果可以用同样的方式写回TsFile。还有呢,IoTDB和TsFile提供了客户端工具,完全可以满足用户以SQL形式、脚本形式和图形形式编写和查看数据的各种需求。3.IoTDB的体系特征灵活部署IoTDB为用户提供了云上一键安装工具、一次解压即可使用的终端工具以及云平台与终端工具之间的桥梁工具(数据同步工具)。存储成本低IoTDB可以达到很高的磁盘存储压缩比,这意味着IoTDB可以用更少的硬件磁盘成本存储同样多的数据。高效的目录结构IoTDB支持来自智能网络设备的复杂时间序列数据结构的高效组织,来自同类设备的时间序列数据的组织,海量复杂时间序列数据目录的模糊搜索策略。高吞吐量读写IoTDB支持上百万低功耗设备的强连接数据访问,支持上面提到的智能联网设备和混合设备的高速数据读写。丰富的查询语义IoTDB支持跨设备和传感器的时间序列数据的时间对齐、时间序列域的计算(频域变换)和时间维度丰富的聚合函数支持。容易上手IoTDB支持类SQL语言、JDBC标准API和易于使用的导入/导出工具。自身和开源生态系统紧密集成IoTDB支持Hadoop、Spark等。分析生态系统和Grafana可视化工具。4.IoTDB的文件类型在IoTDB中呢,需要存储的数据种类繁多。现在我来给大家介绍IoTDB的数据存储策略,方便大家对IoTDB的数据管理有一个直观的了解。首先呢,IoTDB存储的数据分为三类,即数据文件、系统文件和预写日志文件。(1)数据文件数据文件存储用户写入IoTDB的所有数据,IoTDB包含TsFile和其他文件。TsFile存储目录可以用data_dirs来配置相关项目,其他文件通过其他特定的数据来配置项目。为了更好地支持用户的磁盘空间扩展等存储需求,IoTDB支持多种文件目录存储方式进行TsFile存储配置。用户可以将多个存储路径设置为数据存储位置,大家可以指定或自定义目录选择策略。(2)系统文件系统文件包括模式文件,模式文件存储IoTDB中数据的元数据信息。它可以通过配置base_dir配置项目。(3)预写日志文件预写日志文件存储WAL文件。它可以通过配置wal_dir配置项目。(4)设置数据存储目录的示例为了更清楚地理解配置数据存储目录,我在这给出一个示例。存储目录设置中涉及的所有数据目录路径有:base_dir、data_dirs、multi_dir_strategy、wal_dir,分别指系统文件、数据文件夹、存储策略、预写日志文件。配置项的示例如下:base_dir = $IOTDB_HOME/datadata_dirs = /data1/data, /data2/data, /data3/datamulti_dir_strategy=MaxDiskUsableSpaceFirstStrategywal_dir= $IOTDB_HOME/data/wal这段代码并不复杂,相信很多小伙伴都应该可以看懂,我在这里给大家简单说明一下下,设置以上配置后,系统将:将所有系统文件保存在$io TDB _ HOME/data中将TsFile保存在/data1/data、/data2/data、/data3/data中。选择策略是MaxDiskUsableSpaceFirstStrategy,即每次数据写入磁盘时,系统会自动选择剩余磁盘空间最大的目录来写入数据。将WAL数据保存在$IOTDB_HOME/data/wal中这次先为大家介绍到这,下次我再来给小伙伴们分享之前我自己的IoTDB学习经历~
  • [培训资料] 【华为云Stack ManageOne 集成对接】【视频】基础集成-消息推送
    video【华为云Stack ManageOne 集成对接】【视频】基础集成-消息推送
  • [应用安全] 【漏洞通告】Apache Tomcat 拒绝服务漏洞CVE-2022-29885
    漏洞名称:Apache Tomcat 拒绝服务漏洞组件名称:Apache Tomcat影响范围:未配置 EncryptInterceptor 则全版本受影响配置 EncryptInterceptor 如下版本受影响:10.1.0-M1 ≤ Apache Tomcat ≤ 10.1.0-M1410.0.0-M1 ≤ Apache Tomcat ≤10.0.209.0.13 ≤ Apache Tomcat ≤ 9.0.628.5.38 ≤Apache Tomcat ≤8.5.78漏洞类型:拒绝服务利用条件:1、用户认证:不需要用户认证2、前置条件:开启集群配置3、触发方式:远程综合评价:<综合评定利用难度>:未知。<综合评定威胁等级>:中危,能造成拒绝服务。漏洞分析:组件介绍:Apache Tomcat 是美国阿帕奇(Apache)软件基金会的一款轻量级 Web 应用服务器,该程序实现了对Servlet 和 JavaServer Page(JSP) 的支持。漏洞简介:2022年7月2日,监测到一则 Apache Tomcat 拒绝服务漏洞的信息,漏洞编号:CVE-2022-29885,漏洞威胁等级:中危。该漏洞是由于 Tomcat 开启集群配置中存在缺陷,攻击者可利用该漏洞在未权限的情况下,构造恶意数据造成拒绝服务,最终导致目标服务器拒绝服务。影响范围:目前受影响的 Apache Tomcat 版本:未配置EncryptInterceptor则全版本受影响配置EncryptInterceptor如下版本受影响:10.1.0-M1 ≤ Apache Tomcat ≤ 10.1.0-M1410.0.0-M1 ≤ Apache Tomcat ≤10.0.209.0.13 ≤ Apache Tomcat ≤ 9.0.628.5.38 ≤ Apache Tomcat ≤8.5.78解决方案:1.如何检测组件系统版本Windows 系统在 Tomcat 的 bin 目录下,输入 catalina version 命令即可显示版本信息。Linux 系统在 bin 目录下执行如下命令:bash version.sh  可显示版本信息。2.官方修复建议当前官方已发布最新版本,建议受影响的用户及时更新升级到最新版本。链接如下:https://tomcat.apache.org/security-10.htmlhttps://tomcat.apache.org/security-9.htmlhttps://tomcat.apache.org/security-8.html