背景

在物联网领域,时序数据库一直以来都能占据一席之地,得益于它提供的以时间序列为基础的数据结构,以及充分满足物联网实际应用场景的特性,如聚合分析、预警等。

简介

在公司车联网应用中,来自车机的数据因为考虑数据集的量级及扩展,会选用大数据+微服务结合的架构,其中数据处理引擎会使用大数据架构中的流式处理+批式处理两种方式,来满足业务的监控及分析需求,但随着国内车企纷纷入局车联网,对私有云的车联网系统需求越来越多,但往往搭建一套完整的大数据架构涉及太多组件,不便于快速搭建及维护,同时大数据架构中使用流式处理实时信息,使用批式处理离线信息,也越来越不能满足快速业务建立的需求,如建立一个流式处理业务,需要修改 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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐