16 KiB
车辆数据中台一期数据模型
1. 数据职责原则
| 存储 | 负责 | 不负责 |
|---|---|---|
| Redis DB 50 | 最新状态、在线 TTL、字段级当前值、热查询缓存 | 历史事实、告警事件、规则、导出任务 |
TDengine lingniu_vehicle_ts |
高频 RAW 证据、位置/稳定时序历史 | 车辆档案、权限、工作流状态 |
MySQL lingniu_vehicle_data |
车辆主数据、身份映射、接入配置、当前业务投影、统计、规则、事件、通知、导出任务 | 每帧完整历史和无限增长的遥测明细 |
统一业务主键为 VIN。车牌、JT808 手机号、设备号、平台标识只是可变标识,通过映射解析到 VIN;无法解析 VIN 的数据仍留 RAW/接入排障,不进入正式车辆统计。
2. 当前 TDengine 模型
2.1 raw_frames stable
列:ts, frame_id, event_id, message_id, event_time, received_at, raw_size_bytes, raw_hex, raw_text, parsed_json, parse_status, parse_error, source_endpoint。
Tags:protocol, vehicle_key, vin, phone, device_id。
用途:证明收到什么、何时收到、解析成什么。parsed_json 物理列保存 Gateway 已一次扁平化的 parsed_fields,是动态协议字段的历史证据。新字段默认先进入这里,不为每个厂家字段立即新增物理列。
2.2 raw_frame_payload_chunks stable
列:事件/帧、接收时间、payload 类型、分片序号/总数、分片文本;Tags 与 RAW 身份类似。
用途:保存超过主表列长度的 raw/parsed payload,不参与常规业务查询。
2.3 vehicle_locations stable
列:ts, event_id, received_at, longitude, latitude, altitude_m, speed_kmh, direction_deg, alarm_flag, status_flag, total_mileage_km。
Tags:protocol, vin。
用途:VIN 非空车辆的高频位置、速度、方向、告警/状态位、总里程历史。当前平台 DTO 尚未完整透出方向、告警和状态位,也没有 SOC 列;轨迹一期需先补 DTO/查询,SOC 可从 RAW 指标取值或按验证后的需求物化。
数据库当前配置 KEEP 7300 DURATION 10 BUFFER 256。保留期和磁盘容量应纳入运维监控,不在业务页面查询时临时改变。
3. 当前 Redis 模型
| Key | 值/用途 | 约束 |
|---|---|---|
vehicle:latest:{vin} |
跨协议最新核心字段 | 仅 VIN 非空;轻量快照 |
vehicle:latest:{vin}:{protocol} |
单协议最新核心字段 | 可过期/重建 |
vehicle:realtime-raw:{protocol}:{vin} |
单协议最新完整 parsed 状态 | Redis 中完整协议字段唯一副本 |
vehicle:rt-kv:{protocol}:{vin}:values |
扁平字段当前值 | 与类型/时间/meta 配套 |
...:types |
字段值类型 | 支持动态展示和规则类型校验的实时侧依据 |
...:times |
每字段最新归一事件时间 | 防止乱序旧帧覆盖 |
...:meta |
最新事件/接收时间、映射版本 | 用于新鲜度和追踪 |
vehicle:online:{protocol}:{vin} |
TTL 在线状态 | 在线事实的快速判断,不应永久保存 |
vehicle:online-state:{protocol}:{vin} |
可分页的 Hash 副本 | 用于在线列表 |
vehicle:protocols:{vin} |
最近出现协议集合 | 车辆来源发现 |
vehicle:last_seen |
最近活跃车辆 ZSET | 分页/排序候选 |
生产只允许 nats-fast-writer 写 Redis 当前态;Kafka 慢链路的 realtime writer 不应覆盖快路径。在线产品状态应由“最新时间 + 配置阈值”计算并返回阈值/依据,不能只信一个固定 Boolean。
4. 当前 MySQL 模型
4.1 身份与档案
| 表 | 主键/关键字段 | 用途 |
|---|---|---|
vehicle |
vin;plate, oem, enabled, updated_at |
轻量车辆主实体;当前字段不足一期完整档案 |
vehicle_identifier |
(protocol, source_code, identifier_type, identifier_value);VIN/车牌/OEM |
多协议、多来源、多标识解析到 VIN |
vehicle_identity_binding |
VIN;车牌、phone、OEM | 外部维护的兼容映射事实,运行期只读 |
jt808_registration |
phone;device、plate、VIN、厂家、鉴权、来源、首次/最近注册鉴权/出现时间 |
JT808 注册鉴权与绑定证据 |
4.2 当前态与来源
| 表 | 主键/关键字段 | 用途 |
|---|---|---|
vehicle_realtime_snapshot |
(protocol, vin);plate、platform、peer、扁平 parsed_json、event/received time |
每协议每 VIN 最新合并遥测快照 |
vehicle_realtime_location |
(protocol, vin);经纬度、速度、总里程、SOC、海拔、方向、alarm/status、event/received time |
每协议每 VIN 最新位置业务缓存 |
vehicle_data_source |
自增 ID,唯一 (protocol, source_ip);source code/kind、platform、priority、enabled、first/latest seen |
数据来源配置和可信源选择 |
4.3 日里程
| 表 | 主键/关键字段 | 用途 |
|---|---|---|
vehicle_daily_mileage_source |
(vin, stat_date, protocol, source_key);首末里程、样本、质量、是否选中 |
多来源日里程事实和质量解释 |
vehicle_daily_mileage |
(vin, stat_date, protocol);source ID、日里程、最新总里程 |
对外查询结果投影 |
当前明确不存在/不应恢复的旧模型包括泛化 vehicle_daily_metric、TDengine vehicle_mileage_points 和 raw_frames.fields_json 重复列。
5. 一期统一领域模型
5.1 车辆标识
VehicleId = VIN(内部规范化大写、去空格)
VehicleIdentifier = protocol + sourceCode + type + value -> VIN
Plate = 可变展示标识,不作为跨表唯一主键
Source = protocol + sourceCode/sourceId + endpoint
所有 API 都以 VIN 作为详情路径主键;搜索接口可接受车牌、VIN、车辆编号/手机号并返回解析结果。多协议数据保留 protocol 和 sourceId 做归因,不能在合并时丢失来源。
5.2 时间模型
eventTime:车端/协议事件时间,是轨迹、曲线和告警判断的主要时间。receivedAt:平台接收时间,用于延迟、迟到数据和链路健康。storedAt/updatedAt:投影或业务记录更新时间,不冒充车辆上报时间。dataDelaySec = receivedAt - eventTime;silenceSec = now - max(receivedAt/eventTime 的已确认口径)。
5.3 在线状态
never_reported: 无任何 latestReceivedAt
online: silenceSec <= thresholdSec
offline: silenceSec > thresholdSec
unknown: 时间非法、未来时间过大或来源状态无法判断
行驶/静止是独立 motion 状态,建议以速度阈值 + 最近更新时间判断;告警也是独立状态。不要把 online/running/alarm 压成一个互斥枚举,UI 可基于多维状态决定主色和徽标。
5.4 指标值
MetricValue {
vehicleId, metricKey, value, valueType, unit,
eventTime, receivedAt, protocol, sourceId,
quality, mappingVersion
}
metricKey 是协议无关的规范键;协议原字段通过映射表关联。厂家扩展字段允许命名空间,但必须有显示名、类型、分类和单位后才可进入图表/告警。
6. 建议新增 MySQL 模型
6.1 档案与组织
建议优先用关联表而非不断扩宽 vehicle:
vehicle_profile(vin PK, vehicle_no, model_id, vehicle_type, company_id, operation_status, access_vendor_id, first_access_at, ...)vehicle_model(id, oem_id, code, name, vehicle_type, ...)organization(id, parent_id, type, code, name, enabled, ...)access_vendor(id, code, name, enabled, ...)
外部主数据通过受控同步写入 source_system/source_version/synced_at。默认策略保护 manual 和其他外部来源;只有管理员显式选择 takeover 才能改变所有权。同一来源版本相同载荷幂等,不同载荷冲突,避免上游版本不可变性被破坏;每次创建/更新都进入 vehicle_profile_audit。
6.2 指标目录
metric_definition(metric_key PK, display_name, category, value_type, unit, precision, chartable, alertable, enabled, sort_order, version)metric_protocol_mapping(metric_key, protocol, source_field, transform, mapping_version, enabled)
transform 不能存任意可执行代码;使用有限转换类型或由版本化 Go 映射实现。目录服务可缓存,变更有版本和审计。
6.3 告警域
alert_rule(id, name, description, metric_key, operator, threshold_json, severity, duration_sec, recovery_json, repeat_interval_sec, enabled, version, created_by, updated_by, timestamps)alert_rule_scope(rule_id, scope_type, scope_value):vehicle/model/oem/protocol/company;一期可限制组合复杂度。alert_event(id, rule_id, rule_version, vin, protocol, source_id, status, trigger_value_json, threshold_json, first_triggered_at, last_triggered_at, recovered_at, closed_at, location_json, dedupe_key, assignee, timestamps)alert_event_action(id, event_id, action, from_status, to_status, operator_id, note, created_at)notification(id, user_id, event_id, title, body, read_at, created_at)
alert_event.dedupe_key 建唯一约束或等价幂等机制;阈值快照和 rule version 必须保存在事件上,避免规则修改后历史无法解释。
当前实现使用带业务前缀的实体表,完整 DDL 位于 vehicle-data-platform/deploy/migrations/002_alert_center.sql:
vehicle_alert_rule+vehicle_alert_rule_audit:当前规则与每版本不可变快照。vehicle_alert_candidate:(rule_id, vin, protocol)持续命中计时,避免单帧达到阈值就误开事件。vehicle_alert_stream_checkpoint:(consumer_group, topic, partition_id)保存数据库权威next_offset、Kafka high watermark、处理/非法/迟到/回放计数、最近事件证据以及最近非法代码/时间。流 worker 先提交该事务,再提交 Kafka group offset;崩溃后重复抓取的 offset 会被数据库 checkpoint 跳过。累计非法数用于审计,健康状态只对五分钟内仍在发生的非法消息告警。vehicle_alert_event:保存规则名/版本、触发阈值快照、证据时间、位置和乐观锁版本;fingerprint + active status用于评估器幂等检查。vehicle_alert_event_action:触发、恢复和人工处置的不可变时间线。vehicle_alert_notification:站内通知真实已读状态;外部通道只有reserved,没有配置供应商时绝不标记sent。vehicle_alert_rule_state:为 Booleanchanged规则保存每个 rule/VIN/protocol 的最近观测值;003同时增加区间上限和 OEM 范围,004为 fingerprint 重复间隔查询增加索引。
一期 evaluator 读取 vehicle_realtime_location 的当前快照并用 candidate 表证明持续时长。除 freshness_sec 明确按平台墙钟增长外,候选只允许由不同 source_event_id 且事件时间不回退的新观测推进;重复快照不能制造持续时长,迟到观测不能回退 candidate 或 Boolean 状态。规则行会在评估事务内加锁,停用规则、清理 candidate/Boolean 状态和写版本审计在同一事务提交,从而避免 evaluator 与管理员停用并发后留下幽灵候选。它仍不是 Kafka event-time 可重放评估器,因此跨当前快照的迟到数据重算、历史窗口规则和消费 offset 仍是阶段 8 的后续能力。
alert-stream-evaluator 已以 active 模式消费三类 canonical fields topic。它复用 Kafka consumer group 的分区顺序,校验 event_kind/field_mapping/protocol/VIN/source_event_id/字段命名空间,用接收时间识别超过可配置窗口的迟到观测。动态规则锁、当前批次范围内的 candidate/Boolean/活跃事件/重复窗口、事件/动作/通知副作用和 checkpoint 在同一个 MySQL 事务内完成,成功后才 commit Kafka;数据库 ahead 时的重复 offset 由 checkpoint 跳过。超过迟到窗口的观测只允许驱动 data_delay_sec,不能开关速度/SOC/告警位事件。快照 evaluator 在 active 模式只负责按墙钟增长的 freshness_sec,不再读取动态规则。
6.4 导出域
export_job(id, user_id, type, format, query_json, status, progress, estimated_rows, exported_rows, file_uri, file_size, checksum, error_code, error_message, started_at, completed_at, expires_at, created_at)
索引至少覆盖 (user_id, created_at)、(status, created_at) 和过期清理。query_json 保存规范化查询快照,不保存数据库密码或签名下载 URL。
6.5 在线阈值与审计
online_threshold(scope_type, scope_value, threshold_sec, version, updated_by, updated_at),一期建议 scope 仅 global/protocol。audit_log(id, actor, action, resource_type, resource_id, before_json, after_json, trace_id, created_at)。
当前 V2 接入管理已先落地等价的窄表:
vehicle_access_threshold_config(id=1, version, default_threshold_sec, delay_threshold_sec, long_offline_sec, protocol_overrides_json, updated_by, updated_at)。vehicle_access_threshold_audit(id, version, actor, summary, config_json, changed_at)。
表仅向前新增,不改变 gateway 的 vehicle_realtime_snapshot(protocol, vin) 主键与写入语义。后续统一审计域上线时可迁移到通用 audit_log,但必须保留版本历史。
7. 查询与物化策略
- 实时页面优先 Redis,MySQL realtime 作为业务查询/降级投影;返回值统一由 BFF 归一化。
- 轨迹只查 TDengine
vehicle_locations,必要的 SOC/告警补充应避免对每个点逐条回查 RAW;先验证是否需要将 SOC 提升为位置列或建立专用指标 stable。 - 通用历史指标首版可从
raw_frames.parsed_json按白名单提取,但必须限制车辆数、指标数、时间范围并做基准;高频稳定指标按实际查询热度物化为专用时序模型。 - 档案和字典在 BFF/Redis 做版本化短缓存,避免每次实时请求重复查不变数据。
- 地图聚合可从 MySQL realtime/Redis 快照构建短周期服务端缓存;不要把地理历史查询压到实时表,也不要把全量点放浏览器聚合。
- 告警 worker 使用 Kafka 可重放流和 eventTime,MySQL 保存工作流事实;Redis 可保存短期去重/规则缓存但不是唯一事实。
8. 数据质量与治理要求
- 数值同时记录单位和精度;未知单位不得参与跨协议比较或规则判断。
- 原始值、规范值和转换版本可追踪;异常值标记不直接篡改 RAW。
- 未来时间、经纬度越界、速度突变、里程回退、重复事件均定义质量码。
- 轨迹过滤返回算法版本、原始/过滤/抽稀数量,可选择查看未过滤证据。
- 协议新增字段先进入扁平 RAW + Redis KV,经目录登记后才进入 UI;形成稳定高频查询后再物化。
- 所有新增表、字段、索引、保留期和清理任务随 migration 与数据字典发布。
9. 容量和保留
- 约 1,000 到 10,000 车辆、5~30 秒上报意味着时序写入持续增长;TDengine 查询必须带 VIN/时间,禁止开放无界扫描。
- RAW 保留期、位置保留期、导出文件保留期和告警/审计保留期分别配置,不能共用一个默认值。
- MySQL 告警事件和审计按时间索引并规划归档;导出任务定时过期,文件删除和 DB 状态更新需幂等。
- 单 ECS 上告警和导出 worker 设置独立并发、内存、CPU 和 systemd 限制,避免影响接入写链路。
10. 仍需确认的数据问题
vehicle_identity_binding的实际 DDL、权威维护方和未来是否继续兼容。- 车型、车辆类型、运营公司、车辆编号、运营状态、接入厂家的权威来源与更新频率。
- 各协议 SOC、方向、启动、告警等级、电机/燃料电池等规范字段映射和单位。
- “累计运行时长”是已有车端字段、由状态积分计算,还是一期可不提供。
- 在线时间基准使用 eventTime 还是 receivedAt,以及不同协议的默认阈值。
- 轨迹停车阈值、漂移判定、迟到点容忍和跨协议主轨迹选择规则。
- 导出存储与保留期、单用户并发/最大行数。
- 告警规则适用范围组合、迟到窗口、重复/恢复语义和事件归属人规则。