Tdengine + MybatisPlus 实践
背景在物联网领域,时序数据库一直以来都能占据一席之地,得益于它提供的以时间序列为基础的数据结构,以及充分满足物联网实际应用场景的特性,如聚合分析、预警等。简介在公司车联网应用中,来自车机的数据因为考虑数据集的量级及扩展,会选用大数据+微服务结合的架构,其中数据处理引擎会使用大数据架构中的流式处理+批式处理两种方式,来满足业务的监控及分析需求,但随着国内车企纷纷入局车联网,对私有云的车联网系统需求越
背景
在物联网领域,时序数据库一直以来都能占据一席之地,得益于它提供的以时间序列为基础的数据结构,以及充分满足物联网实际应用场景的特性,如聚合分析、预警等。
简介
在公司车联网应用中,来自车机的数据因为考虑数据集的量级及扩展,会选用大数据+微服务结合的架构,其中数据处理引擎会使用大数据架构中的流式处理+批式处理两种方式,来满足业务的监控及分析需求,但随着国内车企纷纷入局车联网,对私有云的车联网系统需求越来越多,但往往搭建一套完整的大数据架构涉及太多组件,不便于快速搭建及维护,同时大数据架构中使用流式处理实时信息,使用批式处理离线信息,也越来越不能满足快速业务建立的需求,如建立一个流式处理业务,需要修改 flink 或 spark streaming 脚本,再部署,开发成本较高,如果通过 flink sql 或 spark streaming sql 脚本配置的方式,对 flink 和 spark 二次开发的成本也较高。
Tdengine
选用 tdengine 作为实时流式处理和批式离线处理的替代,替代其中指标计算,时序统计的功能,既能满足业务快速迭代要求,也可以将大部分原来大数据架构中做的计算卸载到 tdengine 上,节省大量开发及运维成本。
Tdengine + MybatisPlus
Tdengine 支持 SQL 语法,Mybatis 因其简单易用的 API,同 tdengine 结合,如虎添翼。
超级表
超级表是 tdengine 提供的可复用的表结构,普通表可以使用超级表的结构,而不用另外定义一次结构,超级表和普通表,是1对多的关系,1个超级表可以有多个子表,每个子表可以代表一个特定的设备或特定数据集的数据,子表名称上可以带有特定标识,标识其唯一性,一般子表结构分为:时间戳、指标列、tag 列,而 tag 一般只放可枚举的值,具有唯一性的标识需要放在子表的表名中。
定义超级表
定义 drive_motor_state 超级表,表示驱动电机状态指标结构,由时间戳 ts ,以及指标,tag 组成,其中 tag 默认随意指定一个(tdengine 要求至少有一个 tag)。
drop stable drive_motor_state;
create stable drive_motor_state (
ts timestamp,
drive_motor_power binary(20),
controller_temperature smallint,
drive_motor_speed int,
drive_motor_torque double,
drive_motor_temperature smallint,
controller_input_voltage double,
dc_bus_current_of_controller double
) tags (
country binary(2)
);
定义 Mapping 文件
Mapping 表定义了子表的写入,子表名由表名+vin码+序列号组成 drive_motor_state_#{vin}_#{serialNumber} ,用关键字 using 指明超级表名,第一列使用时间戳,tag 给一个默认值。语法和 MySQL 的语法稍许有些差别,但 Mybatis 的模板引擎不影响,tdengine 的 insert 语句可以完全被定义出来,甚至表名也可以动态化。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.dao.mapper.DriveMotorStateMapper">
<!--通用查询映射结果-->
<resultMap id="BaseResultMap" type="com.xxx.entity.DriveMotorState">
<result column="vin" property="vin"/>
<result column="serial_number" property="serialNumber"/>
<result column="ts" property="ts"/>
<result column="drive_motor_power" property="driveMotorPower"/>
<result column="controller_temperature" property="controllerTemperature"/>
<result column="drive_motor_speed" property="driveMotorSpeed"/>
<result column="drive_motor_torque" property="driveMotorTorque"/>
<result column="drive_motor_temperature" property="driveMotorTemperature"/>
<result column="controller_input_voltage" property="controllerInputVoltage"/>
<result column="dc_bus_current_of_controller" property="dcBusCurrentOfController"/>
</resultMap>
<!--通用查询结果列-->
<sql id="Base_Column_List">
` vin`,` serial_number`,` ts`,` drive_motor_power`,` controller_temperature`,` drive_motor_speed`,` drive_motor_torque`,` drive_motor_temperature`,` controller_input_voltage`,` dc_bus_current_of_controller`
</sql>
<insert id="insert">
insert into drive_motor_state_#{vin}_#{serialNumber}
using drive_motor_state (country) tags ('cn')
(
`ts`,
`drive_motor_power`,
`controller_temperature`,
`drive_motor_speed`,
`drive_motor_torque`,
`drive_motor_temperature`,
`controller_input_voltage`,
`dc_bus_current_of_controller`
)
values
(
#{ts},
#{driveMotorPower},
#{controllerTemperature},
#{driveMotorSpeed},
#{driveMotorTorque},
#{driveMotorTemperature},
#{controllerInputVoltage},
#{dcBusCurrentOfController}
)
</insert>
</mapper>
定义 Entity
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("drive_motor_state")
@ApiModel(value="DriveMotorState对象", description="超级表:驱动电机数据, 表名:drive_motor_state_{vin}_{serialNumber}, 说明:VIN 码 + 驱动电机序号 1~253")
public class DriveMotorState extends Model<DriveMotorState> {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = " Tdengine:STableKey;")
private String vin;
@ApiModelProperty(value = " Tdengine:STableKey;")
private Integer serialNumber;
@ApiModelProperty(value = "时间戳; Tdengine:Timestamp;")
private Long ts;
@ApiModelProperty(value = "驱动电机总成数据: 驱动电机状态,0x01:耗电;0x02:发电;0x03:关闭状态;0x04:准备状态“0xFE”表示异常,“0xFF”表示无效; DTO:String;")
private String driveMotorPower;
@ApiModelProperty(value = "驱动电机总成数据: 驱动电机控制器温度,有效值范围:0~250(数值偏移量40℃,表示-40℃~+210℃),最小计量单元:1℃,“0xFE”表示异常,“0xFF”表示无效; DTO:String;")
private Integer controllerTemperature;
@ApiModelProperty(value = "驱动电机总成数据: 驱动电机转速,有效值范围:0~65531(数值偏移量20000表示-20000r/min~45531r/min),最小计量单元:1r/min,“0xFF,0xFE”表示异常,“0xFF,0xFF”表示无效; DTO:String;")
private Integer driveMotorSpeed;
@ApiModelProperty(value = "驱动电机总成数据: 驱动电机转矩,有效值范围:0~65531(数值偏移量20000表示-2000N·m~4553.1N·m),最小计量单元:0.1N·m,“0xFF,0xFE”表示异常,“0xFF,0xFF”表示无效; DTO:String;")
private Double driveMotorTorque;
@ApiModelProperty(value = "驱动电机总成数据: 驱动电机温度,有效值范围:0~250(数值偏移量40℃,表示-40℃~+210℃),最小计量单元:1℃,“0xFE”表示异常,“0xFF”表示无效; DTO:String;")
private Integer driveMotorTemperature;
@ApiModelProperty(value = "驱动电机总成数据: 电机控制器输入电压,有效值范围:0~60000(表示0V~6000V),最小计量单元:0.1V,“0xFF,0xFE”表示异常,“0xFF,0xFF”表示无效; DTO:String;")
private Double controllerInputVoltage;
@ApiModelProperty(value = "驱动电机总成数据: 电机控制器直流母线电流,有效值范围:0~20000(数值偏移量1000A,表示-1000A~+1000A),最小计量单元:0.1A,“0xFF,0xFE”表示异常,“0xFF,0xFF”表示无效; DTO:String;")
private Double dcBusCurrentOfController;
@Override
protected Serializable pkVal() {
return null;
}
}
定义 Mapper 类
public interface DriveMotorStateMapper extends BaseMapper<DriveMotorState> {
}
调用 Mapper 类
DriveMotorState driveMotorState = MapStruct.M.toDriveMotorState(gb32960DriveMotorDto);
driveMotorState.setVin(vin);
driveMotorState.setSerialNumber(Integer.valueOf(gb32960DriveMotorDto.getSn()));
driveMotorState.setTs(timestamp);
driveMotorStateMapper.insert(driveMotorState);
Next Engine·翌擎科技成立于2016年11月,是国内在汽车产业互联网领域发展迅猛的软件企业之一。2019年12月,公司获得腾讯A轮投资,成为腾讯在汽车与出行领域的重要生态合作伙伴之一。2021年,公司再次获得兴富资本数千万元B1轮融资。
翌擎科技沪蓉研发团队招聘
Java开发工程师(上海)
Web开发工程师(上海)
简历投递
邮箱:yu.dong@nx-engine.com
更多推荐
所有评论(0)