引子6:Facebook使用FlightTracker获得RYW@Tao

208 阅读6分钟

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

引子6:Facebook使用FlightTracker获得RYW@Tao

第42篇,本文仍是引子,介绍了FlightTraceker上的一些扩展,没想打能玩的这么花。 是对作者ppt的一些听译和各种文章总结。www.usenix.org/conference/…

超越 "RYW"的范围

到目前为止,一直在讨论RYW一致性,这是一个很好的默认值,但对每个应用来说都是不够的。然而,FlightTracker将读的一致性问题分解为_识别最近的写_和_提供新的结果_,使我们能够灵活地提供不同程度的一致性。例如,为了获得一种新的一致性保证,我们可以在不改变Ticket-inclusive读取实现或任何数据存储属性的情况下,以不同的方式跟踪最近的写入。重新定义 "会话"--或会话所包含的写入内容--使我们能够超越 "RYW",提供更通用的会话级一致性。

考虑一个像GraphQL Subscriptions这样的pub-sub系统,它是Facebook通知系统的基础。一个用户行为触发了一个发布给所有订阅者的事件。为了呈现个性化的通知,应用程序可以在交付该通知之前从订阅者一方的TAO中读取数据。然而,这些订阅者可能会连接到与发布者不同的区域。因此,如果事件的交付超过了TAO的复制,他们可能会经历陈旧的读取。如图4所示,我们通过在事件交付路径上传递发布者的最近写入票据并在用户查询中使用包含票据的读取来解决这个问题。这有效地在 "阅读你自己的文章 "的基础上提供了 "阅读发布者的文章"。

图4. 重用Ticket和包含Ticket的读取,我们为我们的pub-sub系统提供了替代性的写入可见性保证,比如read-the-publisher's-writes。

作为另一个例子,我们将类似的策略应用于Facebook内部的其他框架,比如保证异步作业看到在他们被安排之前发生的写。重要的是,唯一必要的工作是在通信路径的适当点上传输Ticket。对于每个支持的后端,Ticket-inclusive reads的实现都是一样的。

Production results

FlightTracker在生产中已经有四年多的时间。它为两种数据库技术、两种缓存类型(包括TAO)和三种索引系统管理RYW一致性。总的来说,FlightTracker为每秒数千万次的社交图写、每秒数亿次的索引读取以及每秒数十亿次的TAO查询管理RYW。FlightTracker服务本身每秒处理超过1亿次的机票读取和2000万次的机票写入。

社交图谱服务堆栈位于为Facebook用户提供服务的关键路径上,因此在推出FlightTracker和Ticket时,将效率和可靠性影响降到最低是至关重要的。作为一项区域性的内存服务,FlightTracker保持着超过99.9999%的读取可用性,并且比底层数据库的写入可用性高一个数量级。对FlightTracker和Arrivals的查询和更新通常需要不到1毫秒的时间。机票、FlightTracker或Arrivals相关代码的总和占用不到1%的CPU和不到2.6%的RAM。

Effectiveness

FlightTracker使TAO摆脱了对固定通信拓扑结构的依赖,提供了RYW。这创造了一个机会,通过将写路径从TAO中分离出来,并专注于简化读路径来提高效率。它还使TAO有一个更灵活的故障转移模式,以提高可靠性。在我们的重读工作负载中,0.2%的TAO读有一个非空的票据连接。而这些读数中只有3%与尚未通过每分片复制流复制的更新有关。这使得一致性失误率可控,限制了使用基于票据的读取的整体缓存影响。

下文提到性能,确实可以,尽管每个请求可能都要去FT读写一次。 image-20221231232701550

image-20221231232709241

汲取的教训

运营一个以终端用户为中心的服务是最初实施中最具挑战性的方面之一。由于访问社交图谱数据的平台和API种类繁多,统一识别 "登录用户 "的难度令人吃惊。应用程序通常在存储分片之间显示出良好的负载分布,但批处理过程可能按用户操作,并对单个FlightTracker分片造成重大压力。随着时间的推移,我们发现,要求最严格的用例最不需要一致性保证。他们通常会在批处理或迁移过程中写入大量的数据,而在事后不会读取这些数据。

通过建立包含票据的读取合同,我们发现了底层数据存储的一致性漏洞,并发现了导致TAO、图索引、甚至数据库复制中永久性不一致的低概率bug。这些错误的范围包括协议缺陷、错误条件的不正确处理,以及依赖未被所有历史数据尊重的新数据不变性。以前很难注意到这些bug,现在这些bug的数量超过了暂时性的不一致。包含机票的读取不应返回比机票中的数据更早的数据。因此,在FlightTracker中,即使出现一次陈旧的结果,也是可操作的。

Translatable insights

虽然我们的一些动机和实现是Facebook特有的,但我们提供以用户为中心的会话的动机是广泛共享的(如Twitter的曼哈顿,或PathStore),正如我们对扩展一致性保证到全局二级索引的兴趣(如CouchbaseAmazon DynamoDB)。

FlightTracker方法对带有缓存的读优化环境具有特殊的吸引力。即使底层数据存储提供了非常强的一致性,增加缓存(作为额外的系统或在客户端)仍然会出现缓存性和无效性的长期挑战。

我们的FlightTracker方法是可推广的。为异构数据存储而设计的Ticket可以很容易地扩展到其他数据存储,而且开销很小。实现包含门票的读取和暴露版本基元不需要对数据存储的核心复制协议进行修改。它们的开销也相对较小。大量FlightTracker逻辑所在的客户端库可以逐步实现和推广。特别是在试图改造索引系统的时候,我们的方法允许我们将反向元数据索引分离成自己的组件,这对我们来说是非常有利的。

结论

FlightTracker是我们为Facebook的社交图提供RYW一致性的方法。它在一个由异步复制的缓存、数据库副本和索引组成的读取优化的生态系统中运行。FlightTracker保留了最终一致性的读取效率、热点容忍度和松散耦合的优势。此外,它还使我们能够规避在使用穿透写缓存的一致性时遇到的扩展挑战。