19.5 Facebook中的Hadoop和HBase

众所周知,Facebook是目前世界上最大的社交网站。从2004年创建之初的以服务学生为目的的局部交互网站发展到2009年世界范围内的综合社交网站,服务8亿多人群,而现在它已经剑指移动服务、搜索服务、网络直播等综合网络服务提供领域,旨在发展成为综合性网络服务商。

Facebook作为全球性社交网站,拥有约8亿活跃用户,其每天产生的数据非常庞大。下面简单列举一些统计数据(截至2011年9月):

把Facebook用户群作为一个国家,它会成为世界人口第三大国家;

Facebook用户在网站上已上传了1400亿余张照片;

每天上网的人中有44%访问了Facebook,它是继Google之后访问率第二高的网站;

Facebook用户每20分钟发表1200万条评论,每个月分享300亿条内容;

上面这些统计数据背后都意味着Facebook面临着海量的数据存储。用户群的资料需要维护,用户分享的照片、发表的评论、分享的内容都需要存储,用户访问历史需要进行分析处理,同时还需要对原始数据进行提取、反馈给用户等。这些虽然并不简单,但在巨大用户群和使用率面前,都将成为典型的海量数据存储和处理任务。那么Facebook到底面临哪些海量数据的任务?它为什么使用Hadoop+HBase?它是否有所创新或者改进?下面将一一解答这些问题。

19.5.1 Facebook中的任务特点

Facebook的巨大用户群和使用率为其带来了高效存储海量数据的挑战。下面我们从Facebook中一些关键性技术的任务特点出发,介绍Facebook在存储海量数据时必须满足的一些特性。

1.Facebook消息机制

Facebook的消息机制为每一个用户提供一个“facebook.com”的邮箱地址,它负责整合用户或组之间的邮件、SMS(Short Message Service)以及聊天记录。该机制是Facebook收件箱的基础,需要管理“消息从哪位用户发往哪位用户”。该新型应用程序不但需要能够适应同时为超过5亿用户提供服务,还需要达到PB级数据的吞吐以及长时间不间断运行的需求。除此之外,新的线程模型同样需要系统能够存储每一个参与用户的消息。每一个用户需要依附于某一个数据中心。

这个机制的服务内容决定了它每天需要处理数十亿的即时消息及数百万的系统消息,而这些消息的特点又决定了该机制有如下特点:

1)高写吞吐量:由于每时每刻都有成千上万消息产生,那么每天数据的插入量将会非常大,并且会持续性地增长。

2)数据的增量存储:从该机制的特性不难发现,消息机制一般很少涉及删除操作,除非用户显式地发出该请求。此外,每一个用户的收件箱将可能无限量地增长。另外,对于每条消息记录,一般只会在近期被读有限的次数,从长远来讲很少再次查看。因此,大部分的数据不会再次被读到,但是由于存在用户访问的可能性,Facebook需要保证这部分数据一直处于可用状态。在据图存储这一类的数据,Facebook以用户为主键来建立索引,在索引之下存储该用户的线程和消息记录。

3)数据迁移:由于消息机制进行更新,采用新的系统以及数据模型,这就意味着Facebook需要将数据从原数据库中进行分离并迁移到新的数据库中。那么支持大范围扫描、随机访问以及快速大数据块导入操作的系统将会大大减少用户数据迁移的时间。

2.Facebook Insights

Facebook Insights为开发者以及网站管理员提供了关于Facebook站点之间活动实时分析的接口,包括社会网络插件、Facebook页面以及Facebook广告。通过这些匿名化的数据,一些商业用户可以对Facebook的情况有深入的了解,例如印象(impression)、点击率、网页访问次数等。通过这些信息,商业用户可以对自己的服务进行改进。

从这个技术的服务内容来看,Facebook Insights团队想要为用户提供短时间内用户活动的统计信息,也就是在海量统计信息上的实时数据分析。这将需要Facebook能够提供大规模的、异步排队的系统,并使用系统对事件进行处理、存储和聚合操作。该系统应具备较高的容错性,且支持每秒成千上万个事件的并发操作。

3.Facebook度量系统

在Facebook中,系统中的所有软硬件需要将自身的统计信息存储到ODS(Operations Data Store)中。例如,记录某一个服务器或某一组服务器中的CPU使用率;或者,存储对数据集群的写操作记录。这些操作将对写吞吐量有很高的要求。这要求系统应具备如下特点:

1)自动分区:大量的索引以及时序写操作再加上不可预知的数据量的增长,这使得采用sharding模式的MySQL数据库难以应付,甚至需要管理人员人为地对数据进行分片。

2)快速读取最近数据并执行表扫描:在Facebook很多的操作仅仅涉及最近的数据,对较早的数据访问较少,但是之前的数据也同样不能丢失,必须保证其处于可用状态。例如邮件服务、消息服务等。同时,这些操作还要求对最近的数据具有较快的查询速度。

结合具体技术特点的介绍和社交网络网站共有的一些特点,Facebook中任务特点对存储系统的需求可以总结为如下几个方面:

(1)灵活性

由于用户的增加以及市场的拓展,Facebook要求存储系统能够支持对系统容量的增量扩充,并且要求该操作所带来的额外开销要最小化,同时应避免该操作所带来的停机问题。例如,在某些情况下,Facebook可能需要能够快速地增加系统的容量,并且要求系统能够自动地处理新旧硬件之间的负载均衡和利用率的问题。

(2)高的写吞吐量

在Facebook中有很多的应用程序需要存储大量的数据,而对读的需求相对要低。因此,Facebook对写操作有较高的要求。

(3)高效低延迟的强一致性数据中心

在Facebook中有很多非常重要的应用程序(如消息),它们对数据的一致性有很高的要求。例如,在用户主页上显示的“未读”消息数目需要与收件箱中实际的“未读”消息总数一致,然而实现一个全球化的分布式强一致性存储系统确实不可能,只有当数据位于同一个数据中心之内,提供强一致性的数据存储才变得稍有可能。

(4)高效的磁盘随机读

尽管应用程序级别的缓存(嵌入式或见解缓存)得到了广泛的应用和发展,在Facebook,仍然有很多的访问不能命中缓存中的数据,而必须访问后端的数据库系统。

(5)高可用性

Facebook需要为用户提供一种能够长时间不间断的服务,这些服务应该能够处理计划内的和计划外的事件(例如软件更新、硬件或容量扩充以及硬件故障)。此外,Facebook还需要能够容忍数据中心少量数据的丢失以及在某一可允许的时间范围内向其他数据中心进行数据备份。

(6)容错性

Facebook中对于长时间的MySQL数据库的运维经验显示故障隔离是非常重要的。如果某一个数据库发生故障,那么在Facebook中要求只有很少一部分用户会受到该事件的影响。

(7)原子“读-修改-写”原语

原子的增量以及比较和交换API在创建无锁并发应用程序中非常有用,同时也是底层存储系统必须支持的操作。

(8)范围扫描

某些应用程序需要支持某一范围内某些列集合的高效检索。例如,检索某一用户最近的100条消息记录或者计算某一给定广告商在过去24小时内每小时的印象(impression)数。

同样Facebook中的任务也决定了它可以不强制要求下面几点:

1)单个数据中心内的网络分区容错性。不同的系统组件往往本身就是非常集中化的。例如,MySQL服务器很可能会集中地被放置在几个机架之内。单个数据中心内的网络分区故障将可能导致整个服务能力上的故障。因此,需要通过设置冗余网络来避免单个分区故障引起的系统不可用。

2)零故障率。从经验来看,大集群中机器故障是不可避免的。既然不存在这样的理想情况,那么必须对设计方案进行某种,也就是说,Facebook选择面对故障的机器并尽可能地降低宕机的概率。

3)跨数据中心的active-active服务能力。如前所述,Facebook假设用户的数据被存储在不同数据中心。因此,Facebook使用用户端的缓存来降低系统的延迟。