Skip to content

Latest commit

 

History

History
226 lines (178 loc) · 7.1 KB

File metadata and controls

226 lines (178 loc) · 7.1 KB

Dataset First 数据服务结构

适合长期运行、补数、巡检、血缘、质量治理的数据产品服务。

判断规则:

如果服务的核心交付物是“稳定数据集”,而不是页面、接口或一次性脚本,就优先使用 Dataset First。

一句话

以 dataset 为边界,以 schema/data contract 为先,以 runtime/registry/config 为共享控制面,以 collect/backfill/repair/validate 为实现单元。

适合
  • 行情事实采集服务。
  • 另类事件采集服务。
  • 周期轮询快照服务。
  • 原子事件流 + 时间桶聚合并存的数据服务。
  • 需要长期运行、补数、巡检、血缘、质量治理的数据服务。

不适合直接照抄
  • 纯 API 网关。
  • 纯 Web 应用。
  • 纯交易执行服务。
  • 一次性脚本工具。
  • 不产出稳定 dataset 的临时任务。

核心原则
  1. Dataset First:顶层先按 dataset 划分,而不是按 collector/parser/writer/task 划分。
  2. Contract First:先定义目标落表、字段语义、主键、时间列、分区策略和刷新粒度。
  3. Layered Modeling:原子层、聚合层、事件流、时间桶、运行状态分开建模。
  4. Shared Control Plane:config.pyregistry.pyservice_entry.pyruntime/* 统一收口。
  5. Legacy Is Explicit:迁移期 legacy 壳只能兼容转发,新逻辑不得回流旧路径。

标准目录
service-root/
├── README.md
├── AGENTS.md
├── pyproject.toml
├── scripts/
│   ├── start.sh
│   ├── verify.sh
│   └── check_legacy_shells.sh
├── src/<service_name>/
│   ├── __init__.py
│   ├── config.py
│   ├── registry.py
│   ├── service_entry.py
│   ├── common/
│   ├── runtime/
│   │   ├── stack_runner.py
│   │   ├── process_utils.py
│   │   ├── <group>_runner.py
│   │   └── <group>_worker.py
│   ├── writers/
│   ├── validators/
│   └── datasets/
│       ├── <dataset_a>/
│       │   ├── contract.py
│       │   ├── collect.py
│       │   ├── backfill.py
│       │   ├── repair.py
│       │   ├── writer.py
│       │   ├── validate.py
│       │   └── README.md
│       ├── <dataset_b>/
│       └── _reserved/
├── tests/
│   ├── unit/
│   ├── integration/
│   └── fixtures/
└── legacy/ or old-shells/

Dataset 最小结构
<dataset>/
├── contract.py
├── collect.py
├── backfill.py
├── repair.py
├── writer.py
├── validate.py
└── README.md

职责边界:

  • contract.py:定义 dataset key、resource_id、物理表、主键、幂等键、时间语义、字段语义。
  • collect.py:实时采集或轮询采集主逻辑。
  • backfill.py:历史补数、文件回填、分页补齐。
  • repair.py:缺口修复、异常恢复、局部重算。
  • writer.py:统一落库、批量写入、去重、冲突处理。
  • validate.py:数据质量检查、行数、字段、时间连续性校验。
  • README.md:说明该 dataset 的输入、输出、约束与边界。

如果某个 dataset 没有 repairbackfill,必须在 registry 中显式标记为不支持。

Registry 真相矩阵

registry.py 至少应定义:

dataset_key
resource_id
runtime_status        # active | backfill_only | reserved | disabled
physical_table
group                 # lf | hf | events | snapshots
source_kind           # ws | rest | zip | scrape | file | api
collect_supported
backfill_supported
repair_supported
default_enabled
owner

推荐额外字段:

symbol_scope
refresh_granularity
retention_policy
partition_key
schema_version
sensitivity

Registry 的作用:

  • 它是 dataset 清单的单一真相源。
  • 文档、运行、血缘、权限、门禁都应从 registry 派生。
  • 没有 registry,就会回到“数据集藏在脚本里”的旧问题。

Dataset 命名

推荐格式:

<market>_<instrument>_<topic>_<granularity?>_<layer?>

示例:

  • spot_trades
  • futures_um_trades
  • futures_um_book_ticker
  • futures_um_book_depth
  • candles_1m
  • futures_metrics_5m
  • futures_um_metrics_atomic

命名要求:

  • 名字必须表达数据是什么,而不是代码怎么实现。
  • _reserved/ 只用于预留未来命名空间,不用于临时文件。
  • 事件流、快照、时间桶、派生结果要在命名或 contract 中显式表达。

Service Entry 与 Runtime

service_entry.py 统一入口只做:

  • plan
  • start
  • stop
  • status
  • restart

它不直接写业务逻辑,只负责读取 config、读取 registry、调用 runtime runner、输出运行真相。

runtime/ 负责:

  • 进程编排。
  • 模式分组。
  • PID、日志、健康状态。
  • cold-start、restart、stop 行为一致性。

业务代码不允许各自实现第二套守护逻辑。

数据模型分层

推荐区分:

atomic            # 原子事件/原子明细
snapshot          # 单次轮询快照
bucketed          # 时间桶聚合结果
derived           # 从事实层再派生的结果
reserved          # 预留但未启用

事件流模型适合 trades、orderbook updates、tick events、message stream,重点是顺序、幂等、去重、水位线。

时间桶 / 快照模型适合 candles、metrics、periodic snapshots、polling APIs,重点是覆盖、补齐、时间边界一致性。

新建数据服务流程
  1. 先定 dataset 清单:哪些 active、哪些 backfill_only、哪些 reserved。
  2. 先写 contract:字段、主键、时间列、分区策略、资源 ID、schema version。
  3. 再建 registry、config、service_entry、runtime。
  4. 逐个实现 dataset:contract -> writer -> collect -> backfill -> validate -> repair
  5. 最后补 README、AGENTS、verify/CI、资源目录、血缘映射、smoke。

外部源码接入流程
  1. 先盘点外部源码实际产出的数据对象,不先搬代码。
  2. 把原项目脚本反向映射为 dataset。
  3. 将 API client、auth、rate limiter、storage client、retry/backoff 抽到 common/runtime/writers/
  4. 将 legacy 壳显式隔离,只允许兼容转发,不允许承载新逻辑。