# 国家数据大屏口径对账与修复计划 ## 基准说明 - 对账日期:`2026-05-27` - 统计时区:`Asia/Riyadh` - 统计窗口:`2026-05-27 00:00:00` 到 `2026-05-28 00:00:00` - 系统来源:`LIKEI` - 对账方式:旧 Java 源表口径结果 vs 当前 `country_dashboard_*` 预聚合结果。 - 注意:日内数据会继续增长,金额和人数会随时间变化。本文中的“之前数据”来自本轮对账快照;后续修复验证必须重新跑同一窗口源表对账。 ## 总体结论 当前大屏切到预聚合后,差异主要来自三类问题: 1. 旧 Java 是直接按 Mongo/SQL 源表字段聚合,CDC worker 有些字段改成了用户国家表、wallet 事件或部分表事件,口径没有完全复刻。 2. 部分 Mongo 源表没有进入 CDC:日活、礼物流水、幸运礼物、工资转移等需要单独的 reconcile/增量任务。 3. 留存基数与留存命中当前使用 worker 自己的用户国家表和活跃集合,和旧 Java 的注册 cohort + active log 口径不一致。 ## 字段对账表 | 字段 | 旧 Java 口径 | 旧口径源表结果 | 当前预聚合结果 | 差异 | 差异原因 | 修复方案 | 状态 | | --- | --- | ---: | ---: | ---: | --- | --- | --- | | 新增 | 按 admin 用户列表展示口径统计 `user_base_info` 创建时间,展示日等于 `create_time + 8h` 后的日期;按用户国家归组。 | 之前用户列表显示约 57,部署期间增长到 60 | 修复前明显少算 | 修复前不稳定 | worker 原先按数据库原始时间截日,和 admin 用户列表展示日不一致。 | 已改 worker 的新用户统计窗口为 `create_time + 8h` 展示日;回填目标日期并重建 `DAY/ALL`。 | 已修 | | 日活 | Mongo `user_daily_active_log`,按 `activeDate + sysOrigin` 过滤;先按 `registerCountryCode,userId` 去重,再按 `registerCountryCode` 计数。 | 984 | 844 | -140 | worker 原先读取 active log 后,又强依赖 `dashboard_cdc_user_country` 做国家归类,用户国家缺失或删除标记会把活跃用户过滤掉;旧 Java 不查用户国家表。 | 已改 worker:日活直接使用 active log 的 `sysOrigin/registerCountryCode`;只有 active log 国家为空才 fallback 用户国家表。 | 已修 | | 新增充值 | 旧 Java 订单口径中,新注册用户在窗口内产生的充值。 | 2 | 2 | 0 | 当前已对齐。 | 保持现状;后续只做回归验证。 | 正常 | | Google 充值 | Google 订单成功支付金额,按订单完成时间落入统计窗口。 | 63 | 63 | 0 | 当前已对齐。 | 保持现状;后续只做回归验证。 | 正常 | | MifaPay 充值 | MifaPay 订单成功支付金额,按订单完成时间落入统计窗口。 | 0 | 0 | 0 | 当前已对齐。 | 保持现状;后续只做回归验证。 | 正常 | | 币商充值 | 币商/代理充值流水,旧 Java 从币商充值相关 SQL 表聚合。 | 0 | 0 | 0 | 当前已对齐。 | 保持现状;后续只做回归验证。 | 正常 | | 总充值 | Google + MifaPay + 币商等充值汇总。 | 63 | 63 | 0 | 当前已对齐。 | 保持现状;后续只做回归验证。 | 正常 | | 工资兑换 | 旧 Java 包含 SQL 工资账户流水和 Mongo bank 流水中的工资兑换口径。 | 6.75 | 0 | -6.75 | worker 当前没有完整接入工资兑换相关 SQL/Mongo 流水。 | 增加工资兑换 reconcile:读取旧 Java 使用的 SQL 表和 Mongo `user_bank_running_water` 条件,按用户国家归组写 `salary_exchange`;补回填。 | 待修 | | 工资转移 | 旧 Java 来自 Mongo `user_bank_running_water` 的工资转移口径。 | 38 | 0 | -38 | worker 当前未接入 Mongo bank 转移流水。 | 增加 Mongo bank reconcile:复刻旧 Java 的转移类型、状态、时间字段、金额单位,写 `salary_transfer`;补回填。 | 待修 | | 礼物消耗 | Mongo `gift_give_running_water`;旧 Java 条件包含 `refunded != true`、`userId != null`、窗口内 `createTime`、指定 `sysOrigin`、`luckyGift != true`、`originId` 为数字、`dynamicContentId` 为空或不存在;金额取 `giftValue.actualAmount`。 | 7,276,368 | 3,327,288 | -3,949,080 | worker 当前没有完整复刻 Mongo `gift_give_running_water` 条件,可能只覆盖部分礼物事件或国家映射。 | 新增/修正 gift reconcile,直接按旧 Java Mongo 条件聚合普通礼物消耗,写 `gift_consume`;不要从 wallet `LUCKY_GIFT` 反推普通礼物。 | 待修 | | 幸运礼物流水 | 旧 Java 从 `game_lucky_gift_count` 聚合幸运礼物总流水。 | 2,279,050 | 0 | -2,279,050 | `game_lucky_gift_count` 有源数据,但 worker/预聚合没有写入 `lucky_gift_total_flow`。 | 新增 lucky gift reconcile:按旧 Java 查询条件读取 `game_lucky_gift_count`,写 `lucky_gift_total_flow`,同时写用户去重表 `LUCKY_GIFT_USER`。 | 待修 | | 幸运礼物人数 | 旧 Java 从 `game_lucky_gift_count` 按用户去重统计参与人数。 | 101 | 0 | -101 | 同幸运礼物流水,用户去重表未写。 | lucky gift reconcile 写 `country_dashboard_period_user_metric.metric_type='LUCKY_GIFT_USER'`,再重建汇总人数。 | 待修 | | 幸运礼物返奖 | 旧 Java 从 `game_lucky_gift_count` 聚合返奖金额。 | 1,892,900 | 0 | -1,892,900 | 同幸运礼物流水,返奖字段未写。 | lucky gift reconcile 写 `lucky_gift_payout`。 | 待修 | | 幸运礼物利润 | `幸运礼物流水 - 幸运礼物返奖`。 | 386,150 | 0 | -386,150 | 流水和返奖都缺失导致利润为 0。 | 修复幸运礼物流水和返奖后自动恢复;利润不应单独写源数据。 | 待修 | | 游戏流水 | 旧 Java 从 `wallet_gold_asset_record_*` 和游戏统计表按游戏下注/消耗事件聚合。 | 109,688,935 | 74,509,547 | -35,179,388 | worker 当前游戏聚合少覆盖部分 `event_type` 或表来源,且用户去重也随之少算。 | 按旧 Java 的 game event_type 列表逐项核对,补齐 consume 事件映射;对每类事件做源表 vs 预聚合差异拆分。 | 待修 | | 游戏人数 | 旧 Java 按游戏流水参与用户去重。 | 176 | 113 | -63 | 游戏流水事件少覆盖,导致用户去重同步少算。 | 游戏流水修复时同步写 `GAME_USER` 去重表;重建 `DAY/ALL`。 | 待修 | | 游戏返奖 | 旧 Java 从游戏返奖/中奖事件聚合。 | 107,776,247 | 72,064,472 | -35,711,775 | worker 当前 payout 事件覆盖不完整,返奖少算幅度大于流水少算。 | 按旧 Java payout event_type 和 `game_lucky_box_count` 等来源补齐映射;验证 consume/payout 各自差值。 | 待修 | | 游戏利润 | `游戏流水 - 游戏返奖`。 | 1,912,688 | 2,445,075 | +532,387 | 流水和返奖都少算,但返奖少算更多,所以利润虚高。 | 修复游戏流水和游戏返奖后重算;利润不单独写源数据。 | 待修 | | 次日留存 | 旧 Java:注册 cohort 来自用户注册表;命中来自 Mongo `user_daily_active_log` 的目标活跃日期。 | 0 / 0 | 84 / 127 | +84 / +127 | 当前留存基数和命中口径与旧 Java 不一致,使用了 worker 用户国家表和当前 active 集合。 | 重写 retention reconcile:注册 cohort 复刻旧 Java `listNewUserCohorts`,活跃命中直接查 active log;按国家分别写 base/user。 | 待修 | | 七日留存 | 同上,目标日期为注册日 + 7。 | 0 / 0 | 25 / 60 | +25 / +60 | 同次日留存。 | 同 retention reconcile,支持 D7。 | 待修 | | 30 日留存 | 同上,目标日期为注册日 + 30。 | 0 / 0 | 5 / 7 | +5 / +7 | 同次日留存。 | 同 retention reconcile,支持 D30。 | 待修 | ## 已完成修复记录 ### 新增 - 修改点:`dashboard-cdc-worker` 新增用户统计使用 admin 用户列表展示日,即 `create_time + 8h` 后的日期。 - 验证结果:`2026-05-27` 修复后源数据和预聚合从 57 增长到 60,增长来自部署期间新增的 3 个用户。 - 结论:新增已与用户列表显示口径对齐。 ### 日活 - 修改点:`dashboard-cdc-worker/internal/storage/active_reconcile.go` - 提交:`0b5e687 Align daily active metric with active log` - 部署镜像:`dashboard-cdc-worker:daily-active-log-country-20260527-0b5e687` - 验证结果:`2026-05-27` - Mongo 旧 Java 口径:`1054` - `country_dashboard_period_metric` 预聚合:`1054` - 差值:`0` - 结论:日活已与旧 Java active log 口径对齐。 ## 后续修复顺序建议 1. 工资兑换、工资转移:影响字段少,数据源明确,先补 Mongo/SQL reconcile。 2. 礼物消耗:复刻 `gift_give_running_water` 条件,避免继续从 wallet 侧错误推导。 3. 幸运礼物:直接接 `game_lucky_gift_count`,同时写金额和人数去重。 4. 游戏流水、游戏返奖、游戏人数:按 event_type 拆分差异后逐类补齐。 5. 留存:最后统一重写,因为它依赖新增口径和日活口径都稳定。 ## 每项修复后的验证模板 每修一个字段,都必须跑同一套对账: ```sql -- 预聚合结果 SELECT SUM() AS precomputed_value FROM country_dashboard_period_metric WHERE period_type = 'DAY' AND period_key = '2026-05-27' AND stat_timezone = 'Asia/Riyadh' AND sys_origin = 'LIKEI'; ``` 源表侧按旧 Java 条件单独查一遍,并输出: | 字段 | 旧 Java 源表结果 | 预聚合结果 | 差值 | 是否通过 | | --- | ---: | ---: | ---: | --- | | 待验证字段 | 0 | 0 | 0 | 是/否 |