朋友圈存储从 600G 收口到 3G:位图与事件模型改造记录

朋友圈存储从 600G 收口到 3G:位图与事件模型改造记录

简单记录一次朋友圈存储治理:将原本约 600G 的明细模型切换为约 3G 的位图/事件模型,在保持业务结果一致的前提下,完成旧表停写、历史迁移和旧表清理。

下文表名、字段名均为示意代称,不对应线上真实命名。

问题现象

早期的朋友圈可见范围和互动数据,主要通过两张明细表保存:

  • t_visible_snapshot_v1(发布前可见明细)
  • t_visible_snapshot_v2(发布后可见明细)

随着朋友圈数量和客户数量增长,旧模型逐渐暴露出几个问题:

  • 客户关系逐行存储,数据量持续膨胀。
  • 发布前 / 发布后两套明细存在大量重复。
  • 索引维护、WAL、vacuum 和备份成本不断增加。
  • 读写链路长期维护 old/new 两套模型,查询和排障复杂。

问题的本质不是 SQL 不够快,而是用明细行表达集合的成本太高。

新模型设计

1. 可见关系改为位图

新模型使用 t_visible_bitmap 保存可见关系,核心字段可理解为:

  • bitmap_before:创建时可见客户集合
  • bitmap_pending:发布后仍未触达的客户集合

触达客户集合通过差集计算:

touched = bitmap_before - bitmap_pending

这样无需在“发布后明细表”中重复保存完整客户明细。

2. 点赞、评论改为事件表

点赞和评论统一写入 t_interact_event,独立保存朋友圈、客户、互动类型和互动时间。

新旧模型对比如下:

对比项 旧模型 新模型
可见关系 客户明细逐行存储 位图集合
未触达关系 独立明细记录 差集位图
点赞/评论 附着在明细记录上 独立事件表
写入链路 old/new 双写 只写新模型
查询链路 两套明细表 bitmap + event

改造过程

本次按“先切读、再切写、后清理”的顺序推进:

  1. 将页面、接口、报表查询切换到位图和事件模型。
  2. 停止旧表双写,分别写入位图快照、差集位图和互动事件。
  3. 分批把历史明细转换为位图和事件,按批次记录进度并校验结果。
  4. 确认代码、配置、数据库对象和运行日志不再依赖旧表后,删除旧表索引及表本体。

结果验证

存储空间

对象 改造前 改造后
朋友圈旧明细模型 约 600G -
可见位图表 - 约 2.6G
互动事件表 - 约 32MB
新模型合计 - 约 3G

业务主承载空间由约 600G 收口到约 3G,减少约 597G。旧索引清理阶段先释放约 300G,旧表清理后完成剩余空间回收。

业务一致性

抽样验证了以下结果:

  • 创建时可见客户集合一致。
  • 发布后未触达客户集合一致。
  • 已触达、未触达统计口径一致。
  • 点赞、评论数量和互动时间保持可查询。

因此,这次改造不是简单删除历史数据,而是用新的数据模型无损替代旧模型。

总结

朋友圈这次优化的关键,不是清理了多少行数据,而是改变了数据表达方式:

明细行集合 -> 位图集合
重复明细   -> 差集计算
互动附着   -> 独立事件

当大表已经进入数百 GB 规模时,继续加索引、调 SQL 往往只能缓解局部问题。让存储结构与业务语义匹配,才是实现 600G -> 3G 收口的核心。