大数据挑战

日志表爆炸的那天 💥

早上九点,我打开监控面板,看到红色的警告灯在疯狂闪烁。

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 里保存业务事实,而不是把规则散落在应用逻辑里。
  • 查询目标是用短码快速找到目标链接、状态或统计结果,避免在跳转路径上做大范围扫描。
  • 这里要读的是执行计划结论:有没有命中索引、扫描行数是否可控、是否出现全表扫描。
  • 关键字段包括 idshort_codeipcountrycitydevicebrowseros,它们决定了后续查询和管理能力。

分区表的好处:

  1. 查询快: 只扫描相关分区
  2. 删除快: 删整个分区比逐行删除快 100 倍
  3. 维护方便: 可以单独优化某个分区

自动分区管理

分区维护也要流程化,重点是每月提前准备新分区:

落地思路

  • 这里省略具体语法,只保留设计层面的职责边界。
  • 读这段时重点看:输入是什么、系统做哪些判断、状态如何变化、失败时如何兜底。

数据压缩的艺术 🗜️

冷数据搬到 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 倍! ⚡

但成本不是唯一的考虑因素。数据分层还带来了:

  1. 查询速度: 热数据查询从 30 秒降到 0.3 秒
  2. 系统稳定性: MySQL 不再因为磁盘满而宕机
  3. 扩展性: S3 理论上可以存无限数据
  4. 合规性: 冷数据归档可以永久保存,满足审计要求

从冷数据恢复 🔄

有一天,客户问我:“能查下去年 12 月的完整点击记录吗?”

我淡定地打开 S3 浏览器,找到对应的归档文件,下载、解压、导入临时表。

落地思路

  • 这里省略具体语法,只保留设计层面的职责边界。
  • 读这段时重点看:输入是什么、系统做哪些判断、状态如何变化、失败时如何兜底。

30 秒后,我给客户发了完整的 Excel 表格。客户很惊讶:“这么快!”

我笑了笑,心里想:数据分层不只是省钱,更是让系统可持续

新的商机 💡

数据问题搞定了,但我发现一个有趣的现象:

有些用户愿意付费来获取更详细的统计数据。比如:

  • 某电商客户想知道:“哪个国家的点击量最高?”
  • 某自媒体博主问:“我的粉丝在哪些城市最活跃?”
  • 某广告代理商需要:“每小时点击趋势图”

这些查询都需要访问冷数据,但用户愿意为此付费。

我看着账本上的数字,脑子里冒出一个想法:是不是可以推出付费高级分析功能?


👉 下一章:自定义短链接 —— 用户可以自定义短链接后缀,但这个功能带来了新的技术挑战…