Files
lingniu-vehicle-ingest/docs/ops/2026-07-20-daily-mileage-track-reconciliation.md
2026-07-20 07:30:04 +08:00

132 lines
13 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.
# 2026-07-20 日里程与轨迹里程核对
## 技术结论
沪A01559F 的 2026-07-19 日里程曾因统计恢复延迟缺失现已从持久化来源证据重建沪A62013F 的轨迹页展示了累计总里程,但 2026-07-19 没有可信移动证据0 km 是正确的自然日日里程。统计链路现已支持在仪表累计值停止刷新、但速度和坐标证明车辆实际移动时生成低优先级 GPS 估算候选,同时拒绝静止漂移、长间隔、乱序和不合理跳点。
## 事件范围
用户在跨自然日后反馈沪A01559F、沪A62013F“今日里程未计算但轨迹回放有里程”。核对按 `Asia/Shanghai` 自然日执行;由于反馈发生在 2026-07-20 00:00 之后,而车辆最后活动发生在前一日,本次事实窗口固定为 2026-07-19 00:00:00 至 2026-07-20 00:00:00。
“轨迹里程”是轨迹查询窗口内协议总里程差,协议总里程不可用时才使用经过质量过滤的坐标累计;“当日日里程”是同一车辆、协议、来源在上海时区自然日边界上的累计里程差。轨迹卡片中的“累计里程”只是某个点位携带的仪表总值,不等于当日日里程。
## 生产事实
| 车牌 | VIN | 轨迹事实 | 日里程结果 | 结论 |
| --- | --- | --- | --- | --- |
| 沪A01559F | `LMRKH9AC7R1004120` | 主来源 JT8082,793 个有效点;协议总里程差 769.1 km | 宇通 809 km、JT808 769.1 km宇通按来源优先级进入业务统计 | 当日曾存在统计恢复延迟,结果已恢复 |
| 沪A62013F | `LMRKH9AC9R1004099` | 宇通 520 个源点、519 个有效点;最高速度 0轨迹汇总 0 km | 宇通 0 km累计总里程 24,245 km | 0 km 正确;轨迹点展示的是累计总里程,不得补成正向日里程 |
沪A01559F 的 2026-07-19 最终日里程在 2026-07-20 00:32 恢复。沪A62013F 的宇通总里程事件时间仍为 2026-07-18 16:482026-07-19 只有静止位置证据,因此只能保留显式 0 km。
## 根因与修复
stat-writer 已支持在累计里程缺失时,用有速度证据的相邻 GPS 坐标生成低优先级日里程候选;但累计里程字段存在且持续重复时,流程会提前进入 `skipped_same_mileage`,没有执行 GPS 累计。这会影响“车辆真实移动、仪表累计值停止刷新”的 GB32960 或宇通来源。
修复后:
- 重复累计里程仍保留为 `skipped_same_mileage` 证据;
- GB32960、宇通只有在设备速度大于 0 且坐标有效时才进入 GPS 累计;
- GPS 状态仍按 10 秒节流,并拒绝超过 10 分钟、时间倒序或隐含速度超过 220 km/h 的线段;
- 低于 100 米的累计仅保留为内部状态,不生成业务日里程候选;
- 正向仪表累计里程优先于 GPS 估算,真实仪表值恢复后会自动覆盖估算;
- 静止车辆不会因 GPS 漂移产生虚假里程。
## 生产发布与回补验证
2026-07-20 02:31 发布 `mileage-track-reconcile-20260720023109`9 个数据链路服务全部通过 `/readyz`,容量巡检最终为 `status=ok`Kafka lag、消费重试队列和待处理消息均为 0。
发布后对 2026-07-17 至 2026-07-19 的 GB32960、JT808、YUTONG_MQTT 执行正式回补:
| 验证项 | 结果 |
| --- | ---: |
| 重建并写入的来源聚合 | 3,155 |
| 新增 GB32960 GPS 安全候选 | 2 |
| 新增 JT808 GPS 安全候选 | 66 |
| 新增宇通 GPS 安全候选 | 0 |
| 归一化平台来源 | 1,376 |
回补后沪A01559F 的 2026-07-19 结果稳定为宇通 809 km、JT808 769.1 km2026-07-20 在没有新移动证据时按静止结转明确写为 0 km。沪A62013F 的 2026-07-19 仍为宇通 0 km且没有生成 GPS 估算候选,证明 100 米阈值和速度证据门槛没有把约 12 米的静止定位偏差放大为业务里程。
同日全量诊断没有统计管道故障;另有 2 条与本事件无关的源数据缺口,分别为一台赛格 JT808 车辆和一台宇通车辆未上报可用总里程字段,已由诊断接口持续暴露,不能用猜测值补录。
## 同类数据审计与补录边界
生产 `stats-backfill` 对 2026-07-19 全部 19 台有宇通日活动的车辆执行只读扫描,未发现除现有正向仪表里程之外、可由有效移动线段恢复的 GPS 候选。沪A01559F 的结果已经恢复无需重复改写沪A62013F 缺少移动证据,禁止补录正数。
后续历史补录继续使用同一条安全规则:只有存在可用移动线段时才生成 `gps_coordinate_accumulation` 候选,不按累计总里程、位置点数量或页面展示值推断日里程。
2026-07-20 03:44 对当天三协议再次执行全量 dry-run共重建 448 个来源聚合,识别 5 个可由 JT808 有效移动轨迹恢复的候选03:48 正式回补写入 449 个来源聚合并归一化 272 个 JT808 平台来源。复核同时发现阈值规则上线前遗留的沪A56988F `0.004 km` GPS 候选,因此补充了“低于 100 米遗留候选清理 + 同事务重新投影”能力;后续回补会自动修复同类旧数据,而不是只阻止新漂移值写入。
03:56 新版本 `mileage-gps-candidate-reconcile-202607200350` 完成清理型正式回补:写入 452 个来源聚合,`subthresholdGPSCandidatesFound=1``subthresholdGPSCandidatesDeleted=1`。沪A56988F 当天阈值下候选及错误最终投影均已删除;剩余被选中的 GPS 候选最小值为 `0.131 km`,低于 `0.1 km` 的选中候选为 0。清理后该车显式暴露为“JT808 当日缺少新鲜总里程字段”的源数据缺口,统计管道缺口仍为 0系统保留该缺口不用 4 米静止漂移构造业务里程。
## 7 月 20 日 05:40 再次复核
针对“轨迹回放有里程、今日里程没有计算”的再次反馈,按 `2026-07-20 00:00:00``05:40:00` 重新核对生产轨迹、实时总里程证据、来源候选和最终日里程:
| 车牌 | 今日轨迹证据 | 今日统计 | 处理结论 |
| --- | --- | --- | --- |
| 沪A01559F | 宇通 260 个源点、259 个有效点;最高/平均速度均为 0坐标区间累计 0 km | 宇通 `stationary_carry_forward` 0 km仪表累计总里程 14,097 km 的最新证据仍是 7 月 19 日 21:23:59 | 已有显式 0 km 统计,无可信正向里程可补 |
| 沪A62013F | 今日 0 个源点7 月 19 日 520 个源点最高速度仍为 0区间里程 0 km | 7 月 19 日宇通 0 km累计总里程 24,245 km | 今日没有上报,昨日 0 km 正确,禁止把累计值补成日里程 |
同一时点全量诊断覆盖 480 个活跃“协议 × 车辆”项,`pipeline_issue_total=0`;仅有 1 个赛格 JT808 项缺少新鲜总里程,属于上游源数据问题,与这两辆车无关。轨迹页点位卡片同步将“累计里程”明确为“累计总里程”,并说明它不是所选时间窗里程或今日里程,避免把点位累计值误读为区间结果。
## 7 月 20 日 06:34 当天全量回补
再次收到相同车牌反馈后,按当天实时数据重新核对:
- 沪A01559F 今日 260 个源点、259 个有效点,轨迹区间里程、平均速度和最高速度均为 0宇通日里程已有 `stationary_carry_forward` 0 km。
- 沪A62013F 今日 271 个源点、259 个有效点,轨迹区间里程、平均速度和最高速度均为 0宇通日里程已有 `stationary_carry_forward` 0 km。
- 沪A01559F 的正向行驶发生在 7 月 19 日,宇通 809 km、JT808 769.1 km 均已存在沪A62013F 页面上的 24,245 km 是累计总里程,不是当日里程。
随后对 2026-07-20 的 GB32960、JT808、YUTONG_MQTT 执行全量 dry-run 和正式回补。正式运行重建并写入 642 个来源聚合,归一化 319 个 JT808 平台来源,没有宇通或 GB32960 GPS 降级候选,也没有低于 100 米的遗留漂移候选。4 个具备有效移动轨迹、但缺少正向设备累计里程的 JT808 来源按既有安全规则补录:
| 车牌 | VIN | 补录日里程 | 质量原因 |
| --- | --- | ---: | --- |
| 浙F02268F | `LA9HE60A6PBAF4022` | 0.119 km | `gps_coordinate_accumulation` |
| 沪A60339F | `LKLG7C4E8NA774750` | 29.199 km | `gps_coordinate_accumulation` |
| 沪A69311F | `LKLG7C4E8NA774781` | 21.253 km | `gps_coordinate_accumulation` |
| 沪A66218F | `LKLG7C4E9NA774773` | 0.545 km | `gps_coordinate_accumulation` |
回补后生产诊断覆盖 569 个活跃“协议 × 车辆”项GB32960 198/198 正常、JT808 324/325 正常、宇通 46/46 正常。唯一剩余项为沪A56988F 的赛格 JT808 当日没有新鲜总里程且缺少可用移动线段属于明确上游源数据缺口未构造里程。stat-writer `/readyz`、容量巡检均成功,三协议 Kafka lag 和重试队列均为 0。
## 7 月 20 日 06:53 插入事项复核
用户再次以沪A01559F、沪A62013F 为例要求排查“轨迹回放有里程、今日里程未计算”的同类问题。按相同的当天时间窗重新读取生产轨迹 API、最终日里程、来源候选和统计诊断
- 沪A01559F 的 260 个源点中有 259 个有效点,区间里程、平均速度和最高速度仍均为 0最终日里程为宇通 `stationary_carry_forward` 0 km累计总里程为 14,097 km。
- 沪A62013F 的 271 个源点中有 259 个有效点,区间里程、平均速度和最高速度仍均为 0最终日里程为宇通 `stationary_carry_forward` 0 km累计总里程为 24,245 km。
- 沪A01559F 的 769.1 km 来自 7 月 19 日 JT808 轨迹窗口沪A62013F 的 24,245 km 是轨迹点携带的累计总里程。两者都不能作为 7 月 20 日正向日里程补录。
随后再次对 2026-07-20 的三协议执行全量 dry-run 和正式幂等回补。dry-run 重建 667 个来源聚合,正式运行写入 671 个来源聚合、归一化 327 个 JT808 平台来源;正式运行识别 3 个可用的 JT808 GPS 降级聚合,没有低于 100 米的遗留候选。回补后已选中的 JT808 GPS 安全候选包括浙F02268F 0.119 km、浙F09860F 0.303 km、沪A60339F 30.624 km、沪A69311F 21.253 km粤A05579F 的设备累计里程随后恢复并以 1.2 km 正向仪表差值覆盖 GPS 估算。
全量诊断覆盖 580 个活跃“协议 × 车辆”项,`pipeline_issue_total=0`GB32960 204/204 正常、JT808 329/330 正常、宇通 46/46 正常。唯一剩余项仍是沪A56988F 的赛格 JT808 源数据缺口;容量巡检退出码为 0stat-writer、realtime-api、history-writer 及其 `/readyz` 均正常。
## 7 月 20 日 07:29 全量安全补录
再次以沪A01559F、沪A62013F 为样本核对当天轨迹与日里程:
- 沪A01559F 的轨迹接口完整读取 260 个源点、保留 259 个有效点,最高/平均速度和区间里程均为 0最终日里程保持宇通 `stationary_carry_forward` 0 km。
- 沪A62013F 的轨迹接口完整读取 271 个源点、保留 259 个有效点,最高/平均速度和区间里程均为 0最终日里程保持宇通 `stationary_carry_forward` 0 km。
- 页面可见的 14,097 km、24,245 km 分别是两车设备累计总里程,且最新累计里程证据分别停留在 7 月 19 日 21:23:59、7 月 18 日 16:48:10不能作为 7 月 20 日正向日里程补录。
随后对 2026-07-20 的 GB32960、JT808、YUTONG_MQTT 执行全量 dry-run 和正式幂等回补。正式运行重建并写入 702 个来源聚合,补齐 13 个宇通实时累计里程静止结转,生成 7 个被最终统计选中的 JT808 GPS 安全候选,归一化 335 个 JT808 平台来源;没有发现低于 100 米的遗留漂移候选:
| 车牌 | VIN | 最终日里程 | 质量原因 |
| --- | --- | ---: | --- |
| 浙F02268F | `LA9HE60A6PBAF4022` | 0.119 km | `gps_coordinate_accumulation` |
| 沪A66216F | `LKLG7C4E1NA774783` | 1.461 km | `gps_coordinate_accumulation` |
| 沪A69826F | `LKLG7C4E2NA774775` | 2.274 km | `gps_coordinate_accumulation` |
| 沪A01855F | `LKLG7C4E4SA827343` | 0.104 km | `gps_coordinate_accumulation` |
| 沪A35879F | `LKLG7C4E8NA774747` | 0.365 km | `gps_coordinate_accumulation` |
| 沪A60339F | `LKLG7C4E8NA774750` | 33.212 km | `gps_coordinate_accumulation` |
| 沪A69311F | `LKLG7C4E8NA774781` | 21.253 km | `gps_coordinate_accumulation` |
回补后全量诊断覆盖 608 个活跃“协议 × 车辆”项,`pipeline_issue_total=0`GB32960 217/217 正常、JT808 343/344 正常、宇通 47/47 正常。唯一剩余项为沪A56988F 的赛格 JT808 源数据缺口实时合并快照虽保留协议字段名但没有新鲜总里程事件时间也没有满足质量门槛的移动线段因此继续保留缺口不构造数值。history-writer、stat-writer、realtime-api 的 `/readyz` 均正常,容量巡检 `status=ok`,三协议全部 Kafka 分区 lag、stat 重试队列均为 0。
## 限制与后续监控
- GPS 估算只在仪表里程缺失或停滞时兜底,不替代 GB32960、宇通仪表里程或 JT808 设备里程。
- 超过 10 分钟的相邻点、时间倒序、隐含速度超过 220 km/h、非正速度的 GB32960/宇通点,以及不足 100 米的累计都不会形成业务候选。
- 每日巡检继续检查 `actionable_issue_total`、来源候选与最终投影差异、Kafka lag、重试队列和回补任务状态源头完全不提供里程且没有可信移动线段时系统必须保留缺口而不是构造数值。