# 开源机场运营数据库(AODB)高层设计文档 ## 1. 文档目标 本文档定义 AODB MVP 的技术方案基线,重点回答以下问题: 1. AODB 在 MVP 内承载哪些业务闭环,以及哪些能力明确不做。 2. 系统如何划分聚合、服务、数据流和事件边界。 3. 航班、里程碑、资源、告警等核心对象如何建模。 4. 发布事实如何在观测、裁决、审计和订阅之间保持一致。 5. 查询、订阅、部署、容灾和可观测性如何落到可实现架构。 适用范围:年旅客吞吐量 500 万至 3000 万机场,优先支持单机场部署。 ## 2. 设计原则 - 单一事实源:AODB 对外发布单一当前权威事实,不暴露“谁最后写入”式伪一致。 - 事实分层:原始观测、裁决记录、发布事实必须分层建模。 - 写主清晰:每个核心聚合只允许一个服务写入,避免跨服务共享可变状态。 - 事件驱动:状态变化通过事件传播,系统通过契约解耦。 - 规则可解释:字段权威、冲突裁决、人工覆盖必须可追溯、可回放、可解释。 - 渐进复杂度:MVP 先建立稳定闭环,不引入复杂优化平台和长事务编排平台。 ## 3. 范围定义 ### 3.1 MVP 范围 首期只覆盖以下闭环: - 航班计划导入与实时状态更新 - 航班配对与过站上下文最小建模 - 基础资源分配:Stand、Gate、Belt、Counter - 关键里程碑跟踪与发布事实治理 - 延误、资源冲突和数据质量告警 - 对外查询接口与事件订阅 - 审计、人工裁决、重放与复核闭环 ### 3.2 非 MVP 范围 首期不纳入以下能力: - 全局优化排班和复杂资源优化求解 - 深度 AI 预测和自适应调度 - Flink 驱动的复杂 CEP 平台 - Temporal 驱动的复杂长事务工作流平台 - 多机场统一调度中心能力 ## 4. 总体架构 ### 4.1 架构分层 | 层级 | 主要能力 | MVP 主路径组件 | 说明 | | --- | --- | --- | --- | | 接入层 | 外部系统接入、协议解析、统一北向入口 | Kong Gateway、Apache Camel、SSIM 导入器 | 接收计划、动态、资源和人工操作输入 | | 业务层 | 航班当前态、观测治理、资源分配、告警处置、外部接口 | Flight Operation Service、Milestone Service、Resource Service、Alert Service、External API Service | 承担领域逻辑和对外契约 | | 事件层 | 事件骨干、重放、订阅分发 | Kafka、Outbox/CDC 发布器 | 负责异步传播和回放 | | 数据层 | 事务存储、时序存储、缓存 | PostgreSQL、TimescaleDB、Redis | 保存当前态、审计链路和热点读模型 | | 平台层 | 认证鉴权、部署、观测 | Keycloak、Kubernetes、Prometheus/Grafana/Loki | 提供运行时底座 | ### 4.2 核心技术链路 MVP 主链路采用“接入标准化 -> 观测入库 -> 裁决生成 -> 发布事实更新 -> 事件发布 -> 查询/订阅消费”的结构: 1. 外部计划或运行动态通过接入层进入系统。 2. Milestone Service 将输入标准化为 Observation,并按幂等键写入。 3. 规则引擎根据字段权威矩阵和当前上下文生成 Decision。 4. Flight Operation Service 更新 Published Fact 和当前状态摘要。 5. 同一事务内写入 Outbox,由 CDC 发布到 Kafka。 6. External API Service 对外提供查询接口和事件订阅接口。 7. 告警、人工裁决和重放都沿同一事实链路工作,不直接绕过 Published Fact。 ### 4.3 领域划分与聚合边界 为避免多服务共同修改同一业务对象,MVP 采用以下聚合边界: | 聚合 | 职责 | 主键 | 写主 | 发布事件 | 只读依赖 | | --- | --- | --- | --- | --- | --- | | FlightOperation | 航班当前权威态、运行状态、发布事实 | `flight_id` | Flight Operation Service | `FlightUpdated`、`PublishedFactUpdated` | Turnaround、MilestoneObservation、ResourceAllocation | | MilestoneObservation | 里程碑原始观测、标准化观测、候选事实 | `observation_id` | Milestone Service | `MilestoneObserved`、`MilestoneNormalized` | FlightOperation | | Turnaround | 到达航班、离港航班、飞机周转上下文 | `turnaround_id` | Flight Operation Service | `TurnaroundLinked`、`TurnaroundCorrected` | FlightOperation | | ResourceAllocation | 资源占用、锁定、冲突、覆盖 | `allocation_id` | Resource Service | `ResourceAssigned`、`ResourceUnassigned`、`ResourceConflictDetected` | FlightOperation、Turnaround | | AlertCase | 告警和处置对象 | `alert_id` | Alert Service | `AlertRaised`、`AlertAcknowledged`、`AlertCleared` | FlightOperation、ResourceAllocation | 边界约束: - Flight 当前权威态只能由 `Flight Operation Service` 写入。 - Milestone Service 负责观测和候选事实,不直接改写 Flight 当前态。 - Resource Service 只拥有资源占用与冲突事实,不直接修改 Flight 当前态中的非资源字段。 - Alert Service 不产生业务事实,只管理处置状态和告警生命周期。 ### 4.4 核心服务职责 - `Flight Operation Service` - 管理 FlightOperation 当前态。 - 维护 Published Fact。 - 负责 Turnaround 建模和关联修正。 - `Milestone Service` - 接收外部运行动态。 - 解析、标准化并形成 MilestoneObservation。 - 依据字段权威矩阵给出候选事实。 - `Resource Service` - 管理资源主数据和资源分配。 - 进行适配校验、冲突检测、人工覆盖和回滚。 - `Alert Service` - 管理告警、确认、关闭、抑制和处置轨迹。 - `External API Service` - 提供查询接口。 - 提供事件订阅接口或订阅分发适配层。 - 不作为权威事实生成者。 ## 5. 核心模型 ### 5.1 核心标识约定 - Flight - `flight_key`:`carrier + flight_number + op_date + leg_no` - `flight_id`:内部不可变主键 - Turnaround - `turnaround_id` - 可关联一个到达航班和一个离港航班 - MilestoneObservation - `observation_id` - 幂等键优先使用上游报文 ID、序列号或批次 + 行号 - Resource - `resource_id` - `resource_type + resource_code` 唯一 - ResourceAllocation - `allocation_id` - 幂等键由 `resource_id + validity_window + assignment_source + correlation_id` 组合约束 ### 5.2 核心实体与关系 - FlightOperation:指定运行日上的航班运行对象,包含当前发布事实和状态摘要。 - Turnaround:将到达航班、离港航班和飞机周转上下文关联起来,用于资源和时序联动。 - MilestoneObservation:里程碑观测记录,保留原始来源、标准化结果和候选事实。 - Resource:资源主数据,MVP 覆盖 Stand、Gate、Belt、Counter。 - ResourceAllocation:资源分配记录,含有效窗口、锁定类型、来源和覆盖原因。 - AlertCase:告警对象,关联 FlightOperation 或 ResourceAllocation。 - DataQualityFlag:对冲突、低可信度、超窗乱序、待裁决等问题做结构化标记。 关系约束: - 一个 FlightOperation 对应多个 MilestoneObservation。 - 一个 Turnaround 可关联一个到达航班和一个离港航班,也允许只有单侧航班待补全。 - 一个 Resource 在时间轴上可关联多个 ResourceAllocation,但硬冲突不允许同时生效。 - AlertCase 可关联具体 FlightOperation、Turnaround 或 ResourceAllocation。 ### 5.3 FlightOperation 最小字段组 - 主键:`flight_id`、`flight_key` - 属性:`carrier`、`flight_number`、`op_date`、`leg_no`、`direction` - 机体上下文:`aircraft_type`、`tail_number`(可空) - 状态:`flight_status` - 发布事实:计划 / 预计 / 实际时间类字段 - 当前资源摘要:Stand / Gate / Belt / Counter - 质量摘要:冲突标记、待裁决标记、最近裁决摘要 - 关联:`turnaround_id`(可空) ### 5.4 Turnaround 最小字段组 - `turnaround_id` - `arrival_flight_id` - `departure_flight_id` - `tail_number` - `aircraft_type` - `turnaround_status` - `link_source` - `link_confidence` 约束: - 配对可以晚于航班导入发生。 - 配对修正必须产生 `TurnaroundCorrected` 事件并保留审计。 - 若未知配对,FlightOperation 仍可独立运行,但资源和里程碑解释能力下降。 ## 6. 事实分层模型 ### 6.1 三层模型 | 层 | 含义 | 是否可变 | 用途 | | --- | --- | --- | --- | | Observation | 上游原始或标准化观测 | 否 | 追溯、回放、取证 | | Decision | 规则或人工裁决结果 | 否 | 解释为什么当前事实成立 | | Published Fact | 当前对外权威事实 | 是 | 查询、订阅、共享 | ### 6.2 SSOT 定义 AODB 的 SSOT 不等于“数据库中的最后一次写入”,而是: - 由 Observation 输入 - 经字段级权威矩阵与裁决逻辑处理 - 最终形成并发布的 Published Fact ### 6.3 状态写入三元信息 所有关键状态写入都必须附带: - `source` - `confidence` - `decision`(可空) 其中: - Observation 必须保存原始来源和原始时序。 - Decision 必须保存裁决者、依据、原因和裁决时间。 - Published Fact 必须能追溯到 Observation 和 Decision。 ### 6.4 字段级权威矩阵(最小集) | 字段 | 主来源 | 次来源 | 更正规则 | 人工覆盖 | 对外可见性 | | --- | --- | --- | --- | --- | --- | | ALDT | ANSP / 机场运行 | 航司 | 明确更正或高版本号优先 | 允许 | 返回当前值 + 来源 | | AIBT | 地服 / 机场运行 | 航司 | 同上 | 允许 | 返回当前值 + 来源 | | EIBT | 系统计算 | 运行动态派生 | 新计算覆盖旧计算并留历史 | 允许 | 返回当前值 + 可信度 | | TOBT | 航司 / 地服 | 机场运行 | 最新有效更正优先 | 允许 | 返回当前值 + 裁决摘要 | | TSAT | AODB / P1 PDS | 机场运行 | 新计算版本优先 | 允许 | 返回当前值 + 算法版本 | | Stand Assignment | 机场运行系统 | 人工调度 | 人工覆盖优先并保留原因 | 必须审计 | 返回当前值 + 覆盖摘要 | | Gate Assignment | 机场运行系统 | 人工调度 | 同上 | 必须审计 | 返回当前值 + 覆盖摘要 | | Belt Assignment | 机场运行系统 | 人工调度 | 同上 | 必须审计 | 返回当前值 + 覆盖摘要 | | Counter Assignment | 机场运行系统 | 人工调度 | 同上 | 必须审计 | 返回当前值 + 覆盖摘要 | ## 7. Flight 状态模型 ### 7.1 最小状态机 - Planned:已导入计划但尚无有效运行动态。 - Active:已有运行动态、里程碑或资源变更。 - Completed:已达到收敛里程碑并进入归档策略。 - Cancelled:取消或无效,但保留完整历史。 ### 7.2 状态迁移原则 - 状态迁移由 Published Fact 驱动,而不是由单个外部系统直接声明。 - 若存在冲突或裁决,不回滚 Observation 历史,只更新 Published Fact 和当前状态摘要。 - 状态修正必须能通过事件和审计链路回放。 ## 8. 历史、审计与回放 ### 8.1 数据存储视图 - `ObservationLog` - 保存原始或标准化观测 - `DecisionLog` - 保存规则命中和人工裁决 - `PublishedCurrentState` - 保存当前对外权威事实 - `AuditTrail` - 保存 `who / what / when / why` ### 8.2 基本约束 - PublishedCurrentState 的任何关键字段变更都必须能在 ObservationLog 和 DecisionLog 中找到原因链路。 - 人工覆盖不得改写原始 Observation,只能新增 Decision 并更新 Published Fact。 - 历史回放以事件和日志为准,不以任意时点快照为首期前提。 ## 9. 资源模型与冲突治理 ### 9.1 Resource 模型 每个 Resource 至少具备: - `resource_id` - `resource_type` - `resource_code` - `status` - `capability_profile` - `compatibility_constraints` - `parent_resource_id`(可空) - `operational_calendar` ### 9.2 ResourceAllocation 模型 每个 ResourceAllocation 至少具备: - `allocation_id` - `resource_id` - `flight_id` - `turnaround_id`(可空) - `allocation_status` - `assignment_source` - `lock_type`(`soft` / `hard`) - `validity_window` - `override_reason`(可空) - `derived_from_event` - `conflict_flags` ### 9.3 冲突分类 | 冲突类型 | 说明 | 是否阻断 | 是否允许人工覆盖 | | --- | --- | --- | --- | | 时间冲突 | 占用时间窗重叠 | 是 | 是 | | 适配冲突 | 机型、能力或运行属性不匹配 | 是 | 受限 | | 状态冲突 | 资源停用、维护、冻结 | 是 | 否 | | 策略冲突 | 本地策略或运营规则违反 | 视规则 | 是 | ### 9.4 四类资源规则口径 - Stand - 关注机型适配、拖曳、到离港时间窗、过站联动。 - Gate - 关注旅客流程时间窗、国际国内属性、步行距离和能力约束。 - Belt - 关注到港时序、机型、行李量经验参数和恢复能力。 - Counter - 关注值机开放窗口、航司差异化规则和共享柜台能力。 ### 9.5 人工覆盖原则 - 自动分配只产生建议或默认分配。 - 人工覆盖必须记录原因、证据、操作者和影响范围。 - 回滚必须和覆盖一样事件化和审计化。 ## 10. 事件模型与一致性 ### 10.1 事件分类 | 事件类别 | 说明 | 示例 | | --- | --- | --- | | Domain Events | 聚合内部事实变化 | `FlightUpdated`、`ResourceAssigned` | | Integration Events | 对外共享的标准化事件 | `PublishedFactUpdated`、`AlertRaised` | | Audit Events | 审计和裁决事件 | `ManualDecisionRecorded` | | Case Events | 人工复核和告警处置状态变化 | `ReviewTaskOpened`、`AlertAcknowledged` | ### 10.2 MVP 事件清单 - `FlightImported` - `FlightUpdated` - `TurnaroundLinked` - `TurnaroundCorrected` - `MilestoneObserved` - `MilestoneNormalized` - `PublishedFactUpdated` - `ResourceAssigned` - `ResourceUnassigned` - `ResourceConflictDetected` - `AlertRaised` - `AlertAcknowledged` - `AlertCleared` - `DataQualityFlagged` - `ManualDecisionRecorded` - `ReviewTaskOpened` - `ReviewTaskClosed` ### 10.3 事件归属表 | 事件 | 归属聚合 | 触发条件 | 是否对外发布 | 是否可回放 | | --- | --- | --- | --- | --- | | `MilestoneObserved` | MilestoneObservation | 收到有效运行动态 | 否 | 是 | | `PublishedFactUpdated` | FlightOperation | 当前权威事实发生变化 | 是 | 是 | | `ResourceAssigned` | ResourceAllocation | 资源分配生效 | 是 | 是 | | `ResourceConflictDetected` | ResourceAllocation | 检测到冲突 | 是 | 是 | | `ManualDecisionRecorded` | Decision / Audit | 人工裁决完成 | 是 | 是 | | `AlertRaised` | AlertCase | 达到告警条件 | 是 | 是 | ### 10.4 统一事件信封 所有业务事件必须具备: - `event_id` - `event_type` - `schema_version` - `occurred_at` - `produced_at` - `source` - `idempotency_key` - `correlation_id` - `aggregate_id` - `payload` ### 10.5 幂等、顺序和更正语义 - 所有写入事件必须携带 `idempotency_key`。 - 顺序保证以 `flight_id` 为最小粒度。 - 更正必须显式表达,不允许静默覆盖已发布事实。 - 乱序允许在可配置窗口内重排,超窗进入审计旁路并打数据质量标记。 ### 10.6 写库与发事件一致性 MVP 采用 `Outbox Pattern + CDC`: - 业务服务在同一事务内更新 PublishedCurrentState 并写入 Outbox。 - CDC / 发布器将 Outbox 可靠发布到 Kafka。 - 发布失败必须可重试、可恢复、可审计。 ## 11. 查询接口与事件订阅 ### 11.1 接口分离原则 - 查询接口负责读取 Published Fact、历史明细和告警状态。 - 事件订阅负责分发标准化事件流。 - 查询接口不是事实流;订阅接口不承担读模型查询职责。 ### 11.2 查询接口 最小查询对象: - FlightOperation 当前态 - MilestoneObservation 明细 - ResourceAllocation 生效集 - AlertCase 生命周期 最小要求: - 支持按 `op_date`、`flight_id / flight_key`、资源类型、状态过滤 - 返回更新时间和数据版本 - 关键字段返回 `source / confidence / decision summary` ### 11.3 事件订阅接口 最小要求: - 按 `event_type`、`flight_id`、`op_date` 过滤 - 至少一次投递 - 支持断线重连和补偿 - 基于 `event_id` 或游标回放 - 支持租户隔离、连接数和推送速率限流 ### 11.4 消费者契约 - 顺序仅保证到 `flight_id` - 消费者必须按 `event_id` 去重 - 消费者必须处理数据质量标记和裁决摘要 - 回放窗口和游标语义必须文档化 ## 12. 规则体系与人工复核 ### 12.1 规则分类 - `authority rules` - `validation rules` - `conflict rules` - `alert rules` - `allocation heuristics` ### 12.2 规则最小模板 每条规则都必须定义: - 输入 - 输出 - 优先级 - 命中条件 - 可解释字段 - 回放测试方式 ### 12.3 人工复核对象 - 解析失败复核 - 里程碑冲突复核 - 资源冲突裁决 - 人工覆盖审批 ### 12.4 Case 状态机 - `open` - `assigned` - `reviewing` - `decided` - `replayed` - `closed` 原则: - 所有人工动作都必须事件化。 - 所有人工动作都必须形成审计记录。 ## 13. 非功能与部署 ### 13.1 最小 SLO | 指标 | 目标值 | 最低可接受值 | | --- | --- | --- | | 可用性 | 月度 99.95% | 月度 99.9% | | 事件处理延迟 | P95 <= 2 秒 | P95 <= 5 秒 | | 容灾恢复 | RTO <= 30 分钟,RPO <= 5 分钟 | RTO <= 2 小时,RPO <= 15 分钟 | | 审计覆盖率 | 100% 关键变更可追溯 | 99.9% 可追溯 | ### 13.2 最小部署拓扑 | 组件 | 部署方式 | 高可用方式 | 失败影响 | 恢复方式 | | --- | --- | --- | --- | --- | | PostgreSQL / TimescaleDB | Stateful 部署 | 主备切换 + 定时备份 | 当前态和审计写入受影响 | 备份恢复 + 故障切换 | | Kafka | 多副本集群 | 副本和 ISR 保障 | 事件流中断或降级 | Broker 恢复 + 消费追赶 | | CDC / 发布器 | 无状态服务 | 多副本 + 幂等发布 | Outbox 堆积 | 断点续传 + 重试 | | API / 业务服务 | 无状态部署 | 多副本 | 查询或写入能力降级 | 滚动恢复 | | Redis | 主从或哨兵 | 缓存级高可用 | 热点查询性能下降 | 重建缓存 | ### 13.3 关键容灾约束 - PostgreSQL 必须具备 PITR 或等价恢复能力。 - Kafka 必须明确 `replication factor`、`min ISR`、保留窗口和重放策略。 - Outbox / CDC 必须具备断点恢复和重复投递幂等能力。 - 容灾演练必须覆盖数据库切换、事件堆积、订阅重连和回放。 ### 13.4 可观测性要求 - 所有写路径必须具备请求追踪、事件追踪和审计追踪三类关联 ID。 - 关键链路必须暴露延迟、失败率、积压量和重试次数指标。 - 人工裁决、资源覆盖和更正事件必须进入统一审计检索视图。 - 订阅接口必须暴露连接数、滞后量、推送速率和补偿次数指标。 ## 14. 文档边界与引用 - 本文档定义首期可开工的技术方案,不展开字段级数据字典和实现细节。 - 技术栈主选和启用条件以 `airport-wiki/concepts/aodb/开源技术栈选型决策.md` 为准。 - 需求边界以 `airport-wiki/concepts/aodb/AODB 核心需求提炼.md` 为准。 - 字段级权威矩阵以 `airport-wiki/concepts/aodb/AODB 字段级权威矩阵.md` 为准。 - 事件 envelope 和 payload 草案以 `airport-wiki/concepts/aodb/AODB 事件 Schema 草案.md` 为准。 - 最小部署拓扑和恢复策略草案以 `airport-wiki/concepts/aodb/AODB 最小部署拓扑草案.md` 为准。 - 关键设计取舍以 `airport-wiki/concepts/aodb/adr/` 下 ADR 为准。