大数据挑战
日志表爆炸的那天 💥
早上九点,我打开监控面板,看到红色的警告灯在疯狂闪烁。
click_logs 表突破 5000 万条记录了。磁盘占用飙到 40GB。我试着查询上周的数据统计,进度条慢悠悠地爬了 30 秒才返回结果。
我盯着屏幕,意识到一个残酷的事实:按照这个增长速度,三个月后数据库就要爆炸了。
当前数据量:
- 每天点击: 100 万次
- 每条日志: 500 字节
- 每天新增: 500MB
- 一年累积: 180GB
存储增长曲线:
Month 1: 15GB
Month 3: 45GB ← 查询开始变慢
Month 6: 90GB ← 数据库扛不住了
Month 12: 180GB ← 💥我翻着 AWS 账单,看着 RDS 的存储成本一路飙升。我知道,必须做数据分层了。
冷热数据分离 🌡️
那天晚上我先把统计链路画出来:跳转服务只负责产生点击事件,真正的大数据处理交给队列、实时聚合和离线分析。
然后我把数据按照访问频率分成三类:
数据温度分布:
🔥 热数据(最近 7 天)
占比: 2% 访问频率: 80%
查询特点: 实时统计、活跃短链接监控
存储: Redis + MySQL
这些数据是用户最常看的——今天点击了多少、最近一周的趋势。
必须毫秒级响应,放在 Redis 缓存里。
🌡️ 温数据(7 天 ~ 30 天)
占比: 8% 访问频率: 15%
查询特点: 周报、月报查看
存储: MySQL
用户偶尔要看上个月的统计数据,但不会频繁访问。
放在 MySQL 里,用索引优化查询。
❄️ 冷数据(30 天以上)
占比: 90% 访问频率: 5%
查询特点: 历史数据分析、合规审计
存储: 对象存储(S3)
这些数据几乎没人看,但不能删——可能要做年度总结,
或者有人问"去年 12 月的点击量是多少"。
压缩后扔到 S3,成本只有 MySQL 的 1/10。核心理念: 80% 的查询只看 2% 的数据。把冷数据搬走,热数据跑得飞快。
归档方案实现
我把冷数据归档做成每天凌晨的固定流程:
落地思路
- 这里省略具体语法,只保留设计层面的职责边界。
- 读这段时重点看:输入是什么、系统做哪些判断、状态如何变化、失败时如何兜底。
第一次运行时,我看着日志输出,心跳加速:
🔍 查找 2024-01-15 之前的数据...
📦 找到 42,356,789 条记录需要归档
📤 已归档 50,000/42,356,789 条记录
📤 已归档 100,000/42,356,789 条记录
...
✅ 归档完成! 删除了 42,356,789 条记录,释放了 20.2 GB 空间MySQL 表从 5000 万条记录降到了 700 万条,查询速度从 30 秒降到了 0.3 秒。
快了 100 倍。
数据分区优化 📂
归档解决了存储问题,但 MySQL 表还有 700 万条记录。我学会了分区表——按日期分区,查询时只扫描相关分区。
数据设计要点
- 核心是在
click_logs_partitioned里保存业务事实,而不是把规则散落在应用逻辑里。- 查询目标是用短码快速找到目标链接、状态或统计结果,避免在跳转路径上做大范围扫描。
- 这里要读的是执行计划结论:有没有命中索引、扫描行数是否可控、是否出现全表扫描。
- 关键字段包括
id、short_code、ip、country、city、device、browser、os,它们决定了后续查询和管理能力。
分区表的好处:
- 查询快: 只扫描相关分区
- 删除快: 删整个分区比逐行删除快 100 倍
- 维护方便: 可以单独优化某个分区
自动分区管理
分区维护也要流程化,重点是每月提前准备新分区:
落地思路
- 这里省略具体语法,只保留设计层面的职责边界。
- 读这段时重点看:输入是什么、系统做哪些判断、状态如何变化、失败时如何兜底。
数据压缩的艺术 🗜️
冷数据搬到 S3 后,我做了个实验——看看不同压缩方式的效果。
落地思路
- 这里省略具体语法,只保留设计层面的职责边界。
- 读这段时重点看:输入是什么、系统做哪些判断、状态如何变化、失败时如何兜底。
测试结果让我惊喜:
method original_size_kb compressed_size_kb compression_ratio space_saved
0 Gzip 1024.0 102.4 10.00% 90.0%
1 LZMA 1024.0 68.3 6.67% 93.3%
2 Zlib 1024.0 128.0 12.50% 87.5%LZMA 压缩率最高,能节省 93% 的空间。但压缩速度慢,适合归档场景。Gzip 是折中方案,压缩率和速度都不错。
实际压缩效果
我统计了生产环境的压缩效果:
原始数据: 42,356,789 条 × 500 字节 = 20.2 GB
压缩后:
- Gzip: 2.0 GB (压缩率 10:1)
- LZMA: 1.4 GB (压缩率 14:1)
S3 存储成本:
- 标准: ¥0.18/GB/月
- 归档: ¥0.025/GB/月
月成本对比:
- MySQL 存储: ¥18/月 × 20GB = ¥360/月
- S3 归档(LZMA): ¥0.025 × 1.4GB = ¥0.035/月
节省了 99%! 💰成本分析 💰
我把数据分层前后的成本做了个详细对比:
【方案 A: 全放 MySQL】
存储: 50GB × ¥1.5/GB/月 = ¥75/月
问题:
- 查询越来越慢
- 备份时间长
- 磁盘快满了
- 扩容成本高
月成本: ¥75 💸
【方案 B: 冷热分离】
热数据(MySQL): 7 天 × 500MB/天 = 3.5GB × ¥1.5 = ¥5.25/月
温数据(MySQL): 23 天 × 500MB/天 = 11.5GB × ¥1.5 = ¥17.25/月
冷数据(S3 归档): 335 天 × 500MB/天 × 10%压缩 = 16.75GB × ¥0.025 = ¥0.42/月
月成本: ¥22.92 💰
【节省】
¥75 - ¥22.92 = ¥52.08/月
一年节省: ¥625/年
而且查询速度快了 100 倍! ⚡但成本不是唯一的考虑因素。数据分层还带来了:
- 查询速度: 热数据查询从 30 秒降到 0.3 秒
- 系统稳定性: MySQL 不再因为磁盘满而宕机
- 扩展性: S3 理论上可以存无限数据
- 合规性: 冷数据归档可以永久保存,满足审计要求
从冷数据恢复 🔄
有一天,客户问我:“能查下去年 12 月的完整点击记录吗?”
我淡定地打开 S3 浏览器,找到对应的归档文件,下载、解压、导入临时表。
落地思路
- 这里省略具体语法,只保留设计层面的职责边界。
- 读这段时重点看:输入是什么、系统做哪些判断、状态如何变化、失败时如何兜底。
30 秒后,我给客户发了完整的 Excel 表格。客户很惊讶:“这么快!”
我笑了笑,心里想:数据分层不只是省钱,更是让系统可持续。
新的商机 💡
数据问题搞定了,但我发现一个有趣的现象:
有些用户愿意付费来获取更详细的统计数据。比如:
- 某电商客户想知道:“哪个国家的点击量最高?”
- 某自媒体博主问:“我的粉丝在哪些城市最活跃?”
- 某广告代理商需要:“每小时点击趋势图”
这些查询都需要访问冷数据,但用户愿意为此付费。
我看着账本上的数字,脑子里冒出一个想法:是不是可以推出付费高级分析功能?
👉 下一章:自定义短链接 —— 用户可以自定义短链接后缀,但这个功能带来了新的技术挑战…