RISELab 分布式应用框架Ray项目介绍

Ray 简介

Ray是UC Berkeley大学 RISE lab(前AMP lab) 2017年12月 开源的新一代分布式应用框架(刚发布的时候定位是高性能分布式计算框架,20年中修改定位为分布式应用框架),通过一套引擎解决复杂场景问题,通过动态计算及状态共享提高效率,实现研发、运行时、容灾一体化

Ray的历史

Google的三驾马车(2003年,GFS,BigTable,MapReduce)为分布式系统指明了方向,分布式计算框架也是从MapReduce开始的, Mapreduce提供了一个极简的编程模型,加上GFS的开源实现HDFS,构成了Hadoop 1.0的架构(2005年,Hadoop 1.0的架构比较简单,基本是按论文中的框架实现,Hadoop1.0 = Mapreduce + HDFS),在第一阶段分布式计算主要以离线计算为主;随着2010年分布式实时计算系统Storm的推出,分布式计算开始向实时计算演进,但是Storm对流式数据的处理,做到了低延时,却牺牲了一致性和吞吐量。实际大数据处理业务中,系统需要同时提供低延时和准确性,单靠Storm无法满足要求,于是诞生了Lamda架构,将hadoop的批能力和Storm的流能力结合,系统整体输出低延迟并且最终一致的结果。 Spark 2009年诞生于AMPLab, 通过引入弹性分布式数据集RDD的理念,在内存中完成大数据处理,大大加快了处理速度,成为hadoop的实际继承者, 由于Spark在批处理领域的成功,人们希望把这一成功的设计复制到流处理领域,于是诞生了Spark Streaming, Spark Streaming的思想很简单,将数据流按时间窗口切分,用批模拟流,在处理有序数据流时,spark streaming可以提供强一致性保证,同时由于批处理的先天优势,spark streaming可以实现高吞吐量, Spark Streaming 的缺陷在于由于使用微批模拟流,实时性不如真正的流处理,数据延迟通常在秒级甚至分钟级,同时流量控制方面当系统出现反压时,会导致大量批次排队等待,这也是后续的Apache Flink能够获取成功的原因。Ray刚推出时,主要是为了解决AI场景下的计算性能和开发效率问题。

Ray要解决的问题

  • 传统的计算模式和计算引擎是绑定的,从 Flink 到 Spark,一个是流一个是批,二者可以互相转换,但是很多的特性在转换的时不顺畅,并且有一些优点会丢失(Spark 推出的时候目标就是代替Hadoop做批计算,虽然也可以跑流计算,但是Spark是用批来模拟流;Flink推出的时候是为了代替Storm做更好的流计算,虽然它也可以跑批计算,但是是用流来模拟批,模拟过程中都会有一定的缺陷和先天不足)。同时,图计算模式其实无法被包括在任何计算引擎之中,因为这些计算引擎在设计的时候已经绑定了一个模式。
  • Ray的定位为下一代分布式应用框架,所以期望解决的核心问题主要是,提供更简单的编程模型,更高的吞吐量和更快的响应速度

Ray 架构

  • Ray的核心设计思路
    Ray的架构设计思路是下层有一层抽象和通用的分布式调度能力,可以基于这个原始层,在上面抽象出不同的计算模式,同时把通用能力沉淀到下层,最终变成两个层级:第一层是计算模式,流、批、图计算、机器学习都是不同的计算模式;而下面一层是分布式服务,这是一个核心层用来解决调度问题、容灾问题、资源恢复等核心问题

  • Ray在整体技术栈中的位置:

  • Ray的上下文:

  • Ray的逻辑架构

  • Ray 的节点需要运行两个进程,一个是 RayLet 进程,一个是 Plasma Store(对应图中的 Object Store)进程。其中 RayLet 进程中维护着一个 Node Manager,和一个 Object Manager。Ray 提供了 Python 的 API,而 RayLet 是用 C++ 实现的。其中的 Node Manager 充当了论文中 Local Scheduler 的角色,主要负责管理 Node 下的 Worker,调度在 Node 上的任务,管理任务间的依赖顺序等。而其中的 Object Manager,主要提供了从其他的 Object Manager Pull/Push Object 的能力。

  • Plasma Store 进程,是一个共享内存的对象存储进程。原本 Plasma 是 Ray 下的,而目前已经是 Apache Arrow 的一部分了。之前介绍 Ray 在执行带有 remote 注解的函数时并不会立刻运行,而是会将其作为任务分发,而返回也会被存入 Object Store 中。这里的 Object Store 就是 Plasma。

  • 论文中的 Control State,在实现中被叫做 GCS,是基于 Redis 的存储。而 GCS 是运行在一类特殊的节点上的。这类特殊的节点被称作 Head Node。它不仅会运行 GCS,还会运行对其他节点的 Monitor 进程等。

  • Ray 提交任务的方式与 Spark 非常类似,需要利用 Driver 来提交任务,而任务会在 Worker 上进行执行。Ray 支持的任务分为两类,分别是任务(Task)和 Actor 方法(ActorMethod)。其中任务就是之前的例子中的被打上了 remote 注解的函数。而 Actor 方法是被打上了 remote 注解的类(或叫做 Actor)的成员方法和构造方法。两者的区别在于任务都是无状态的,而 Actor 会保有自己的状态,因此所有的 Actor 方法需要在 Actor 所在的节点才能执行

Ray的核心优势和实现

Ray 的优势是一开始设计的时候,没有把自己绑定成某一种场景或计算模式的解决方案,它是一个真正的原生的分布式框架,可扩展性非常强。它不具备任何强封装的特性,所以可以非常灵活地做一些改动。

  • 高效的数据存储和传输:每个节点通过共享内存,维护一个局部的对象存储(多进程共享使用),同时使用优化的Apache arrow进行节点间的数据交换。
  • 全局的状态维护:Ray通过全局的状态存储服务(Global Control State GCD)来存储和管理各类任务控制和状态信息,包括任务拓扑结构信息,数据和任务的生产关系信息,函数之间的调用关系拓扑结构信息。同时将这些状态信息剥离出来统一管理,可以让调度器本身成为一个无状态的服务,从而具备了实现任务迁移、扩展和信息共享的能力
  • 去中心化的高效调度:Ray使用自下而上的层级调度,减少了任务通过全局调度器的中转开销。同时通过全局的状态维护,让本地调度器也具备获取全局系统信息的能力,和HA的能力。
  • actor 模型:为了能和各种需要维护状态的任务进行交互,比如所模拟的目标系统的状态变迁,以及其它各种第三方有状态任务或接口逻辑的封装(比如通过TensorFlow训练一个神经网络模型的任务,这些第三方系统可能无法将内部状态信息暴露出来交给Ray来管理),Ray也定义了名为Actor的抽象封装。在Ray中,Actor是一种有状态的任务,通过暴露特定的方法接口供外部进行远程调用。而对于Actor的调用历史,也可以转化成一种自依赖关系拓扑图,保存在GCS中。从而将促成Actor内部状态变迁的调用过程也通过任务图的方式记录了下来,从而系统也就具备了Actor状态重建的能力。
  • 远程调用:Ray让用户通过显示的定义,如@ray.remote的装饰器的形式来告知系统需要允许远程调用的函数。当一个远程调用函数被定义以后,它就会被推送到所有的工作节点上,已备后续调用。相关的函数代码也会被存储到GCS中。这样后续的任务调度,容错恢复等过程都能够更简单的实现。

Ray的落地场景

Ray在蚂蚁金服的若干场景已落地:

  • 动态图推导,流+图计算,性能上可以1秒内完成6层迭代查询,用于实时反套现、欺诈识别;
  • 金融在线决策,流+分布式查询+在线服务,性能上数据生产到分布式查询一秒内,用于金融网络监控、机构渠道路由等;
  • 在线机器学习,流+分布式机器学习,性能上实现秒级数据样本到模型更新,用于智能营销、实时推荐、流控等。

金融数据智能的差异化需求:

  • 实时性要求高,实时数据以两倍以上的速度增长,在线决策越来越多,不再是把数据离线做决策再部署到线上;
  • 计算场景复杂多样,以前可能是一个简单的聚合,逐渐进化到用规则做决策,基于图、基于机器学习等决策,整个计算的形式越来越多样化;
  • 数据链路长,研发调试效率低,当你要做全链路数据研发的时候,从头到尾会经历十几个系统,对整体的数据研发提出了很大的挑战;
  • 计算及存储高可用,包括跨城市的容灾,高可靠的计算服务;
  • 数据安全、监管合规、风险防控,需要做严格的数据安全和隐私保护,特别在监管层面要合规。

参考

(完)