为Dashboard收件箱设计的Cell架构
现在支持Dashboard的功能的分散-集中架构非常受限,这种状况不会持续很久。
解决方法是采用基于Cell架构的收件箱模型,与Facebook Messages非常相似。
收件箱与分散-集中架构是对立的。每一位用户的dashboard都是由其追随者的发言和行动组成的,并按照时间顺序存储。
就因为是收件箱就解决了分散-集中的问题。你可以会问到底在收件箱中放了些什么,让其如此廉价。这种方式将运行很长时间。
重写Dashboard非常困难。数据已经分布,但是用户局部升级产生的数据交换的质量还没有完全搞定。
数据量是非常惊人的。平均每条消息转发给上百个不同的用户,这比Facebook面对的困难还要大。大数据+高分布率+多个数据中心。
每秒钟上百万次写入,5万次读取。没有重复和压缩的数据增长为2.7TB,每秒百万次写入操作来自24字节行键。
已经流行的应用按此方法运行。
cell
每个cell是独立的,并保存着一定数量用户的全部数据。在用户的Dashboard中显示的所有数据也在这个cell中。
用户映射到cell。一个数据中心有很多cell。
每个cell都有一个HBase的集群,服务集群,Redis的缓存集群。
用户归属到cell,所有cell的共同为用户发言提供支持。
每个cell都基于Finagle(Twitter推出的异步的远程过程调用库),建设在HBase上,Thrift用于开发与firehose和各种请求与数据库的链接。(请纠错)
一个用户进入Dashboard,其追随者归属到特定的cell,这个服务节点通过HBase读取他们的dashboard并返回数据。
后台将追随者的dashboard归入当前用户的table,并处理请求。
Redis的缓存层用于cell内部处理用户发言。
请求流:用户发布消息,消息将被写入firehose,所有的cell处理这条消息并把发言文本写入数据库,cell查找是否所有发布消息追随者都在本cell内,如果是的话,所有追随者的收件箱将更新用户的ID。(请纠错)
cell设计的优点:
大规模的请求被并行处理,组件相互隔离不会产生干扰。 cell是一个并行的单位,因此可以任意调整规格以适应用户群的增长。
cell的故障是独立的。一个Cell的故障不会影响其他cell。
cell的表现非常好,能够进行各种升级测试,实施滚动升级,并测试不同版本的软件。
关键的思想是容易遗漏的:所有的发言都是可以复制到所有的cell。
每个cell中存储的所有发言的单一副本。 每个cell可以完全满足Dashboard呈现请求。应用不用请求所有发言者的ID,只需要请求那些用户的ID。(“那些用户”所指不清,请指正。)他可以在dashboard返回内容。每一个cell都可以满足Dashboard的所有需求,而不需要与其他cell进行通信。
用到两个HBase table :一个table用于存储每个发言的副本,这个table相对较小。在cell内,这些数据将与存储每一个发言者ID。第二个table告诉我们用户的dashboard不需要显示所有的追随者。当用户通过不同的终端访问一个发言,并不代表阅读了两次。收件箱模型可以保证你阅读到。
发言并不会直接进入到收件箱,因为那实在太大了。所以,发言者的ID将被发送到收件箱,同时发言内容将进入cell。这个模式有效的减少了存储需求,只需要返回用户在收件箱中浏览发言的时间。而缺点是每一个cell保存所有的发言副本。令人惊奇的是,所有发言比收件箱中的镜像要小。(请纠错)每天每个cell的发言增长50GB,收件箱每天增长2.7TB。用户消耗的资源远远超过他们制造的。
用户的dashboard不包含发言的内容,只显示发言者的ID,主要的增长来自ID。(请Tumblr用户纠错)
当追随者改变时,这种设计方案也是安全的。因为所有的发言都保存在cell中了。如果只有追随者的发言保存在cell中,那么当追随者改变了,将需要一些回填工作。
另外一种设计方案是采用独立的发言存储集群。这种设计的缺点是,如果群集出现故障,它会影响整个网站。因此,使用cell的设计以及后复制到所有cell的方式,创建了一个非常强大的架构。
一个用户拥有上百万的追随者,这带来非常大的困难,有选择的处理用户的追随者以及他们的存取模式(见Feeding Frenzy