4. 现有系统架构分析:梳理上下游依赖与数据流向
做数据迁移,最怕什么?
最怕你埋头干了大半个月,上线才发现漏了一个数据消费者。数据对不上,业务方找上门,回滚又得折腾半天。
所以,切入任何 SDK 改造项目,我的第一步永远是:把现有系统架构画出来。不是画给老板看的那种高瞻远瞩的架构图,是画给开发组自己看的、带箭头、带数据表、带调用次数的实打实依赖图。
说白了,你得搞清楚:数据从哪来?经过谁?最终落到哪?
4.1 系统架构全景图:先看全局
先别急着扎进代码细节。我建议你把整个系统的核心模块列出来,至少包含以下几层:
- 接入层:负责接收客户端 SDK 上报的原始数据。通常是 Nginx 或 API Gateway。
- 业务逻辑层:对原始数据进行清洗、校验、聚合。常见的是 Java/Go 写的微服务集群。
- 数据存储层:包括关系型数据库(MySQL、PostgreSQL)、缓存(Redis)、消息队列(Kafka、RabbitMQ)。
- 数据消费层:下游的数据分析平台、报表系统、推荐系统、运营后台等。
拿我最近改造的一个广告 SDK 项目举例。它的旧架构大概长这样:
4.2 梳理上下游依赖:谁是直接依赖?谁是间接依赖?
全景图搭好之后,下一步是枚举每个模块的上下游。
我习惯用一张表格来记录,你想想看,如果靠脑子记,20 个微服务的依赖关系很快就把你搞晕了。
| 模块名称 | 上游生产者 | 下游消费者 | 依赖类型 | 数据格式 |
|---|---|---|---|---|
| 数据采集服务 | 客户端 SDK | 清洗服务、原始日志库 | 强依赖(同步) | JSON / Protobuf |
| 清洗服务 | 数据采集服务 | 分析服务、MySQL | 强依赖(同步 + 异步) | Avro / Parquet |
| 分析服务 | 清洗服务 | 实时报表、推荐引擎 | 弱依赖(异步可降级) | JSON |
| 离线数仓 | MySQL Binlog / Kafka | BI 报表、运营后台 | 弱依赖(T+1 任务) | ORC / CSV |
为什么这张表这么重要?因为我记得接过一个棘手的项目——客户端 SDK 要切换数据上报协议,从 JSON 改成 Protobuf。乍一看很简单,只在接入层改一下解析逻辑就行。但真翻出依赖表才发现,下游有三个历史遗留的日志解析脚本直接解析原始 JSON 字段!如果不在架构分析阶段发现这个问题,上线后那三个脚本会直接报错崩溃。
- 强依赖(同步):改造时必须做兼容性测试,尽量采用“双写”或“灰度切换”。
- 弱依赖(异步/离线):允许一定的延迟,可以先改造核心链路,再慢慢处理离线任务。
4.3 数据流向分析:追踪一条数据的一生
依赖搞清楚了,接下来轮到数据流。我会挑一条最核心的用户行为数据,从客户端生成开始,一直追踪到它最终被哪个报表使用。简单说,就是“数据的一生”。
举个例子,一条“用户点击广告”的事件:
- 客户端 SDK 打包点击事件,包含 userId、adId、时间戳、设备信息。
- 通过 HTTP POST 发送到接入层(Nginx)。
- 接入层校验签名后,写入 Kafka 的
click_raw主题。 - 清洗服务消费 Kafka,调用用户画像服务补齐用户标签,写出到
click_clean主题。 - 分析服务消费
click_clean,聚合出 5 分钟粒度的点击率,存入 Redis。 - 实时报表定时从 Redis 拉数据渲染。
- 离线数仓每晚从
click_clean拉全量数据,跑次日留存分析。
这条路径上,哪些环节改造时会受影响?
- 如果改客户端 SDK 数据格式,步骤 2(接入层)和步骤 3(Kafka 消息体)都要跟着变。
- 如果只换消息队列(比如 Kafka 迁到 RocketMQ),步骤 3 及之后的所有消费者都得改连接配置。
- 如果换数据库,步骤 5 的写入逻辑和步骤 7 的离线 ETL 都得调整。
梳理清楚这些,你就能精准评估“牵一发而动全身”的范围。
4.4 核心数据实体定义:数据字典不能省
光知道流向还不够。我见过太多团队,“用户 ID”这个字段,在不同的系统里叫 uid、user_id、userId、userid,甚至有的是 memberId。迁移时各种字段映射错误,数据质量掉到地上。
所以,在动手改造前,我强烈建议你整理一份核心数据字典。不要求全,先把迁移涉及到的字段统一起来。
| 标准字段名 | 旧系统命名 | 新系统命名 | 数据类型 | 说明 |
|---|---|---|---|---|
| user_id | uid / userid | user_id | STRING (UUID) | 用户唯一标识 |
| ad_id | adId / promotion_id | ad_id | INT64 | 广告物料 ID |
| event_timestamp | time / create_time | event_timestamp | INT64 (Unix ms) | 事件发生时间戳 |
4.5 避坑指南:架构分析阶段最容易忽略的 3 个点
这部分是我自己的血泪史,分享出来给你避开。
- 忽略隐式依赖。 什么是隐式依赖?代码里没写,但运维脚本、监控告警、定时任务直接读数据库表或日志文件。比如有个 DBA 手写的清理脚本,直接 truncate 了某张旧表。你改造把表名改了,脚本不更新,下周磁盘就可能爆满。
- 低估消息队列的消费端延迟。 改造期间经常需要“双写”上下游两套系统。很多人只在代码层面做了双写,却没考虑消费者 backlog 堆积。如果双写期间生产速率翻倍,Kafka 的消费 lag 会飙高,造成数据实时性下降。
- 没留够数据对齐时间。 新系统上线后,通常需要跑一段时间进行数据校验(新 vs 旧)。我对团队的要求是:至少留出 3 个完整的业务周期(比如 3 天)来做对比分析。别想着上线当天就切干净,99% 的情况都会翻车。
好了,架构分析阶段的核心内容就是这些。记住:画全图、列依赖、追数据、定字典。这四步做完,后续的改造方案才能站稳脚跟,不至于做到一半发现方向错了。