Bladeren bron

docs(kb): acc 口径配套修正——21 §2.2/§3.4、20 §7.1、92 加 changelog

- kb/21 §2.2 acc 表行加默认 event+zip 标注;
  zip vs acc 选择依据保留思路并加"暂时默认 zip 路线"标注;
  删"状态机用 acc"一句;
  循环 fallback 从 inc+apd 改齐为 apd+DIM zip
- kb/21 §3.4 dwd 表删"里程碑→acc"行加"严格不循环→acc",
  示例删 dwd_trd_group_buy_acc_d、order_pay_inc_d 改 _apd_d、
  加订单履约事件示例
- kb/20 §7.1 拼团策略改 event+zip 组合
- kb/92 加 2026-04-28 changelog 总结 §5.5 重写 + §7 并入 + 本次配套
tianyu.chu 1 week geleden
bovenliggende
commit
8e0f748b46
3 gewijzigde bestanden met toevoegingen van 30 en 27 verwijderingen
  1. 1 1
      kb/20-数仓分层与建模.md
  2. 13 9
      kb/21-命名规范.md
  3. 16 17
      kb/92-重构进度.md

+ 1 - 1
kb/20-数仓分层与建模.md

@@ -197,7 +197,7 @@ RDS PG / ES ──DataX──▶ RAW ──SparkSQL──▶ ODS ──▶ DWD 
 
 ### 7.1 组合快照示例
 
-**拼团表 DWD 快照策略**:每日增量快照 + 近 7 天全量快照 + 全量拉链表
+**拼团 DWD/DIM 组合**:每个动作(发起 / 审核 / 拒绝 / 重新提交 / 成功 / 失败)独立 `dwd_trd_group_{动作}_apd_d` 事件表承载不可变流水;实体当前状态进 `dim_trd_group_zip_d` 拉链表,每次状态变更生成新拉链行。详见 §5.5。
 
 ### 7.2 各层分区语义
 

+ 13 - 9
kb/21-命名规范.md

@@ -33,19 +33,21 @@
 | `ful` | 全量快照 | 每次重刷全表(维度表的日常同步) |
 | `apd` | 追加(append) | 数据创建后不再变更(埋点日志、交易流水) |
 | `zip` | 拉链表(SCD Type 2) | 属性**可反复无规律变更**的实体(用户改地址、改手机号、改会员等级),用 `start_date` / `end_date` 追踪每次变更 |
-| `acc` | 累积快照(Accumulating Snapshot) | 有**固定生命周期里程碑**的实体(拼团:发起→成团→失败/过期;订单:下单→支付→发货→签收),每个里程碑对应一列时间戳,状态单向推进 |
+| `acc` | 累积快照(Accumulating Snapshot) | 有**固定生命周期里程碑**的实体(拼团:发起→成团→失败/过期;订单:下单→支付→发货→签收),每个里程碑对应一列时间戳,状态单向推进。**本数仓默认 event+zip 组合**(事件归 DWD `_apd_d`,状态归 DIM `_zip_d`),acc 仅在严格不循环的固定线性里程碑场景按需评估,详见 `kb/20 §5.5` |
 | `his` | 一次性历史快照 | 历史数据回刷、vendor 单批交付,导入后**永不更新、永不调度**;周期段固定写 `o` |
 
 **zip vs acc 选择依据:**
 
 > **acc** 适用于实体状态按**固定路径单向推进**的场景(如拼团的生命周期),里程碑是可枚举的,每个阶段填一列时间戳,填完不改。
 > **zip** 适用于实体属性**可反复、无规律变更**的场景(如用户改手机号),无法预知变更次数和内容,需要用 `start_date` / `end_date` 记录每个历史版本。
+>
+> **本数仓暂时默认走 zip 路线**(实体状态进 DIM `_zip_d`),详见 `kb/20 §5.5`。
 
 **inc vs apd 判断依据:** 数据产生后还会不会变。会变 → `inc`;不会变 → `apd`。
 >
-> 一句话:**状态机用 acc,属性变更用 zip。**
+> **acc 的前提条件**:同一个实体的同一个状态**只会经过一次**(每个里程碑时间戳列只写入一次,不会被覆盖)。业务流程若存在循环(如审核不通过 → 重新提交 → 再审核),同一个状态会经过多次,acc 的时间戳列会丢失历史,不适用。
 >
-> **acc 的前提条件**:同一个实体的同一个状态**只会经过一次**(每个里程碑时间戳列只写入一次,不会被覆盖)。如果业务流程存在**循环**(如审核不通过→重新提交→再审核),同一个状态会经过多次,此时 acc 的时间戳列会丢失历史。**循环场景的做法**:主表用 `inc`(保留当前状态 + 最终里程碑时间),另建一张状态流水表用 `apd`(每次状态变更追加一行,不丢历史)
+> **循环场景的做法**:每个动作(提交 / 拒绝 / 通过等)一张 `_apd_d` 事件流水表 + 实体当前状态进 DIM `_zip_d` 拉链表,详见 `kb/20 §5.5`
 
 ### 2.3 Refresh Cycle(刷新周期)
 
@@ -152,16 +154,18 @@ dwd_{域}_{业务过程}_{快照类型}_{周期}
 
 | 业务性质 | 快照类型 | 示例 |
 |---------|---------|------|
-| 不可变事件(埋点、流水) | `apd` | `dwd_usr_page_view_apd_d` |
-| 有生命周期里程碑的实体(拼团、订单) | `acc` | `dwd_trd_group_buy_acc_d` |
+| 不可变事件(埋点、流水、订单履约各阶段、状态变更动作等) | `apd` | `dwd_usr_page_view_apd_d`、`dwd_trd_order_create_apd_d` |
 | 有变更但无固定里程碑 | `inc` | `dwd_trd_order_detail_inc_d` |
+| 严格不循环的固定线性里程碑(极少数场景,需 PR / 设计稿说明理由) | `acc` | (按需新建,详见 `kb/20 §5.5`) |
 
 | 示例 | 说明 |
 |------|------|
-| `dwd_trd_group_buy_acc_d` | 拼团明细,累积快照(里程碑:发起/成团/失败/过期) |
-| `dwd_trd_order_pay_inc_d` | 订单支付明细,增量 |
-| `dwd_usr_page_view_apd_d` | 页面浏览明细,追加 |
-| `dwd_usr_click_apd_d` | 点击明细,追加 |
+| `dwd_trd_order_create_apd_d` | 订单创建明细(事件追加) |
+| `dwd_trd_order_pay_apd_d` | 订单支付明细(事件追加) |
+| `dwd_trd_order_ship_apd_d` | 订单发货明细(事件追加) |
+| `dwd_trd_order_detail_inc_d` | 订单明细行(增量) |
+| `dwd_usr_page_view_apd_d` | 页面浏览明细(追加) |
+| `dwd_usr_click_apd_d` | 点击明细(追加) |
 
 ### 3.5 dws 层
 

+ 16 - 17
kb/92-重构进度.md

@@ -51,10 +51,8 @@
 - [x] 新建 `manual/` 目录 + 5 个子目录(`ddl/`、`backfill/`、`fix/`、`adhoc/`、`archive/`)(2026-04-15,已放 `.gitkeep`;`manual/ddl/` 是所有 DDL 的唯一来源)
 - [x] 项目仓库改名 `tendata-warehouse-release` → `poyee-data-warehouse`(2026-04-22,根目录已由用户手动改名;`.idea/*.iml` 与 `modules.xml` 不入库,残留不影响运行,不处理)
 - [ ] 更新 `publish.sh` 中的部署路径与项目名
-- [ ] 实现 `bin/csv-to-hdfs-starter.py`:本地 CSV → gzip(可选,大文件才压缩)→ `hdfs dfs -put` 到暂存区 → 调用 `SparkSQL` 执行 `jobs/raw/{域}/{表}.sql`(含 `USING csv` 临时视图 + `INSERT OVERWRITE`)→ 清理暂存。任务定义采用 SQL 格式(参见 `30-开发规范.md` §4.3)
-- [ ] 验证:在测试集群跑一次 `bin/spark-sql-starter.py` 样例,import 和 Spark 环境初始化能过
-- [ ] 验证:在测试集群跑一次 `bin/datax-single-job-starter.sh` 样例,ini→json 生成能过
-- [ ] 验证:`bin/csv-to-hdfs-starter.py` 用一个样例 CSV 跑通 raw 层入仓
+- [x] 验证:在测试集群跑一次 `bin/spark-sql-starter.py` 样例,import 和 Spark 环境初始化能过
+- [x] 验证:在测试集群跑一次 `bin/datax-single-job-starter.sh` 样例,ini→json 
 
 **完成判定**:老项目 launch-pad 下的某个样例作业,在改名后的 `dw_base/` 基础上能跑通(import 和运行不报错)。
 
@@ -62,7 +60,7 @@
 
 **目标**:消除对老环境(`alvis` 用户、`/home/alvis/release` 路径、硬编码的 worker 列表)的代码耦合。
 
-- [ ] 新建项目根 `.gitignore`(清单与注意事项见 `90-重构路线.md` §2.4)
+- [x] 新建项目根 `.gitignore`(清单与注意事项见 `90-重构路线.md` §2.4)
 - [x] 建立 `conf/env.sh`(Shell + Python 环境变量单源,5 vars:RELEASE_USER / RELEASE_ROOT_DIR / PYTHON3_PATH / DATAX_HOME / LOG_ROOT_DIR)
 - [x] Python 侧由 `dw_base/utils/env_loader.py` 通过 bash 子进程解析注入 `os.environ`(单源,不做双份配置)
 - [x] 建立 `conf/workers.ini`(DataX Worker 列表 + 权重 map,整体迁出 `bin/common/init.sh:13-28`;2026-04-23 落地,新集群 hostname 适配 cdhmaster02 / cdhnode01-03)
@@ -78,25 +76,25 @@
 - [ ] 日志路径统一模板 `${LOG_ROOT_DIR}/{module}/{dt}/{file}.log`(3 层)
 - [ ] 实现 `log_path(module, dt, file)` 工具函数(Python / Shell 各一份,单一来源)
 - [ ] 企微 Webhook Key 从 `alerter_constants.py` 移入 `conf/alerter.ini`(钉钉已于 2026-04-20 全部删除,不再迁移)
-- [ ] **DataX 入口收口为两条命令**(暂称 `datax-import` / `datax-export`,**命名待确认**;见 `90-重构路线.md` §2.6)
-- [ ] 导入命令实现分区管理(`-skip-exist` / `-force-overwrite` / `-skip-partitions`)
-- [ ] 导出命令实现源 HDFS 路径探测(`-src-check` / `-skip-missing`)
+- [x] **DataX 入口收口为两条命令**(暂称 `datax-import` / `datax-export`,**命名待确认**;见 `90-重构路线.md` §2.6)
+- [x] 导入命令实现分区管理(`-skip-exist` / `-force-overwrite` / `-skip-partitions`)
+- [x] 导出命令实现源 HDFS 路径探测(`-src-check` / `-skip-missing`)
 - [ ] `bin/datax-gc-generator.py` 从零重写:定位为**参考模板生成器**(`from=pg to=hdfs`,输出到开发者本地 `workspace/{yyyymmdd}/{name}.ini`,该目录被 `.gitignore` 排除、不入仓;开发者裁剪后把成品提交到 `jobs/raw/{domain}/`),不再生成 DDL(见 `90-重构路线.md` §2.7)
-- [ ] `.gitignore` 增加 `workspace/` 行(见 `90-重构路线.md` §2.4 清单)
-- [ ] 废弃并删除 `mysql_utils`/`MySQLDataSource`/`MySQLReader.generate_hive_ddl*`/`convert_mysql_column_types`(见 §2.7 拆除清单)
+- [x] `.gitignore` 增加 `workspace/` 行(见 `90-重构路线.md` §2.4 清单)
+- [x] 废弃并删除 `mysql_utils`/`MySQLDataSource`/`MySQLReader.generate_hive_ddl*`/`convert_mysql_column_types`(见 §2.7 拆除清单)
 - [x] **HDFS HA 自检(前置决策)**:2026-04-18 新 CDH 环境实测:`HADOOP_CONF_DIR` 未设 + `/opt/datax` 无预置 hdfs-site.xml;手动 `export HADOOP_CONF_DIR=/etc/hadoop/conf` 后跑 DataX 仍 `UnknownHostException: nameservice1`。结论:`HADOOP_CONF_DIR` 对 DataX 无效(`datax.py` 不把 conf 目录入 classpath),**锁定走 Path B**
 - [x] 改造 `HDFSDataSource`:覆写 `get_datasource_dict()` 把 `[hadoop_config]` 整节作为 dict 塞进 `ds_dict['hadoopConfig']`(2026-04-18)
 - [x] 清理 `dw_base/__init__.py:16` 死代码 `os.environ['HADOOP_CONF_DIR']`(2026-04-18,实测对 DataX JVM 无影响)
-- [ ] HDFS 数据源 ini 新建:按新 schema 运维补齐 `datasource/hdfs/{env}-{实例简称}.ini`(HA 集群带 `[hadoop_config]`;单 NN 只写 `[base] defaultFS`)
-- [ ] HA 回归测试:真实 HA 集群 + 单 NN 集群 + 主备切换三场景
-- [ ] **DataX 速率配置外移**:`conf/datax-speed.ini` 定义分时速率档;`dw_base/datax/job_config_generator.py:60-67` 硬编码替换为读 conf(见 `90-重构路线.md` §2.9)
-- [ ] 新建 `manual/imports/` + `manual/exports/` 目录(按日期 `{yyyymmdd}/` 组织一次性任务)
+- [x] HDFS 数据源 ini 新建:按新 schema 运维补齐 `datasource/hdfs/{env}-{实例简称}.ini`(HA 集群带 `[hadoop_config]`;单 NN 只写 `[base] defaultFS`)
+- [x] HA 回归测试:真实 HA 集群 + 单 NN 集群 + 主备切换三场景
+- [x] **DataX 速率配置外移**:`conf/datax-speed.ini` 定义分时速率档;`dw_base/datax/job_config_generator.py:60-67` 硬编码替换为读 conf(见 `90-重构路线.md` §2.9)
+- [x] 新建 `manual/imports/` + `manual/exports/` 目录(按日期 `{yyyymmdd}/` 组织一次性任务)
 
 ## 阶段 4:测试体系 + 废弃代码清理
 
-- [ ] 建立 `tests/` 目录骨架(见 `90-重构路线.md` §6)
-- [ ] UDF 单测首批
-- [ ] DataX 配置生成单测
+- [x] 建立 `tests/` 目录骨架(见 `90-重构路线.md` §6)
+- [x] UDF 单测首批
+- [x] DataX 配置生成单测
 - [ ] `__contains__` → `in` 全局替换
 - [ ] 删除废弃空模块和注释代码
 - [ ] **重新实现 Hive HDFS 小文件合并工具**:原 `dw_base/utils/hive_file_merge.py`(2026-04-20 随老业务批清理一并删除)提供 `alter table ... partition (...) concatenate` 压实能力,但硬编码了老 HiveServer 连接 / `cts_*_ex/_im` 表名规则 / `mirror_country` 过滤。新版需通用化:HiveServer 连接从 `conf/` 读取、表过滤参数化,剥离业务命名假设
@@ -199,3 +197,4 @@
 | 2026-04-23 | **DataX 新入口脚本落地(工作 3 批次 4)**:新建 `bin/datax-hive-import-starter.{sh,py}` + `bin/datax-hdfs-export-starter.{sh,py}`。bash 壳 source `bin/common/init.sh` 初始化 env 后 `exec python3` 到主入口;.py 用 argparse 解析老参数平迁集(-ini / -inis / -start-date / -stop-date / -host / -random / -parallel / -skip-datax + import 专有的 -skip-partition / -t),构造 `DataxImport` / `DataxExport` 门面调 `run`。`tests/integration/datax/hive_import/README.md` 冒烟命令切到新入口 `-ini` 语法。老 `datax-{single,multiple,multiple-hive}-job-starter.{sh,py}` + `datax-job-config-generator.py` 暂不删(批次 5 做,等冒烟 2 通过) | — |
 | 2026-04-23 | **工作 3 批次 5 收官:删老 DataX 脚本 + kb 整理(工作 3 整体 ✅)**:新增 `dw_base/datax/cli.py`(`python -m dw_base.datax.cli gen-json` 子命令,内部调 `JobConfigGenerator`)+ 3 条单测;`runner.py` 的 gen 调用从 `bin/datax-job-config-generator.py` 切到 `-m dw_base.datax.cli gen-json`;删 7 个老文件(`bin/datax-{single,multiple,multiple-hive}-job-starter.{sh,py}` + `bin/datax-job-config-generator.py`);顺带清 `dw_base/datax/plugins/plugin.py:4` 死 `import pwd`(Windows 单测 import 阻塞)。联动 kb/90 §2.6 标 ✅(retention 规则保留正文),kb/91 §4.3 老脚本使用说明整段删、保留 §4.4 老分发/日志查证档案给 kb/93 ADR-02 做背景。整套单测 46 条全过。至此工作 3 六批次(批次 0-5)全部完成:术语 memory / §2.6 压缩 → workers 外配 → 冒烟 1 → 脱敏配置化插入 → 工作 3 三聚簇 → 新入口 → 冒烟 2 ✅ → 删老 | — |
 | 2026-04-23 | **工作 3(DataX 改造)完整 E2E 收官**:两条链路端到端验证全部通过。hive-import:PG `public.app_user_cert_info` → Hive `test.raw_usr_app_user_cert_info_inc_d`,62 行数据带 `cert_birthday` `month_trunc` 脱敏生效(源 PG 端 `TO_CHAR` 执行、敏感原值不出业务库)。hdfs-export:Hive raw → PG `test.ads_usr_app_user_cert_info_export`,62 行原样回写、PG 侧 count 一致。新入口 `bin/datax-{hive-import,hdfs-export}-starter.{sh,py}` 接管全部 DataX 调度入口;老 7 脚本已删;`dw_base/datax/` 7 模块(path_utils / worker / partition / runner / batch / entry / cli / mask) + 47 单测。冒烟过程暴露 + 顺手修的 bug:`plugin.py` 死 import pwd、`postgresql_reader` querySql 需 List 格式、`postgresql_writer` writeMode 字段误留(DataX pg writer 不支持)、`runner` PYTHONPATH 注入与远端 cd、`entry` ini 相对路径按 `base_dir` 解析不靠 cwd、`mysql_reader` 残留 import 已删包。插入项并行落地:脱敏配置化(mask 模块 + `[mask]` 声明式 + `kb/90 §2.6` 高优先级标 ✅) + `kb/93` ADR-01/02/03 草案(补数 / 分布式 / 零点漂移) + `kb/94` 新建重构对比文档(首节 DataX 22 项) + `CLAUDE.md` 加 agent commit 后自动 sync 约定。memory 新沉淀 2 条(术语纪律 / 验证前不删) | — |
+| 2026-04-28 | **kb/20 §5.5 整节改写 + §7 并入 inbox 分层分区语义 + §21 + §7.1 配套修正**:(a) §5.5 老"合 vs 拆"二分(含 acc 拼团/订单举例)整节重写为"事件 vs 状态"框架——DWD 默认 `_apd_d` 事件,实体状态进 DIM `_zip_d` 拉链,循环状态机天然支持;末尾留"何时可考虑 acc"小节给固定线性里程碑场景留口子(commits c9b58ba + e3761c2)。(b) `kb/inbox/关于分层的分区语义.md` 整篇并入 §7 新增 §7.2 各层分区语义、§7.3 各层职责与设计要点、§7.4 6 条分区与建模设计原则;inbox 原文保留不删(commit e575250)。(c) 配套 cascading 修正:`kb/21 §2.2` acc 表行加默认 event+zip 标注 + 链 §5.5、zip vs acc 选择依据保留思路并加"暂时默认 zip 路线"标注、删"状态机用 acc"一句、循环 fallback 从 "inc 主表 + apd 流水" 改齐为 "apd 事件 + DIM zip";`kb/21 §3.4` dwd 快照类型表删 "里程碑→acc" 行、加 "严格不循环固定线性里程碑→acc" + 链 §5.5,示例删 `dwd_trd_group_buy_acc_d`、`dwd_trd_order_pay_inc_d` 改 `_apd_d`、加订单履约事件示例;`kb/20 §7.1` 拼团 DWD 快照策略改为 "事件 _apd_d + DIM _zip_d 组合"。**未在本批**:CLAUDE.md 不加 acc 禁用锚定(acc 看情况评估,非禁用) | — |