1. 为什么我们需要TDengine+MySQL的混合架构?
如果你正在开发一个物联网项目,比如智能工厂的设备监控、智慧农业的传感器网络,或者车联网的数据平台,那你肯定遇到过这个头疼的问题:数据量太大了,而且长得还不太一样。我做了这么多年物联网项目,发现大家最纠结的就是怎么存数据、怎么查数据。业务数据,比如用户信息、设备档案、订单记录,用MySQL这种关系型数据库来存,那是天经地义,增删改查都方便,事务支持也好。但那些源源不断涌进来的传感器数据,温度、湿度、位置、电压,每秒可能产生成千上万条,而且主要是写和查,很少去改和删,这种数据塞进MySQL,时间一长,单表几千万甚至上亿条,查个当天的数据都要等好几秒,系统能不卡吗?
我见过一个真实的案例,一个环境监测系统,几千个传感器每分钟上报一次数据。一年下来,MySQL里一张表就堆了二十多亿条记录。前端页面想查某个设备最近24小时的数据曲线,那个查询进度条转得人心慌,用户体验极差。更别提那种需要跨设备、跨时间范围做聚合分析的场景了,数据库服务器CPU直接飙满,搞不好整个服务都挂掉。这时候,时序数据库(TSDB)的优势就体现出来了。TDengine就是专门为这种场景设计的,它用“一个设备一张表”或者“一类设备一张表”的超级表模型,把数据按时间和设备天然地分区存储。查询时,它可以直接定位到具体设备的子表,效率极高,面对海量时间序列数据,查询速度能比MySQL快几十甚至上百倍。
但是,我们不可能把所有的数据都搬到TDengine里。用户管理、权限配置、设备元信息这些强关联、需要复杂事务的业务数据,还是得放在MySQL里。这就带来了一个很现实的需求:我们的Java应用,也就是那个SpringBoot服务,需要同时连接两个数据库,并且能根据业务逻辑,灵活地从不同的库里去读写数据。你可能会想,那我启动两个服务,一个连MySQL,一个连TDengine,不就行了?理论上可以,但在资源紧张的服务器上(比如很多小公司用的2核4G或4核8G的云服务器),跑两个Java应用,内存占用翻倍,部署和维护成本也上去了。最经济、最优雅的方案,就是在一个SpringBoot应用里,通过配置多数据源,同时驾驭MySQL和TDengine。这就是我们今天要聊的实战方案的核心价值:用一套代码,一个服务进程,搞定两种截然不同的数据库,让它们各司其职,发挥最大效能。
2. 项目搭建与环境准备
2.1 依赖引入与关键配置
万事开头难,我们先从项目的“地基”——pom.xml开始。这里面的依赖项一个都不能错,特别是TDengine的JDBC驱动,版本要对得上你的TDengine服务端。
<dependencies>
<!-- SpringBoot Web基础 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Mybatis整合SpringBoot -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version> <!-- 注意版本与SpringBoot匹配 -->
</dependency>
<!-- 分页神器PageHelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
<!-- TDengine官方JDBC驱动 -->
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>3.2.8</version> <!-- 请务必与服务器版本一致 -->
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 数据库连接池(这里用HikariCP,SpringBoot默认) -->
<!-- 如果想用Druid,可以引入下面的依赖并调整配置 -->
<!--
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
这里有个小坑我踩过:TDengine的JDBC驱动版本(比如3.2.8)一定要和服务器上安装的TDengine版本兼容。如果不确定,可以去TDengine的官方GitHub仓库查看版本对应关系。用错了版本,连接的时候会报一些莫名其妙的错误。
接下来是application.yml(我喜欢用yml,比properties更清晰)。这里我们要配置两套数据源,分别指向MySQL和TDengine。
server:
port: 8080
spring:
datasource:
# MySQL 数据源配置
mysql:
jdbc-url: jdbc:mysql://你的MySQL地址:3306/你的业务数据库?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: 你的用户名
password: 你的密码
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
connection-timeout: 30000
maximum-pool-size: 10
minimum-idle: 5
# TDengine 数据源配置
taos:
jdbc-url: jdbc:TAOS://你的TDengine地址:6030/你的时序数据库?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8
username: root
password: taosdata # 默认密码,生产环境一定要改!
driver-class-name: com.taosdata.jdbc.TSDBDriver
hikari:
connection-timeout: 30000
maximum-pool-size: 15 # TDengine查询可能更频繁,连接池可以稍大
minimum-idle: 5
# MyBatis配置
mybatis:
# 注意:这里配置的type-aliases-package和mapper-locations是全局默认的。
# 在多数据源场景下,我们通常会在各自的配置类里单独指定,所以这里可以不配,或者配一个公共的。
# 如果配置了,要确保不会引起冲突。
type-aliases-package: com.yourdomain.data.domain
configuration:
map-underscore-to-camel-case: true # 下划线转驼峰,强烈建议开启
# PageHelper分页插件配置
pagehelper:
helper-dialect: mysql # 默认方言,对于TDengine的分页需要特殊处理,后面会讲
reasonable: true
support-methods-arguments: tr


264

被折叠的 条评论
为什么被折叠?



