论文阅读: TAO:Facebook的社交图谱的分布式数据存储(三)

312 阅读21分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

论文阅读: TAO:Facebook的社交图谱的分布式数据存储(三)

因为从数据库较旧,所以The slave storage被LRU的话,数据可能是旧的。但是通常刚写的数据不会这么快被LRU。实际中,如果The slave storage配置LRU比Master Cache小很多,因为错误的运维配置,这种现象很容易发生,而且很难调查!如下图中,primary与secondary的LRU热度不一样,这是可能的,淘汰范围也不一样,导致某条数据需要从mysql读取,但是step 5还未到,导致读到了旧数据。我们在生产环境遇到类似的事故,这是非常困难的调查过程,直接阅读相关章节,看看Facebook架构师是如何看待这个事情,这很有意思,因为你发现自己平时遇到的bug,居然在论文中有被提及和讨论,另外这算是运维事故,我们应该在运维上避免这个事情发生,这至少要求:

1.完善的管理平台

2.监控系统

3.精心配置的报警机制,(如果没意义的告警时长被发出,则导致没人看告警了)

论文地址www.usenix.org/system/file…

image-20221215124738175

6.一致性

在正常操作下,TAO中的对象和关联最终是一致的[33, 35];在写操作后,TAO保证最终向所有层交付无效或重新填充操作。外部输入后,如果有足够的时间,TAO中的所有数据副本将是一致的,并反映出对所有对象和关联的所有成功写入操作。复制滞后通常小于一秒。

在正常操作中(一个请求最多遇到一次故障),TAO在单一层内提供读写一致性。TAO用本地写入的值同步更新缓存,当写入成功时,主领导者会返回一个变化集。这个变化集通过从属领导(如果有的话)传播到发起写查询的从属层。如果为一个关联配置了反转类型,那么对该类型的关联的写入可能会影响id1的和id2的分片。在这些情况下,主领导者返回的变化集包含这两个更新,从属领导者(如果有的话)和转发写的follower必须在返回给调用者之前将变化集发送到各自层的id2的分片上。

双边关系需要有两个更新,并在返回给客户端前完成这两个操作(到各自的分片上)

变更集不能总是安全地应用于follower的缓存内容,因为如果第二个follower的更新的填充或失效尚未交付,那么follower的缓存可能是过时的。在大多数情况下,我们用一个存在于持久化存储和缓存中的版本号来解决这个race condition。

版本号在每次更新时都会被递增,所以如果变化集显示其更新前的值是过时的,(因为对follower的更新不是简单地覆盖,缓存实现了所有TAO接口,所以发现版本号不对需要copy一遍)follower可以安全地使其数据的本地拷贝失效。

版本号不会暴露给TAO客户端。在slave region,这个方案容易受到缓存驱逐(LRU导致)和存储服务器更新传播之间罕见的race condition的影响。

The slave storage可能持有比缓存服务器所缓存的数据更早的版本,所以如果更改后的条目被从缓存中驱逐,然后从数据库中重新加载,客户端可能会观察到一个值在单个从属层的时间上的倒退。

因为从数据库较旧,所以The slave storage被LRU的话,数据可能是旧的。但是通常刚写的数据不会这么快被LRU。实际中,如果The slave storage配置LRU比Master Cache小很多,因为错误的运维配置,这种现象很容易发生,而且很难调查!

这种情况只有在slave region的存储服务器接收更新的时间长于缓存项目从缓存中被驱逐的时间时才会发生,而这种情况在实践中是很少见的。

虽然TAO不为其客户提供强一致性,但由于它同步写入MySQL,主数据库是一个一致的真相来源。这使我们能够为需要一致性的一小部分请求提供更强的一致性。TAO的读取可能被标记为关键,在这种情况下,它们将被代理到主区域。我们可以在认证过程中使用关键读数,例如,这样复制滞后就不允许使用过时的证书。

6.1 故障检测和处理

TAO可以扩展到多个图形位置的数千台机器,因此瞬时和永久性故障是很常见的。因此,TAO检测潜在的故障并绕过它们是很重要的。TAO服务器采用积极的网络超时,以避免继续等待可能永远不会出现的响应。每个TAO服务器维护每个目的地的超时,如果有几个连续的超时,就将主机标记为停机,并记住停机的主机,以便主动中止后续请求。这种简单的故障检测器工作得很好,尽管它并不总是在断电的情况下保持全部容量,例如限制TCP吞吐量的突发性数据包掉落。在检测到故障的服务器后,TAO以最大努力的方式绕过故障,以保持可用性和性能的一致性为代价。我们主动探测故障机器,以发现它们何时(如果)恢复。

数据库故障。在全局配置中,如果数据库崩溃,或因维护而停用,或从主数据库复制而落后太多,数据库就会被标记下来。当一个如果主数据库发生故障,它的一个从属数据库会自动晋升为新的主数据库。当一个区域的从属数据库发生故障时,缓存缺失会被重定向到托管数据库主站的区域内的TAO领导。然而,由于缓存一致性信息被嵌入到数据库的复制流中,它们不能被主机制传递。在从属数据库停机期间,在主数据库上运行一个额外的binlog tailer,并在区域间传递重新填充和失效信息。当从属数据库恢复时,停电时的无效和重新填充信息将再次被传送。

领导者失败。 当一个领导者的缓存服务器发生故障时,跟随者会自动在它周围路由读和写请求。跟随者将未读请求直接转发到数据库。与此相反,对一个失败的领导者的写请求会被重新路由到领导者层的一个随机成员。这个替换的领导者执行写和相关的动作,比如修改反向关联和向跟随者发送无效信息。替换的领导者也会排队向原领导者发出异步失效,以恢复其一致性。这些异步失效被记录在协同节点上,并插入到复制流中,在那里它们被储存起来,直到领导者变得可用。如果失效的领导者是部分可用的,那么在领导者的一致性被恢复之前,后面的人可能会看到一个陈旧的值。

refill和invalidation失败。领导者以异步方式发送补发和失效信息。如果follower无法到达,领导者会将消息排入磁盘,以便在稍后的时间交付。请注意,如果这些消息由于每个领导者的失败而丢失,那么跟随者可能会留下陈旧的数据。这个问题可以通过一个批量失效操作来解决,该操作会使一个分片id的所有对象和as-sociations失效。在一个失败的领导被替换后,所有映射到它的分片必须在跟随者中被无效化,以恢复一致性。

follower失败。在TAO follower失败的情况下,其他层的follower分担为失败主机的分片服务的责任。我们为每个TAO客户端配置了一个主要的和备用的follower层。在正常操作中,请求只被发送到主服务器。如果为某一特定请求托管分片的服务器由于超时而被标记下来,那么该请求将被发送到备份层中该分片的服务器。因为故障转移请求仍然会被发送到托管相应分片的服务器上,它们是完全可缓存的,不需要额外的一致性工作。来自客户端的读和写请求也以同样的方式进行故障转移。请注意,在不同层之间的故障转移可能会导致写后读的一致性被违反,如果读在写的重新填充或无效之前到达故障转移目标。

image-20221215124014975

图3:所有Facebook产品对TAO的客户端请求的相对频率。读取几乎占了所有对API的调用。

7 生产环境的工作负载类型

Facebook有一个生产中的TAO实例。像TAO这样的多租户系统使我们能够摊薄运营成本,并在客户之间分享多余的能力。它也是快速产品创新的一个重要因素,因为新的应用程序可以与现有的数据相连接,而且当一个应用程序从一个用户增长到数以亿计时,不需要移动数据或亲视服务器。多租户对对象特别重要,因为它允许统一处理整个64位id空间,而不需要额外的步骤来解决otype。

TAO系统包含许多follower层,分布在几个地理区域。每个地区都有一套完整的数据库,一个领导者缓存层,以及至少两个跟随者层。我们的TAO部署每秒钟持续处理10亿次读取和数百万次写入。我们不知道是否有另一个如此规模的地理分布式图形数据存储。

为了描述TAO的工作量,我们在40天内随机抽取了650万个请求。在本节中,我们将描述对该样本的分析结果。

在高层次上,我们的工作负荷显示出以下特点。

• 读取比写入要频繁得多

• 大多数边缘查询的结果为空;以及

• 查询频率、节点连通性和数据大小具有长尾的分布。

图3分解了TAO上的负载。读取占主导地位,只有0.2%的请求涉及写入。大多数关联读取的结果是空的关联列表。对assoc get的调用只有19.6%的时间找到了关联,在我们的跟踪中,对assoc range的调用有31.0%的结果不是空的,对assoc time range的调用只有1.9%返回任何边。

图4显示了assoc计数的返回值的分布。45%的调用返回0。在非零值中,虽然小值是最常见的,但有1%的返回值 > 500 , 000。

image-20221215124043994

image-20221215124055876

图5:assoc范围和assoc时间范围查询所返回的边的数量。64%的非空结果有1条边,其中13%的限制为1。

图5显示的是在范围和时间范围查询中返回的关联,以及在返回的关联中达到极限的子集。大多数范围和时间范围的查询有很大的客户提供的限制。12%的查询有limit = 1,但是其余95%的查询有1000个限制。更少在限制为1的查询中,只有不到1%的返回值实际达到了限制。 尽管对不存在的关联的查询很常见,但对于对象来说却不是这样的。一个有效的ID只在对象创建过程中产生,所以obj get只能在对象被删除或者对象的创建还没有被复制到当前区域的情况下返回一个空结果。在我们的追踪中,这两种情况都没有发生;每个对象的读取都是成功的。这并不意味着对象从未被删除--它只是意味着从来没有尝试过读取一个被删除的对象。

图6显示了TAO查询结果的数据大小分布。客户端查询的关联中,39.5%不包含任何数据。我们的实现允许对象存储1MB的数据,关联存储64K的数据(尽管对于存储超过255字节数据的关联,必须配置一个自定义表)。大多数对象和关联的实际大小要小的多。然而,大数值的出现足够频繁,系统必须有效地处理它们。

image-20211202175833412

图6:TAO API返回的关联和对象中存储的数据大小。关联通常比对象存储的数据少得多。在返回的60.5%的关联中,平均关联数据大小为97.8字节,其中有一些数据。对象的平均数据大小为673字节。Figure 6: The size of the data stored in associations and objects that were returned by the TAO API. Associations typically store much less data than objects. The average association data size was 97.8 bytes for the 60.5% of returned associations that had some data. The average object data size was 673 bytes.

image-20221215124209767

图7:在我们的生产环境中,单个follower的吞吐量。缓存未命中和写入比缓存命中更昂贵,所以峰值查询率随着命中率上升。写入作为非命中请求包括在此图中。

8 性能

为整个Facebook运行单一的TAO部署,使我们能够从规模经济中受益,并使新产品能够很容易地与社交图的现有部分整合。在本节中,我们报告了TAO在实际工作负载下的性能。可用性。 在90天的时间里,从网络服务器上测得的TAO查询失败的比例为4 . 9 10−6。在解释这个数字时必须小心,因为一个TAO查询的失败可能会阻止客户发出另一个查询。在第一种情况下,动态数据的依赖性。TAO的故障也可能与其他依赖系统的故障相关。

image-20221215124115507

图8:客户观察到的TAO读取请求的延迟(以毫秒为单位),包括客户API开销和网络工作穿越,按高速缓存命中和高速缓存失误分开。

image-20211202180123999

图9:来自与数据库主站在同一区域的客户的写入延迟,以及来自58毫秒以外区域的写入延迟。

follower的容量。 一个follower的峰值吞吐量取决于它的命中率。图7显示了我们在生产中观察到的最高的15分钟平均吞吐量,我们目前的硬件配置有144GB内存,2个英特尔至强8核E5-2660处理器,运行在2.2Ghz的超线程,以及10个千兆以太网。

命中率和延时。 作为第7节中描述的数据收集过程的一部分,我们测量了客户端应用程序的延迟;这些测量包括所有的网络延迟和穿越PHP TAO客户端堆栈的时间。所有地区的请求都以相同的速率取样。TAO的总体读取命中率为96.4%。图8显示了客户端观察到的读取延迟。obj get的失误延迟比其他读取高,因为对象通常有更多的数据(见图6)。

TAO的写操作是同步进行的,所以从其他地区的写操作包括一个区域间的往返。图9比较了两个相距58.1毫秒的数据中心的延迟(平均往返时间)。在与主站同一区域的平均写延迟为12.1毫秒;在远程区域的平均写延迟为74.4=58.1+16.3毫秒。

复制滞后。 TAO的区域间异步复制写入是一种设计上的权衡,它更倾向于读取性能和吞吐量的一致性。我们观察到,在85%的追踪过程中,TAO的从属存储服务器滞后其主机不到1秒,99%的时间不到3秒,99.8%的时间不到10秒。

故障转移。 当领导者不可用时,follower缓存直接联系数据库;在我们的样本中,有0.15%的follower缓存失误使用了这种故障转移路径。写入请求的故障转移包括将这些请求委托给一个随机的领导者,这发生在0.045%的关联和对象写入中。由于计划内的维护或计划外的停机,从属数据库有0.25%的时间被提升为主数据库。

9.相关工作

TAO是一个地理分布式的最终一致的图存储,为读取进行了优化。以前的分布式系统工作已经探索了松弛一致性、图数据库和读优化的存储。据我们所知,TAO是第一个在一个单一系统中大规模结合所有这些技术的。

最终一致性。 Terry等人[33]描述了最终一致性,即TAO所使用的宽松的一致性模型。Werner将读写一致性描述为最终一致性的一些变体的属性[35]。

地理上分布的数据存储。 Coda文件系统使用数据复制来提高性能和可用性,以应对缓慢或不可靠的网络[29]。与Coda不同,TAO不允许在系统断开的部分进行写入。

Megastore是一个存储系统,它在地理分布的数据中心使用Paxos来提供强大的一致性保证和高可用性[5]。Span- ner是Google在Megastore之后开发的下一代全球分布式数据库,它引入了时间API的概念,暴露了时间的不确定性,并利用它来提高提交的吞吐量,为读取提供快照隔离[8]。TAO解决了一个非常不同的用例,没有提供一致性保证,但处理的请求多出许多数量级。

分布式哈希表和键值系统。 非结构化的键值系统是扩展分布式存储的一种有吸引力的方法,因为数据可以很容易地被分区,而且分区之间不需要什么通信。亚马逊的Dynamo[10]展示了它们如何被用于构建灵活和强大的商业系统。从Dynamo获得灵感,LinkedIn的Voldemort[4]也实现了一个分布式的键值存储,但却是为一个社交网络。TAO接受了比Dynamo更低的写入可用性,以换取避免多主站冲突解决所带来的编程复杂性。键值存储的简单性从Facebook对memcache的使用中可以看出,价值存储也允许积极的性能操作[21]。分布式哈希表的许多贡献都集中在路由方面[28, 32, 25, 24]。Li等人[16]描述了DHTs的性能,而Dabek等人[9]专注于设计广域网络中的DHTs。TAO利用了我们的数据中心安置所带来的集群间延迟的层次性,并假设了一个有少量成员或集群的连接环境拓扑结构的变化。

许多其他的工作都集中在键值存储所提供的一致性标准上。Gribble等人[13]通过利用两阶段提交提供了一个缓存数据的一致性视图。Glendenning等人[12]建立了一个可线性化的键值存储,可以容忍流失。Sovran等人[31]实现了地理复制的交易。COPS系统[17]通过跟踪客户端上下文访问的所有键的所有挂起,在一个高可用的键值存储中提供因果一致性。Eiger[18]通过跟踪列族数据库中待定操作之间的冲突,对COPS进行了改进。如果可以提高每台机器的效率,Eiger中使用的技术可能适用于TAO。

分层连接。 Nygren等人[22]描述了Akamai内容缓存如何通过将边缘集群分组为区域组,共享一个更强大的 "父 "集群来优化延迟,这与TAO的跟随者和领导者层类似。

结构化存储。 TAO遵循最近的趋势,从关系型数据库转向结构化存储方法。虽然定义松散,但这些系统通常提供比传统ACID属性更弱的保证。谷歌的BigTable[6]、雅虎的PNUTS[7]、亚马逊的SimpleDB[1]和Apache的HBase[34]是这种更具扩展性的方法的例子。这些系统都提供了类似于TAO的对象和关联语义的每记录或行级别的一致性和交易,但没有提供TAO的读取效率或图语义。Es- criva等人[27]描述了一个可搜索的键值存储。Redis[26]是一个内存存储系统,提供了一系列的数据类型和一个完全适合内存的数据集的表达式API。

图谱服务。 由于TAO是专门为社会图谱服务而设计的,因此它与现有的图谱数据库作品有相同的特征也就不足为奇了。Shao和Wang的Trinity努力[30]在内存中存储其图结构。Neo4j[20]是一个流行的开源图数据库,它提供了ACID语义和在多台机器上分片数据的能力。Twitter也使用其FlockDB[11]来存储其社交图的一部分。据我们所知,这些系统的规模都不足以支持Facebook的工作负荷。

Redis[26]是一个具有丰富选择的键值存储。值类型足以有效地实现对象和关联的API。然而,与TAO不同的是,它要求数据集完全适合在内存中。Redis的复制是只读的,所以如果没有像Nishtala等人的远程标记这样的更高层次的系统,它们不能提供读写一致性[21]。

图处理。 TAO目前不支持高级图处理API。有几个系统试图支持这样的操作,但它们不是为了直接接收来自客户端应用程序的工作负载而设计的。PEGASUS[14]和雅虎的Pig Latin[23]是在Hadoop之上对图进行数据挖掘和分析的系统,PEGASUS专注于peta规模的图,而Pig Latin专注于更有表达力的查询语言。同样,谷歌的Pregel[19]也处理了很多相同的图分析问题,但使用了自己的更具表达力的作业分配模型。这些系统专注于大型任务的吞吐量,而不是大量的更新和简单查询。Facebook也有类似的大规模离线图处理系统,对从TAO的数据库复制的数据进行操作,但这些分析工作并不在TAO本身内执行。

10 总结

总的来说,本文有三个贡献。首先,我们描述了一个具有挑战性的Facebook工作负载:需要高吞吐量、低延迟地读取访问大型、不断变化的社交图的查询。其次,我们描述了Facebook社交图的对象和关联数据模型,以及为其服务的API。最后,我们详细介绍了TAO,我们的地理分布式系统,实现了这个API。

TAO是在Facebook内部大规模部署的。缓存和持久化存储的分离使得这两层可以独立设计、扩展和运行,并在我们的组织中最大限度地重复使用组件。这种分离也允许我们在这两层中选择不同的效率和一致性的权衡,并使用empotent的缓存失效策略。事实证明,TAO的限制性数据和一致性模型对我们的应用开发者来说是可用的,同时允许高效和高可用性的实现。