【转】分布式数据流的轻量级异步快照

本篇翻译自论文:Lightweight Asynchronous Snapshots for Distributed Dataflows,Flink的容错快照模型即来源于该论文。原文地址:https://arxiv.org/pdf/1506.08603.pdfnode

分布式数据流的轻量级异步快照

摘要

分布式有状态的流处理使得大规模持续计算可以部署在云端,它的目标是低延迟和高吞吐。其最基本的挑战之一是提供潜在失败可能性下对处理的保证。现有的方法都依赖用于故障恢复的周期性全局状态快照。这些方法有两个主要缺点。首先,它们常常中止(拖延)所有的计算,这会影响摄取。其次,它们热衷于保持运行过程当中的全部状态,致使快照比所需的要大。在咱们这项工做中,咱们提出了异步屏障快照Asynchronous Barrier Snapshotting (ABS),这是一个的、适用于现代数据流执行引擎的、将空间占用最小化的轻量级算法。ABS仅仅在非循环执行拓扑上保留Operator的状态,同时在循环的数据流上保留最小化的record日志。咱们在Apache Flink(一个支持有状态的分布式流处理分析引擎)中实现了ABS。咱们的评估表名,咱们的算法对执行没有很重的影响,而且保持了线性的扩展以及在频繁快照的状况下表现良好。算法

关键词 容错, 分布式计算, 流处理, 数据流, 云计算, 状态管理apache

1. 介绍

分布式数据流处理是一种新出现的容许持续计算的数据密集型计算范例,目标是端到端的低延迟同时保证高吞吐量。一些对时间要求严格的应用能够从诸如Apache Flink和Naiad这样的数据流处理系统受益,尤为是实时分析领域(eg. 预测分析和复琐事件处理)。容错在这类系统中相当重要,由于绝大多数真实世界的用例是不能提供错误的。目前已知的,在有状态的处理系统上可以保证exactly-once语义的方法,依赖于执行状态的全局一致快照。然而,这里有两个主要缺点会使得它们的应用对于实时流处理而言效率低下。同步快照技术会中止分布式计算的总体执行来得到总体状态的一致视图。此外,据咱们所知,已知的全部分布式快照算法会包含正在通道中传输的记录或者未处理的信息做为快照的一部分,大多数状况下,包含的状态会比须要的大。编程

在这项工做中,咱们专一于提供轻量级的快照,专门针对分布式有状态的数据流系统,在性能上影响很小。咱们的解决方案提供异步的低空间成本状态快照,它仅仅包含了Operator在非循环执行拓扑上的状态。另外,咱们经过在拓扑的选中部分应用下游备份,同时保持快照状态在最小值,来覆盖循环执行图的case。咱们的技术不会中止流操做,它只会引入很小的运行开销。这篇论文的主要贡献能够概括以下:后端

  • 咱们提出而且实现了一个异步快照算法,它在非循环执行图上实现了最小化的快照。
  • 咱们描述并实现了用于循环执行图上的算法的概论。
  • 咱们展现了咱们的方法相比于使用Apache Flink Streaming做为基础系统的最新技术的优点。

论文的剩余篇幅组织以下:第2部分概述了有状态数据流系统中分布式全局快照的现有方法;第3部分提供了Apache Flink的处理处理和执行模型,接着第4部分咱们详细描述了全局快照的主要方法。咱们的恢复方案会在第5部分有个简要介绍。第6部分总结了咱们的实现,第7部分是咱们的测试评估,将来工做和结论在第8部分。缓存

2. 相关工做

在过去十年间,(业界)为作持续处理的系统提出过几种恢复机制[4,11][4,11]。将持续处理模拟为无状态分布式批处理计算(如离散化流和Comet[6,15][6,15])的系统依赖于状态从新计算。另外一方面,有状态的数据流系统,如Naiad、SDGs、Piccolo和SEEP[三、五、十一、12][三、五、十一、12](它们也是咱们在这项工做中的主要关注点),使用checkpoint检查点获取故障恢复的全局执行的一致快照。Chandy和Lamport[4][4]提出的分布式环境中的一致全局快照问题在过去几十年中获得了普遍的研究[4,7,8][4,7,8]。全局快照理论上反映了执行的总体状态,或者在其操做的特定实例上可能的状态。Naiad [11][11]采用的一种简单但成本高昂的方法是分三步同步快照:第一步是暂停执行图的总体计算,第二步是执行快照,最后一步是指示每一个task在全局快照完成后继续其操做。这个方法对吞吐量和空间使用都有着很大的影响,由于须要阻塞整个计算,同时还依赖上游备份,该备份记录生产者端发送的records。另一种流行的方法,最初由Chandy和Lamport提出,如今已经部署在不少系统中,是在作上游备份的时候异步执行快照[4,5,10][4,5,10]。这是经过在整个执行图中分布标记来实现的,这些标记会触发Operator和通道状态的持久性。可是,因为须要上游备份,而且因为对备份记录的从新处理致使恢复时间延长,这种方法仍然存在额外的空间需求。咱们的方法扩展了Chandy和Lamport最初的异步快照思想,可是,它不考虑非循环图记录的备份日志记录,同时在循环执行图上保留很是有选择性的备份记录。安全

3. Apache Flink

咱们当前的工做以Apache Flink Streaming的容错需求为指导,Apache Flink Streaming是一个分布式流分析系统,是Apache Flink Stack(前身Stratosphere [2][2])的一部分。 Apache Flink围绕通用的Runtime引擎进行架构,统一处理有状态而且互连的task组成的批处理和流工做。 Flink中的分析做业被编译为任务的有向图。 数据元素从外部源获取,并以管道方式经过任务图进行路由。 task根据收到的输入持续操纵其内部状态,并产生新的输出。网络

3.1 流式编程模型

Apache Flink的流式处理API容许经过暴露无界有分区的数据流(部分排序的record序列)做为其核心的数据抽象(称为DataStream)来组合复杂的流分析job。DataStream能够从外部数据源创立(如消息队列,Socket流,自定义Generator)或者经过在其余DataStream上调用操做。DataStream以高阶函数的形式支持多种operator如map、filter、reduce,这些函数在每条记录上都应用,生成新的DataStream。下面代码示例1展现了如何在Apache Flink实现一个增量的WordCount。在这个程序里,单词从文本读入,每一个单词的count打印到标准输出。这是一个有状态的流程序,由于数据源须要留意当前单词在文件的偏移量,计数器叶鏊维持当前的每一个单词的计数做为它们的内部状态。架构

图1:增量的WordCount执行图异步

1
2
3
4
5
6
val env : StreamExecutionEnvironment = ...
env.setParallelism(2)

val wordStream = env.readTextFile(path)
val countStream = wordStream.groupBy(_).count
countStream.print

示例1:增量的WordCount程序

3.2 分布式数据流执行

当用户执行一个应用,全部的DataStream operator会编译成一个执行图,原则上是一个有向图G = (T, E),顶点T表明Task,边E表明task之间的数据通道,这和Naiad类似。上图1描绘了一个增量WordCount示例程序的执行图。如图所示,每一个operator实例都被封装到相关task上。 当没有输入通道时,task能够更进一步被分类为数据源,没有输出通道时,task能够下沉。此外,M表示在并行执行期间全部经过task传输的record的集合,每一个task t∈Tt∈T 封装了一个独立执行的operator实例,而且由如下部分组成:(1)输入输出通道的集合:It,Ot⊆EIt,Ot⊆E;(2)一个operator的状态stst和(3)用户自定义函数(UDF)ftft。数据接收是基于拉取(pull-based)的:在执行期间,每一个task消耗其input records,更新其operator状态并根据其用户自定义函数生成新记录。更具体地说,对于一个task t∈Tt∈T接收的每一个record r∈Mr∈M,一个新的状态s、tst、会随着根据UDF ft:st,r−>[s、t,D]ft:st,r−>[st、,D] 获得的输出records集合 D⊆MD⊆M产生。

4. 异步屏障快照(Asynchronous Barrier Snapshotting, ABS)

为了提供持续的输入,分布式处理系统须要对故障task有弹性(容忍)。一个提供弹性的方式是周期性地抓取执行图的快照,这样就能够用来稍后从故障中恢复。一个快照是一个执行图的全局状态,抓取全部必须的信息来从特定的执行状态重启计算。

4.1 问题定义

咱们定义了一个执行图G=(T,E)G=(T,E)的全局快照Gx=(Tx,Ex)Gx=(Tx,Ex)做为一个全部task和edge的状态集合,TxTx和ExEx分别地。更详细地说,TxTx由全部operator的状态sxt∈Tx,∀t∈Tstx∈Tx,∀t∈T组成,ExEx是通道状态的集合ex∈Exex∈Ex,而exex由在e中传输的records组成。

咱们须要为每一个快照G∗G∗保留某些属性,为了保证恢复的正确结果如Tel所描述的终止(Termination)和可行性(Feasibility)[14][14]。

终止(Termination)保证了一个快照算法在全部进程alive的状况下最终能在有限的时间内完成。可行性(Feasibility)表示快照是有意义的的,即在快照过程当中没有丢失有关计算的信息。从形式上讲,这意味着快照中维护了因果顺序,这样task中传递的records也是从快照的角度发送的。

4.2 非循环数据流的ABS

执行被拆分红stages的状况下,不保存通道状态就作快照是可行的。Stages将注入的数据流和全部相关的计算拆分为一系列可能的执行(executions),在这些执行中,全部先前的输入和生成的输出都已经被安全处理。一个stage结束时的operator状态的集合反映了整个执行的历史。所以,它能够单独用于快照。咱们算法的核心思想是在保持持续数据流入的同时,使用阶段性(分阶段)快照建立相同的快照。

在咱们的方法中,stage在持续数据流执行中被特殊的屏障标记所模拟,这些屏障标记被数据流周期性地注入,也在整个执行图中被推送到下游接收。随着每一个task接收指示执行阶段的屏障,逐步构建全局快照。 咱们进一步对咱们的算法作出如下假设:

图2:非循环图的异步屏障快照(ABS)

算法1:非循环执行图的异步屏障快照

1: upon event do
2: state := init_state; blocked_inputs := ϕϕ;
3: inputs := input_channels;
4: outputs := output_channels; udf := fun;
5:
6: upon event > do
7: if input ≠≠ Nil then
8: blocked_inputs := blocked_inputs ∪∪ {input};
9: trigger ;
10: if blocked_inputs = inputs then
11: blocked_inputs := ϕϕ;
12: broadcast >;
13: trigger ;
14: for each 
inputs as input
15: trigger ;
16:
17:
18: upon event 
do
19: 
{state ‘‘, out_records}:=udf(msg,state);
20: 
state:=state‘‘;
21: for each 
out_records as {out_put,out_record}
22: *trigger
 ;
23:

  • 网络信道是准可靠的,遵照FIFO传送次序,能够被阻止(blocked)和解除阻止(unblock)。
    当通道被阻止(blocked)时,全部消息(msg)都被缓冲但在解除阻塞(unblock)以前不会继续传递。
  • Task能够在它们的通道(channel)组件触发(trigger)操做如阻止(blocked)、解除阻止(unblock)和发送(send)消息。广播(broadcast)消息也是在输出通道(output_channel)上支持的。
  • 在源头task上注入的消息(msg),即消息屏障,被解析为“Nil”输入通道(input_channel)。

译者注:这段确实有点晦涩难懂,我来解释一下。

  1. 首先说图,能够看到图上黑色加粗的线标记的是barrier屏障,屏障存在于每一个通道上,能够看作一个特殊的record,在其前面的record叫preshot records,在其后面的record叫postshot records,当preshot records都被传递到途中的count算子后,src->count的通道上只剩postshot records,这时候通道会block,按照前文的说法,block的channel上的record都会在缓存里。当链接至某个算子的所有输入信道(如图中b所示的count-1 task的两条输入通道src-1->count-1和src-2->count-1通道)都已经block之后,对该task作快照,同理图中c所示的count-2 task也同样。
  2. 而后说算法,首先要明确一下,算法中的input和output其实都是指通道。
    • 第一个方法很好理解,一个初始化方法,此时block的输入通道是空集,也就是没有被block的通道。
    • 第二个和第三个方法其实都是receive的方法,上面我在解释图的时候说过,能够把barrier看成一个特殊的record来考虑。因此,第二个方法是接收到barrier,第三个方法是接收到正常的有msg的record。那咱们先来讲第二个,当task接收到barrier屏障时,首先是个常规的空值判断,若是input不为空,那么就把触发该input通道的block。而且该task的block的input通道的集合为当前已经block的通道和参数input通道的并集。若是block的input通道等于全部input通道,也就是全部input通道都已经被block了,此时触发该task的快照操做,而且把屏障日后广播(即对全部output通道加上这个屏障),而后对全部input通道解除block。
    • 第三个方法,传入msg,经过UDF计算出结果record和结果状态,而且把结果状态赋值给当前状态,而且把全部结果record日后发送(结果集的每一个record对应的output通道不必定是同一个,只逐个往对应的output通道发送)。

下文也会有官方解释,更进一步了解该算法。↓↓↓↓


ABS算法也如图2所示:一个中心协调器会周期性地给全部source注入stage屏障。当一个source收到了屏障,它就会给当前状态作一个快照,而后广播屏障到全部输出通道(如图2的a)。当一个非source的task收到了其input通道里的某个发送过来的屏障,它会block该input通道直到它收到了全部input通道的屏障(算法第9行,图2的b),而后该task就会生成其当前状态的快照而且广播屏障给全部output通道(算法第12-13行,图2的c)。接下来,该task会解除全部input通道的block继续计算(算法第15行,图2的d)。最终的全局快照Gx=(Tx,Ex)Gx=(Tx,Ex)是彻底由全部Ex=ϕEx=ϕ的operator的状态T∗T∗组成的。

证实简述:正如以前提到的,一个快照算法须要保证终止(Termination)和可行性(Feasibility)。
终止(Termination)是由通道和非循环执行图的属性保证的。通道的可靠性保证了只要task存活,最终将收到以前发送的每一个屏障。 此外,因为始终存在来自源的路径,所以有向无环图(DAG)拓扑中的每一个任务task都会从其全部输入通道接收到屏障并生成快照。
至于可行性(Feasibility),它足以代表全局快照中的operator的状态只反映到最后一个stage处理的records的历史。这是由先入先出顺序(FIFO)和屏障上input通道的block来保证的,它确保在快照生成以前没有post-shot记录会被处理。

4.3 循环数据流的ABS

在执行图存在有向循环的状况下,前面提出的ABS算法不会终止,这就会致使死锁,由于循环中的task将无限等待接收来自其全部输入的屏障。此外,在循环内任意传输的records不会包含在快照中,违反了可行性。所以,须要一致地将一个周期内生成的全部记录包括在快照中,以便于可行性,并在恢复时将这些记录放回传输中。咱们处理循环图的方法扩展了基本算法,而不会引入任何额外的通道阻塞,以下算法2所示。首先,咱们经过静态分析,在执行图的循环中定义back-edges L。根据控制流图理论,在一个有向图中,一个back-edge是一个指向已经在深度优先搜索(depth-first search)中被访问过的顶点(vertex)的边(edge)。定义执行图 G(T, E \ L) 是一个包含拓扑中全部task的有向无环图(DAG)。从这个DAG的角度来看,该算法和之前同样工做,不过,咱们在快照期间还使用从已定义的back-edges接收的记录的下游备份。这是由每一个task t 实现的,back-edges的一个消费者Lt⊆It,LtLt⊆It,Lt产生一个从LtLt转发屏障到接收屏障们回LtLt的备份日志。屏障会push全部在循环中的records进入下游的日志,因此它们在接二连三的快照中只会存在一次。

图3:循环图的异步屏障快照(ABS)

算法2:非循环执行图的异步屏障快照

1: upon event do
2: state := init_state; marked := ϕϕ;
3: inputs := input_channels; logging := False
4: outputs := output_channels; udf := fun;
5: loop_inputs := backedge_channels;
6: state_copy := Nil; backup_log := [];
7:
8: upon event > do
9: marked := marked ∪∪ {input}
10: regular := inputs \ loop_inputs;
11: if input ≠≠ Nil AND input ∉∉ loop_inputs then
12: trigger ;
13: if !logging AND marked = regular then
14: state_copy := state; logging := True;
15: broadcast >;
16: for each 
inputs as input
17: trigger ;
18:
19: if 
marked = input_channels then
20: trigger ;
21: 
marked := ϕϕ; logging := False;
22: state_copy := Nil; backup_log := [];
23:
24: upon event 
do
25: if 
logging AND node ∈∈ loop_inputs then
26: 
backup_log := backup_log :: [input];
27: 
{state ‘‘, out_records}:=udf(msg,state);
28: 
state:=state‘‘;
29: for each 
out_records as {out_put,out_record}
30: *trigger
 ;
31:


译者注:这个算法跟上一个算法不同的地方在于,把循环过的input边看成back-edge,其他边看成regular,除掉循环的DAG依然仍是按以前的作法处理,而后有back-edge的边的task,在接收到屏障的时候须要把其state作一个备份,而且接受它的back-edge中在屏障以前的pre-shot record做为log。


更详细解释下ABS算法2(图3所示):有着back-edge做为输入通道的task,一旦它们的常规通道(e∉Le∉L)都接收到了屏障,该task就会产生了一个其状态的本地备份(算法的14行,图3的b)。接下来,从这一点开始,它们记录从back-edges收到的全部record,直到它们收到来自它们的stage屏障(算法第26行)。这就容许,像图3(c)中看到的,全部在循环中的pre-shot record,都会包含在当前快照中。注意,最后的全局快照Gx=(Tx,Lx)Gx=(Tx,Lx) 包含了全部task的状态TxTx和在传输中Lx⊂ExLx⊂Ex仅仅back-edge中的记录。

证实简述:再次地,咱们须要证实终止(Termination)和可行性(Feasibility)。与4.2中终止(Termination)被保证同样,由于每一个task最终都会接收到全部输入通道(包括后端)的屏障。经过从全部常规输入接收屏障后当即广播屏障,咱们避免了前面提到的死锁条件。

FIFO的属性仍适用于back-edge,如下属性证实了可行性。(1)快照中包含的每一个task状态,是在处理常规输入接收的post-shot record以前所执行的各自task的状态副本。 (2)快照中包含的下游日志是完整的,因为FIFO保证,包含back-edge接收的全部屏障以前的全部pending的post-shot record。

5. 故障恢复

虽然不是这项工做的主要焦点,但故障恢复方案是咱们应用快照方法的动机。所以,咱们在这里简要说明了它的操做。有几种故障恢复方案可使用这种持续快照。在最简单的形式中,整个执行图能够从上一个全局快照从新启动,以下所示:每一个任务t(1)从持久化存储中检索其快照stst的关联状态并将其设置为其初始状态,(2)恢复其备份日志并处理全部其中包含的records,(3)开始从其输入通道中摄取records。相似于TimeStream [13],部分图恢复方案也是可行的,经过仅从新安排上游依赖task(输出通道链接失败task的task)以及它们各自的上游任务直到源。 示例恢复计划如图4所示。为了提供exactly-once语义,应在全部下游节点中忽略重复记录以免从新计算。 为了实现这一目标,咱们能够遵循与SDG相似的方案[5],使用来自源的序列号标记记录,所以,每一个下游节点均可以丢弃序列号小于已处理的记录的记录。

图4:示例恢复计划

6. 实现

咱们为Apache Flink贡献了ABS算法的实现,以便为流运行时提供精确的一次处理语义。在咱们当前的实现中,阻塞通道将全部传入记录存储在磁盘上,而不是将它们保留在内存中以提升可伸缩性。虽然这种技术确保了鲁棒性,但它增长了ABS算法的运行时间影响。

为了从数据中区分operator状态,咱们引入了一个显式的OperatorState接口,该接口包含更新和检查状态的方法。 咱们为Apache Flink支持的有状态的运行时operator提供了OperatorState实现,例如基于偏移量的源或聚合。

快照协调是做为JobManager上的参与者进程实现的,它为单个job的执行图保留全局状态。协调器按期向执行图的全部源注入阶段屏障。从新配置后,最后一个全局快照状态将从分布式in-memory的持久化存储中恢复到operator上。

7. 评估

咱们评估的目标是将ABS的运行时开销与Naiad [11]中采用的全局同步快照算法进行比较,并测试该算法在大量节点上的可扩展性。

7.1 Setup

用于评估的执行拓扑(图5)由6个不一样的运算符组成,并行度等于集群节点的数量,Task点的数量是6倍的集群节点数量。该执行包含了3个shuffle,以强调ABS中通道阻塞的可能影响。 源生成总共10亿条记录,这些记录统一分布在源实例之间。拓扑中的operator的状态是每一个key的聚合和源偏移。 实验在Amazon EC2集群上运行,使用多达40台 m3.medium实例。

图5:用于评估的执行拓扑

咱们测量了在不一样快照方案下运行的评估做业的运行时开销,即ABS和具备不一样快照间隔的同步快照[11]。 咱们在Apache Flink上实现了Naiad [11]中使用的同步快照算法,以便为比较提供相同的执行后端。 该实验使用10节点集群运行。 为了评估算法的可扩展性,咱们处理了固定数量的输入记录(10亿),同时将拓扑的并行性从5个增长到40个节点。

7.2 结论

在图6中,咱们描述了两种算法对基线的运行时影响(没有容错)。当快照间隔很小时,同步快照的巨大性能影响尤其明显。这是由于系统花费更多时间不处理任何数据,以得到全局快照。 ABS对运行时的影响要小得多,由于它在不阻塞总体执行的状况下连续运行,同时保持至关稳定的吞吐率。对于较大的快照间隔,同步算法的影响不过重要,由于它是忽然执行的(在咱们的实验中为1-2秒),同时让系统在其他执行期间以其正常吞吐量运行。然而,就许多临界环境应用(如入侵检测管道)的实时保证而言,突发事件一般会违反SLA。所以,这些应用将经过ABS的性能进一步受益。在图7中,咱们将运行ABS的拓扑的可扩展性与基线的3秒快照间隔进行比较(没有容错)。很明显,基线工做和ABS都实现了线性可扩展性。

图6:两种算法对基线的运行时影响(没有容错)

图7:与基线的3秒快照间隔进行比较(没有容错)

8. 将来的工做和结论

在将来的工做中,咱们计划经过解耦快照状态和运行状态来探索进一步下降ABS影响的可能性。 这容许纯粹的异步状态管理,由于任务能够在持久化快照的同时连续处理记录。 在这种方案中,还须要将pre-shot和post-shot记录与相应的状态同步,这能够经过根据它们所属的快照标记记录来解决。 因为这种方法会增长算法的计算,空间和网络I/O要求,咱们计划将其性能与咱们当前的ABS实现进行比较。 最后,咱们计划研究不一样的恢复技术,这些技术只维护exactly-once语义,同时经过在每一个任务粒度上操做来最小化从新配置的须要。

综上所述,咱们重点研究了分布式数据流系统中周期性全局快照的问题,介绍了一种新的快照技术ABS,它能够得到良好的吞吐量。ABS是第一个考虑非循环执行拓扑可能的最小化的状态的算法。此外,咱们还扩展了ABS来处理循环执行图,只存储恢复时须要从新处理的记录。咱们在ApacheFlink上实现了ABS,并跟同步快照做对比,测试评估了咱们的方法。在此早期阶段,ABS显示出良好的效果,对总体执行吞吐量的影响很小,具备线性可扩展性。

参考文献

[1] Apache flink. https://flink.apache.org/.

[2] A. Alexandrov, R. Bergmann, S. Ewen, J.-C. Freytag, F. Hueske, A. Heise, O. Kao, M. Leich, U. Leser, V. Markl, et al. The stratosphere platform for big data analytics. The VLDB JournalThe International Journal on Very Large Data Bases, 23(6):939–964, 2014.

[3] R. Castro Fernandez, M. Migliavacca, E. Kalyvianaki, and P. Pietzuch. Integrating scale out and fault tolerance in stream processing using operator state management. In Proceedings of the 2013 ACM SIGMOD international conference on Management of data, pages 725–736. ACM, 2013.

[4] K. M. Chandy and L. Lamport. Distributed snapshots: determining global states of distributed systems. ACM Transactions on Computer Systems (TOCS), 3(1):63–75, 1985.

[5] R. C. Fernandez, M. Migliavacca, E. Kalyvianaki, and P. Pietzuch. Making state explicit for imperative big data processing. In USENIX ATC, 2014.

[6] B. He, M. Yang, Z. Guo, R. Chen, B. Su, W. Lin, and L. Zhou. Comet: batched stream processing for data intensive distributed computing. In Proceedings of the 1st ACM symposium on Cloud computing, pages 63–74. ACM, 2010.

[7] A. D. Kshemkalyani, M. Raynal, and M. Singhal. An introduction to snapshot algorithms in distributed computing. Distributed systems engineering, 2(4):224, 1995.

[8] T. H. Lai and T. H. Yang. On distributed snapshots. Information Processing Letters, 25(3):153–158, 1987.

[9] L. Lamport. Time, clocks, and the ordering of events in a distributed system. Communications of the ACM, 21(7):558–565, 1978.

[10] Y. Low, D. Bickson, J. Gonzalez, C. Guestrin, A. Kyrola, and J. M. Hellerstein. Distributed graphlab: a framework for machine learning and data mining in the cloud. Proceedings of the VLDB Endowment, 5(8):716–727, 2012.

[11] D. G. Murray, F. McSherry, R. Isaacs, M. Isard, P. Barham, and M. Abadi. Naiad: a timely dataflow system. In Proceedings of the Twenty-Fourth ACM Symposium on Operating Systems Principles, pages 439–455. ACM, 2013.

[12] R. Power and J. Li. Piccolo: Building fast, distributed programs with partitioned tables. In OSDI, volume 10, pages 1–14, 2010.

[13] Z. Qian, Y. He, C. Su, Z. Wu, H. Zhu, T. Zhang, L. Zhou, Y. Yu, and Z. Zhang. Timestream: Reliable stream computation in the cloud. In Proceedings of the 8th ACM European Conference on Computer Systems, pages 1–14. ACM, 2013.

[14] G. Tel. Introduction to distributed algorithms. Cambridge university press, 2000.

[15] M. Zaharia, T. Das, H. Li, S. Shenker, and I. Stoica. Discretized streams: an efficient and fault-tolerant model for stream processing on large clusters. In Proceedings of the 4th USENIX conference on Hot Topics in Cloud Ccomputing, pages 10–10. USENIX Association, 2012.

【原文】http://blog.orisonchan.cc/2019/04/04/51/

相关文章
相关标签/搜索