Files
lingniu-vehicle-ingest/docs/architecture/storage-minimal-contract.md
2026-07-02 19:47:32 +08:00

71 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 车辆数据最小落库合约
## 目标
车辆接入系统只持久化能回答业务问题、能回放纠错、能支撑高频查询的数据。协议细节默认保存在 raw不向上层业务表扩散。
## 第一性原则
1. raw 是证据层,必须能证明收到过什么、解析成什么。
2. Kafka 是回放层,消费者失败后优先靠 Kafka lag 追平。
3. Redis 是当前态缓存,不是历史库。
4. TDengine 只承担高写入时间序列raw、位置历史。
5. MySQL 只承担低基数业务状态:身份映射、实时快照、日指标。
6. 同一个事实只落一个主表,其他表只存查询必要的投影。
7. 新字段先进入 `parsed_json`,只有稳定查询需求出现后才提升为列。
## 目标表边界
| 存储 | 表/Key | 保留内容 | 不保留内容 |
| --- | --- | --- | --- |
| TDengine | `raw_frames` | raw hex/text、完整 `parsed_json`、解析状态、协议标签、车辆标识标签 | `fields_json` 这类可从 `parsed_json`/业务表再得到的重复字段 |
| TDengine | `raw_frame_payload_chunks` | 超长 raw/parsed payload 分片 | 业务查询字段 |
| TDengine | `vehicle_locations` | 时间、VIN/协议标签、经纬度、速度、方向、SOC、总里程等位置核心字段 | 完整协议 JSON、注册鉴权信息 |
| MySQL | `vehicle_realtime_snapshot` | 每个协议+VIN 的最新事件时间、接收时间、车牌、事件 ID | phone、device、source endpoint、完整 JSON |
| MySQL | `vehicle_realtime_location` | 每个协议+VIN 的最新位置核心字段 | raw、parsed JSON、消息头内部字段 |
| MySQL | `vehicle_daily_metric` | 日期、VIN/临时 vehicle key、协议、指标名、指标值、首末总里程、样本数 | 每帧细节、位置点列表 |
| MySQL | `vehicle_identity_binding` | 人工维护或导入的 VIN、车牌、phone、device_id 映射 | 注册历史 |
| MySQL | `jt808_registration` | JT808 phone 主键下的注册、鉴权、VIN 匹配状态 | GB32960/MQTT 注册信息 |
| Redis | `vehicle:realtime-raw:{protocol}:{vin}` | 每协议最新完整 parsed 状态 | 历史数据、统计结果 |
## 当前应收敛的重复点
1. `vehicle_mileage_points``vehicle_locations.total_mileage_km` 重复。
- 状态Go 写入链路已停止创建和写入 `vehicle_mileage_points`
- 兼容:`/api/history/mileage-points` 已改为从 `vehicle_locations` 读取 `total_mileage_km IS NOT NULL`
- 删除:确认线上无直接读表后,再删除 TDengine stable 和子表。
2. `raw_frames.fields_json``raw_frames.parsed_json``vehicle_locations` 重复。
- 状态:新建 raw schema 和 raw 写入已停止使用 `fields_json`
- 兼容raw 查询只选择公共列,不依赖 `fields_json`;旧表保留该列也不影响查询。
- 删除:等历史查询和前端不再展示 `fields_json` 后删除列。
3. `vehicle_daily_metric``vehicle_key``vin` 同时存在。
- 当前保留原因JT808 可能先用 phone 作为临时 key后续才绑定 VIN。
- 收敛方向:业务查询以 VIN 为主;没有 VIN 的数据只用于排查和待绑定,不作为正式车辆指标。
## 字段提升规则
协议字段进入系统后分三层:
1. `parsed_json`:默认入口,保存完整结构化解析。
2. 核心列只有跨协议稳定查询需要时才提升例如经纬度、速度、SOC、总里程。
3. 指标表:只有聚合口径稳定、产品需要分页/排序/报表时才持久化。
反例:
- 不因为某个协议字段存在就增加 MySQL 列。
- 不为了方便调试在 snapshot/location 放完整 JSON。
- 不为 telemetry field 配置服务提前复制一份字段表;字段配置服务应从 raw/Kafka 回放生成自己的结果。
## 删除或迁移顺序
1. 先写测试证明旧 API 能从新主表读到同等结果。
2. 改代码停止写重复表或重复列。
3. 部署后观察 Kafka lag、writer 成功计数、API 结果。
4. 查询生产库确认旧表不再新增。
5. 做一次备份或导出。
6. 删除旧表或旧列。
任何一步无法证明安全,就停在兼容状态,不直接删生产数据。