社交网络存储的实践与演进

122 阅读4分钟

一、背景与挑战

在社交网络场景中,用户、视频、商品等实体可抽象为图模型中的,而点赞、收藏、关注等交互关系则构成。早期系统采用 MySQL 存储这些关系数据,但随着业务快速增长,面临以下核心问题:

  1. 读写性能瓶颈:社交场景下读请求占比高达 99%,传统关系型数据库难以支撑高并发读压力。

  2. 缺乏图模型语义:业务需要自己做点边相关语义转化,迭代与维护成本极高。

  3. 一致性难题:双向关系存储、度数计数的需求等业务需求引入了数据不一致风险。

为应对上述挑战,参考 Facebook TAO 架构设计理念,采用Redis+MySQL的两级写穿透架构,在DAU增长数倍的情况下显著降低了总核数的开销,实现了性能与成本的双重突破。

二、核心架构设计

1. 分层存储模型

采用三级分层写穿透架构,通过缓存层屏蔽存储层复杂性。

路由层:负责数据分片,将请求按照分片键进行哈希运算,如crc16%16383,后转发给对应槽位所在的Redis进程。

缓存层

  • 从节点:一级缓存,提供低延迟读服务,响应大部分读请求,同时与主节点组成replica。
  • 主节点:二级缓存,通过Redis cluster组织数据分片,主从节点间通过gossip实现高可用。

存储层

  • MySQL Proxy :封装分片路由与事务协调逻辑,支持简单的单机事务。
  • MySQL 集群:采用分库分表存储全量数据,通过 CDC 链路同步跨 AZ 数据。

2. 常见缓存问题应对

雪崩防护

  • 缓存对象创建时加入随机 TTL 偏移,避免数据同时大批量过期。
  • 多活部署备机集群,当主节点不可用时秒级切换。

缓存穿透

  • 在初始化阶段检查请求,若含非法参数则直接返回报错。
  • 引入缓存对象状态机,如已删除,已添加等拦截无效请求。

热点击穿

  • 设置更长的过期时间,例如天,周级别的TTL。
  • 结合协程,引入对象粒度的队列,大量请求到来时做限流与等待。

三、历史遗留问题与重构方案

1. 度数维护

在社区的业务场景中,存在着读写点与边的需求,为了保证读取效率点与边分表存储,两者存在一致性问题;此外度数请求QPS达到百万级,若频繁淘汰数据负担将极大。

解决方案

  • 热点隔离:将度数数据迁移至 Redis 独立 DB,并设置周级 TTL,避免 LRU 淘汰。
  • 单机事务:在分表键一致的场景下,实现可重复读隔离级别的单机事务,容忍幻读以换取性能。
  • CDC 同步:带版本号的 CDC 链路保证缓存层与存储层的最终一致性。

2. 双向同步

跨分片挑战

双向边因分片策略分布在不同数据分片,无法原子化更新。

解决方案

采用异步队列 + CDC 兜底策略:

  • 正边写入成功后,将反边写入任务加入异步队列,超时则通过 CDC 订阅 binlog 触发幂等操作。
  • 网络异常时熔断队列,依赖 CDC 保证最终一致性。

3. 更新类型

乱序问题

若由业务自主增删对象,会导致对象间时间上乱序,体现为用户的收藏夹内乱序问题。

解决方案

由于分片逻辑的存在,此问题类似于双向同步,均需要跨缓存分片,此时由于涉及新旧两个对象,需要约定全局顺序来避免死锁问题。

五、未来架构演进方向

1. 分层存储优化

引入 RocksDB 作为冷热数据中间层,替代部分 Redis 存储,热数据驻留 Redis,冷数据落盘 RocksDB,利用顺序写优势提升写入性能,适用于更多的工作负载场景。

4. 数据模型重构

利用宽表等数据结构,将点与边数据合并存储,减少跨表查询,提升多跳查询效率;进一步支持动态字段扩展,降低业务迭代成本。

5. 中心化管控与弹性扩展

根据负载扩缩容主从比,提升资源利用率;通过中心化服务管理分片、路由等信息,简化运维复杂度。

参考资料

  1. TAO: Facebook's Distributed Data Store for the Social Graph
  2. Redis集群规范
  3. Redis Proxy