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 知识体系总览
下面这张图,是我自己画的,把数据采集与存储的核心逻辑串起来了。你一看就明白。
这张图的核心逻辑是:数据从源头来,经过采集、存储、脱敏三道关,最终变成高质量的回放数据。每一步都有坑,每一步都需要你用心设计。
总结一句话:数据采集与存储,不是简单的「采了存了就行」。你得想清楚:采什么?怎么采?存哪里?怎么保证安全?这四个问题想明白了,你的回放数据质量就稳了。
好了,这节课就到这里。下一节我们聊聊数据清洗与预处理,到时候我会分享一个我亲手写的清洗脚本,保证让你少走弯路。