# 埋点数据同步方案(设计文档) > 受众:产品 / CTO / 协作方。本文档说明埋点数据从 ES 进入数仓的整体方案、合规取舍、协作约束。 > 实现细节见 `kb/14-埋点同步-开发.md`。 ## 1. 背景与需求 - **数据源**:埋点系统后端 = Elasticsearch(生产单环境,无 dev / test) - **量级**:约 1.4M event / 天;事件类型 50+ 长尾 - **存量形式**:按天 NDJSON.gz 文件(ES `_search` 导出,每行一个 ES hit 文档) - **增量形式**:实时写入 ES `traces-{YYYY-MM-DD}` 滚动索引 - **业务目的**:用户行为分析(留存、漏斗、转化、活跃度等) ## 2. 合规约束 - **公司原则**:敏感数据不出业务库 / 不入数仓 - **涉敏举例**: - 下单事件:收货地址、收件人姓名、收件人手机号 - 退款事件:银行卡号 - 其他事件按业务实际声明 - **合规优先级**:合规 > 数据完整性 > 开发便利 - **合规对"入仓"的定义**:物理存储层面的存在,不是逻辑层面的可访问性。一旦敏感字段落地到 HDFS / Hive 表,即使下游不查询也算违规 ## 3. 整体方案 ``` ┌────────────────┐ │ 埋点 ES (prod) │ └────┬───────────┘ │ ┌────────────┴─────────────┐ │ │ [增量路径] [历史路径] 每日 ES → Hive 一次性 .json.gz 文件 ES Storage Handler 按天解压解析 映射表 SELECT Python 脚本 │ │ └────────────┬─────────────┘ │ 【入仓阶段脱敏】 (按事件类型应用规则) │ ▼ ┌──────────────────┐ │ raw 层(数仓) │ └──────────────────┘ ``` 两条路径**最终落到同一张 raw 表**,schema 一致;脱敏规则共用同一份配置。 ## 4. 设计取舍:raw 层默认范式破例 数仓默认 raw 层走 schema-on-read landing 范式(数据原样落、ods 阶段才做类型转换 / 脏数据识别,详见 `kb/20-数仓分层与建模.md §8.1`)。本场景**主动破例**: | §8.1 理由 | 是否适用 | 说明 | |---|---|---| | 1. 隔离源端类型变化 | ✗ | 埋点 schema 长尾,新事件 / 新字段频繁,本就要求协作通知 | | 2. 同步阶段不可失败 | △ | 部分适用,需对解析失败做容错处理 | | 3. 保留原始精度与原文 | ✗ | 合规要求就是要丢字段,与"保原文"目标冲突 | | 4. 脏数据可观测 | △ | 事件本身可观测,脱敏后字段不可回溯(合规接受这代价) | | 5. schema-on-read 范式契合 | ✗ | 合规要求物理拦截敏感字段,不能等 ods 读取阶段才处理 | 3 条不适用 ≥ §8.1 阈值,破例成立。 **破例代价(明示)**: - 入仓阶段需做 JSON 解析 + 字段脱敏 + 配置化逻辑 - 埋点上下游 schema 变更需协作通知(违反"隔离源端"原则) - ods 失去"raw 一定有原始数据可回溯"的兜底保障 ## 5. 脱敏策略 ### 5.1 三种脱敏动作 | 动作 | 含义 | 适用 | |---|---|---| | `drop` | 字段直接删除,不入 raw | 高敏字段(地址、手机号、卡号等) | | `mask` | 字段保留但用脱敏函数处理 | 中敏字段(脱敏后的姓名、订单号末四位等) | | `reject` | 整事件不入 raw | 极敏感事件(如有) | 脱敏函数复用现有的 5 种:`md5 / month_trunc / mask_middle / keep_first_n / keep_last_n`(实现见开发文档)。 ### 5.2 配置驱动 所有脱敏规则集中在一份配置文件(`conf/tracking-mask.ini`),格式与加载方式见开发文档。 ### 5.3 兜底策略:选项 3 不加固 - **未在配置中的事件 / 字段**:默认允许,全部原样入 raw - **配置中显式声明 drop / mask 的字段**:按规则处理 - **风险**:新含敏事件没及时进配置 → 原文入仓 → 违规 - **风险缓解**:靠协作流程(§6)+ 审计机制(§6.2) > **候选选项(已否决)**: > > - **选项 1(事件级白名单)**:任何新事件不在 conf 都不入仓——卡业务上线节奏,否决 > - **选项 2(字段级白名单仅对已声明事件)**:含敏事件首次进 conf 时所有字段必须登记,后续上游加字段自动 drop——多一道保险但仍有"全新含敏事件没及时进 conf"风险,与选项 3 漏的根本场景相同,多余的复杂度不抵收益,否决 ## 6. 协作流程 ### 6.1 三种新事件场景 | 场景 | 处理 | |---|---| | 新事件 + 无敏感字段 | 默认入仓,无需通知 | | 新事件 + 有敏感字段 | 强制走流程:埋点开发方 PR 注明 → 数仓更新配置 | | 已有事件加敏感字段 | 同上 | ### 6.2 审计机制 每日 ods 跑前对比当日 ES 出现的 event_name 集合 vs 配置已知集合,新增事件列表推 alerter(企微)。 数仓收到通知后人工判断是否含敏: - 含敏 → 立即更新 conf - 不含敏 → 无需操作(继续兜底) ### 6.3 应急响应 发现敏感字段误入仓时: 1. 立即更新 conf 加 drop / mask 规则 2. 历史数据:对受影响 dt 分区跑回填,覆盖原数据 3. 复盘:分析为何协作流程失守 ## 7. 风险与决策点 ### 7.1 已识别风险 - **R1 协作流程失守**:新含敏事件没及时进 conf → 违规 - 缓解:审计机制(§6.2)+ 应急响应流程(§6.3) - **R2 ES Storage Handler 故障**:增量路径中断 - 缓解:DS 调度告警 + 重跑(INSERT OVERWRITE 幂等) - **R3 历史数据脱敏不彻底**:早期入仓的非脱敏数据残留 - 缓解:现 testbed 数据按本方案重跑(落地范围决策见 §7.2) ### 7.2 已锁定决策 - **加固方案**:选项 3 不加固 - **raw 表组织**:单 wide schema 表(不按事件分多张) - **现 testbed 处置**:暂不处理(drop 重做或换名共存留待后续单独评估) ## 8. 落地范围 本方案仅覆盖 raw 层入仓 + 脱敏。后续阶段(不在本方案): - ods 层 schema 设计(按事件分流解析 params_json) - dwd / dws / ads 层建模 - 实时埋点路径(如需要)