开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情
[论文阅读] FlightTracker: Consistency across Read-Optimized Online Stores at Facebook(一)
第37篇,朋友们,还记得Facebook的Tao嘛?如下图,但用户在secondary写入的时候,立即去读取,是无法获得RYW保证的,以至于业务需要将读流量穿透到Primary区域,这带来了巨大的跨区流量,导致了昂贵的费用。FlightTracker就是用来解决这个问题的一个设计。本文是一个讨论以及我的听译和理解。而后我将翻译FlightTracker论文,这篇论文是非常有趣和较容易懂,甚至可以较好落地的系统! PPT和讲稿来自:www.usenix.org/conference/…
这篇论文是关于Facebook的TAO缓存Stack的一致性。TAO是一个大型的社交图存储系统,由许多缓存、索引和持久性存储后端组成。Facebook和TAO的庞大规模使得它很难实施有意义的一致性保证,TAO基本上是作为一个最终一致性的系统运行的,尽管它有一些更强的一致性组件。然而,一个纯粹的最终一致系统是非常不可预测的,也很难编程,所以TAO最初解决的是提供一个读你写(RYW)的一致性属性。目前执行RYW的方式是FlightTracker。
FlightTracker是一个在每个Facebook数据中心运行的周期性令牌(Facebook称这些令牌为_Tickets_)系统。票据记录了由数据中心粘性(也即是该用户访问的区域固定这个region)用户会话执行的最近写操作。从某种意义上说,票据是一组图元_<Key, Key-Progress>组成,其中Key-Progress是一些指定对Key的写入时间的值,如版本、时间戳,或分区序列号。然后,读取包括票据,并在堆栈中传播到为请求服务的节点。有了票据中的时效信息,服务器可以在本地决定它是否是足够的最新的。如果该节点是陈旧的,它可以将请求转发到更高层次的缓存或持久存储来检索数据。
也就是说,有了<Key, Key-Progress>,我们不必每次都回到下图中的Primary区域读取数据来获取RYW。首选是本地region,那么,这一策略会有多少成功在本region即完成RYW动作呢?具体看论文。
许多其他系统使用陈旧性令牌,但它们通常不明确地指定用户所做的所有写入行为。例如,一个令牌可以是一个单一的数字,代表客户端看到的最后一个交易ID。这对于确保recency令牌很小是很好的,但是它的分辨率较小--这样的令牌会强制执行每个分区的recency,而不是每个键,当需要每个键的RYW保证时,会导致太多的缓存丢失。
也就是传统实现粒度过粗,导致分辨率有限,但是如果每个key都保存一个进度,将导致存储非常昂贵。FlightTracer如何取得这些良好的取舍?
然而,保存和传输所有客户端的明确写集是很昂贵的,所以FlightTracker使用了一些压缩策略。其一,只需跟踪键上最近的写即可。其二,在一些写量较大的工作负载中,FlightTracker可能会降低分辨率,停止跟踪单个写量,例如,切换到按交易ID或序列号的分区级跟踪。最后,TAO堆栈强制执行一些大约60秒的有界一致性,所以超过60秒的写入可以从票据中清除掉。
FlightTracker将机票存储在基于分布式散列的简单复制系统中。读取时,首先从FlightTracker中获取票据,然后将其纳入所有的读取操作中。由于一个请求通常会进行多次读取,因此取票的成本会在多次读取操作中摊销。尽管如此,FlightTracker获取ticket的速度还是很快的--只需要0.3毫秒。 每当发生写操作时,一个特定用户会话的票据就会被更新,以包括新的写操作,而排除被压缩的写操作。