存储是Feed流系统的核心之一。Feed流系统中需要存储的内容分为两部分:账号关系(例如关注列表)、Feed消息内容。

设计思路

Feed流存储系统有几个问题是设计的关键:
  • 如何能支持100TB,甚至PB级数据量?
  • 数据量与成本成正比,如何能降低成本?
  • 如何保证账号关系和Feed不丢失?

账号关系

账号关系特点
  • 变长链表,长度可达亿级别。
  • 数据量大,但关系简单。
  • 性能敏感。直接影响关注、取关的响应速度。
  • 有序性。不要求具有排序功能,只需要能按照主键排序即可。只要能按照主键排序,那么关注列表和粉丝列表的顺序就固定、可预期。

存储方案

根据以上特点,最适合存账号关系(关注列表)的方案应该是分布式NoSQL数据库,其中包括:

  • 开源HBase
    很多企业选择开源HBase来存储账号关系。开源HBase在满足了上述四个特征的同时可以把系统搭建起来,但是仍会有一些问题:
    • 需要自己运维、调查问题、修复问题,运维成本高。
    • GC会导致比较大的毛刺,影响用户体验。
  • 表格存储
    阿里云的表格存储也属于有序性的分布式NoSQL数据库,很多知名的系统选择了使用表格存储。表格存储具有以下优势:
    • 单表支持10万亿行+、10PB+的数据量,再快的数据增长速度都无需担心。
    • 数据按主键列排序,可保证有序性和可预期性。
    • 单key读写延迟在毫秒级别,可保证关注、取关的响应时间。
    • 是全托管的分布式NoSQL数据库服务,无需任何运维。
    • 全部采用C++ 实现,彻底无GC问题,不会由于GC而导致较大的毛刺。

以上可见,使用表格存储来存储账号关系是一个比较好的选择。

Feed消息

Feed消息特点

  • 数据量大,而且在Feed流系统的写扩散(推模式)模式下数据量会再膨胀几个数量级,所以数据量很容易达到100TB,甚至PB级别。
  • 数据格式简单。
  • 数据可靠性要求高,不能丢失数据。
  • 需保证个人发的Feed的消息ID在个人发件箱中都是严格递增的,这样读取时只需要一个范围读取即可。由于个人发布的Feed并发度很低,用时间戳也能满足基本需求,但是当应用层队列堵塞,网络延迟变大或时间回退时,用时间戳还是无法保证严格递增。最好的方法是适用主键自增功能。

存储方案

根据Feed消息特点,Feed消息的最佳的存储系统应该是具有主键自增功能的分布式NoSQL数据库,但是在开源系统里面没有完全符合特点的数据库,所以有两种存储方法:

  • 关系型数据库 + 分库分表
    目前有很多用户选择了关系系数据库+ 分库分表。虽然这个架构可以运行,但是存在一些问题:
    • 分库分表带来了运维复杂性。
    • 分库分表带来了逻辑层和数据层的极大耦合性。
    • 关系型数据库的主键自增功能性能差,例如开源MySQL数据库。不管是用MyISAM还是InnoDB引擎,要保证自增ID严格递增,必须使用表锁。表锁粒度大,会严重限制并发度,影响性能。
    • 关系型数据库的可靠性低于非关系型。关系型数据库的可靠性通常最多6个9,远低于分布式数据库,低4到5个级别。
  • 表格存储
    基于上述原因,一些技术公司开始考虑使用表格存储。表格存储是一个具有自增主键功能的分布式NoSQL数据库,这样就只需要使用一种系统,除此之外表格存储还有以下优势:
    • 单表可达10PB、10万亿行。
    • 10个9的SLA保障Feed内容不丢失。
    • 天然分布式数据库,无需分库分表
    • 两种实例类型:高性能实例可提供极佳的读写性能;容量型实例可提供低存储成本。
    • 主键自增功能性能佳。其他系统的自增功能都需要加锁,但表格存储完全不需要加锁,包括表锁和行锁。

通过对比分析,表格存储在功能、性能、扩展性以及成本方面都要更加适合存储Feed消息。