4. 数据采集与存储:从源头到仓库的完整链路

大家好,我是你们的老朋友。今天咱们聊聊数据回放里最基础、也最容易被忽视的一环——数据采集与存储。

说实话,我见过太多团队在回放时翻车,追根溯源,八成是数据采集阶段就埋了雷。要么数据不全,要么格式不对,要么存了一堆没法用的垃圾。嗯,这节课我就把我在一线踩过的坑、总结的经验,一次性倒给你们。

核心观点:数据采集的质量,直接决定了回放复现的成败。源头脏了,后面再怎么洗也白搭。

4.1 数据采集的三种主流方式

数据采集说白了就三招:埋点、抓包、API。我分别说说它们的适用场景和坑。

4.1.1 埋点:最主动的方式

埋点就是在代码里手动插入采集逻辑。比如用户点击了某个按钮,你就记录一条日志。

优点:想采什么采什么,精度高,语义明确。

缺点:侵入性强,需要改代码,漏埋了还得补发版本。

我个人习惯的做法是:先定义好事件模型,再动手写代码。别上来就埋,埋完发现字段对不上,那才叫痛苦。

我的经验:我在项目中遇到过,埋点字段名没统一,iOS叫"click_time",Android叫"clickTime",后端解析直接崩了。后来我们强制用驼峰命名,加一个全局字典做映射。

// 一个标准的埋点示例
{
  "event": "button_click",
  "properties": {
    "button_id": "submit_order",
    "page": "checkout",
    "timestamp": 1700000000000
  },
  "user_id": "u_12345"
}

4.1.2 抓包:最无侵入的方式

抓包就是在网络层面拦截请求和响应。适合你没法改代码的场景,比如第三方SDK、老旧系统。

优点:不改一行代码,拿到的是最原始的网络数据。

缺点:数据量大,噪音多,还得自己解析协议。

常用的工具有Charles、Wireshark、tcpdump。我个人偏爱tcpdump,命令行一把梭,配合Wireshark做可视化分析。

注意:抓包会涉及用户隐私数据,比如密码、token。我曾经在抓包时不小心把生产环境的用户手机号也抓下来了……嗯,后来被安全部门约谈。所以,抓包一定要在测试环境或脱敏后使用。

4.1.3 API:最标准的方式

通过调用业务系统的API接口,拉取数据。适合数据量不大、有现成接口的场景。

优点:标准化,容易对接,数据质量有保障。

缺点:依赖接口稳定性,接口改了你就得跟着改。

我建议的做法是:先确认API的限流策略和分页机制。不然你一个循环拉数据,直接把对方服务打挂了,那就尴尬了。

# 一个简单的API采集示例
import requests

def fetch_orders(page=1, page_size=100):
    url = f"https://api.example.com/orders?page={page}&size={page_size}"
    headers = {"Authorization": "Bearer your_token"}
    resp = requests.get(url, headers=headers)
    return resp.json()

4.2 数据存储选型:选对了省心,选错了糟心

数据采回来,总得找个地方存。选型这事儿,说白了就是权衡:你要快,还是要稳,还是要灵活?

存储方式 适用场景 优点 缺点
文件(JSON/CSV/Parquet) 小数据量、临时分析、离线回放 简单、通用、可读性强 不支持随机查询、并发差
数据库(MySQL/PostgreSQL/ClickHouse) 结构化数据、需要查询、中等规模 支持SQL、事务、索引 写入瓶颈、扩展成本高
消息队列(Kafka/Pulsar/RabbitMQ) 高吞吐、实时流、多消费者 削峰填谷、解耦、持久化 运维复杂、延迟敏感

我个人习惯是:小数据用文件,中等数据用数据库,大数据用消息队列+数据库组合。你想想看,如果你每天几亿条日志,全塞MySQL,那MySQL不炸才怪。

避坑指南:我曾经在一个项目里,把所有的回放数据都存成了JSON文件。一开始还好,后来数据量到了几十个G,每次回放都要全量加载,慢得让人崩溃。后来改成了Parquet格式,配合列式存储,速度提升了10倍。

4.3 数据脱敏与安全:红线不能碰

数据采集和存储过程中,最敏感的就是安全问题。尤其是涉及用户隐私的数据,比如手机号、身份证、银行卡号。

脱敏的常见手段:

  • 替换:用固定字符替换敏感字段,比如手机号变成"138****1234"
  • 加密:用AES/RSA加密存储,使用时再解密
  • 掩码:只显示部分字符,比如身份证只显示前6位和后4位
  • 哈希:用SHA256做单向哈希,不可逆
# 一个简单的脱敏函数
def mask_phone(phone: str) -> str:
    if len(phone) != 11:
        return phone
    return phone[:3] + "****" + phone[7:]

重要提醒:脱敏不是万能的。我曾经见过一个团队,脱敏了手机号,但没脱敏身份证号,结果通过身份证号反查手机号,照样泄露了隐私。所以,脱敏要全面,不能留死角。

另外,存储时一定要做好访问控制。谁可以读?谁可以写?谁可以删?这些权限必须明确。我建议用最小权限原则:每个人只给够用的权限,不多给。

4.4 知识体系总览

下面这张图,是我自己画的,把数据采集与存储的核心逻辑串起来了。你一看就明白。

数据采集与存储知识体系 数据源 App / Web / 服务端 / 第三方 采集方式 埋点 / 抓包 / API 存储选型 文件/数据库/消息队列 数据脱敏与安全 替换 / 掩码 加密 / 哈希 访问控制 高质量回放数据

这张图的核心逻辑是:数据从源头来,经过采集、存储、脱敏三道关,最终变成高质量的回放数据。每一步都有坑,每一步都需要你用心设计。

总结一句话:数据采集与存储,不是简单的「采了存了就行」。你得想清楚:采什么?怎么采?存哪里?怎么保证安全?这四个问题想明白了,你的回放数据质量就稳了。

好了,这节课就到这里。下一节我们聊聊数据清洗与预处理,到时候我会分享一个我亲手写的清洗脚本,保证让你少走弯路。

可可精品资料库