Jiffy: Elastic Far-Memory for Stateful Serverless Analytics

Jiffy的设计灵感来自于操作系统中的虚拟内存设计:以块为单位分配far-memory。弹性地扩展分配给各个作业的内存资源,并以秒为单位满足即时作业的需求。

解决四个挑战

  • 首先,每个无服务器analytics工作可以围绕多个阶段(或一个有向无环图)进行组织,每个阶段都有数万到数千的单独任务。需要一个有效的机制来维护memory-task映射。
  • 其次,在无服务器的analytics中,向共享far-memory系统读写的任务数量可能会迅速变化。因此,任务级隔离变得至关重要:新任务的到达和离开不应影响现有任务的性能。
  • 第三,无服务器任务与中间数据的解耦意味着任务的失败可能与中间数据无关。因此,我们需要对中间数据进行明确的生命周期管理的机制。
  • 第四,任务与中间数据的解耦也意味着内存容量弹性扩展时的数据分区变得具有挑战性,特别是对于无服务分析中使用的某些数据类型(例如键值存储)。事实上,天真地把这个任务委托给应用程序将需要大量的网络传输(在计算任务和远端存储系统之间)和每次容量扩展时的数据读/写操作。因此,我们需要新的机制来有效地实现远存系统内的数据分区。

设计点

  • 分层寻址,解决虚拟内存的管理的问题,挑战1/2
  • 数据的生命周期管理,解决因为serverless任务失败而数据空悬的问题,挑战3
  • data repartition,解决内存扩缩容的情况,挑战4

开源 https://github.com/resource-disaggregation/jiffy

Motivation

Pocket的一些回顾

  • Scalable centralized management:虽然数据存储本身分布在多个存储服务器上,但通过控制平面和元数据平面的存储管理功能在逻辑上是集中的
  • Multi-tiered data storage:作业可以根据其性能和/或成本限制,在数据平面的DRAM、Flash或HDD层上存储数据
  • Adding/removing memory servers:Pocket可以通过在数据平面增加更多的内存服务器来扩大内存容量

Analytics execution with pocket

  1. 当作业首次启动时,它向控制平面注册自己,要么指定它预期使用的内存资源量,要么提供Pocket可以用来估计的提示。
  2. 控制器使用这些信息为作业分配资源,并通知元数据平面关于数据平面上的资源放置。
  3. 当作业的无服务器计算任务首次尝试在作业分配的内存上读取或写入中间数据时,它会联系元数据服务以获得拥有其分配资源的内存服务器的IP地址。
  4. 无服务器任务随后可以直接从内存服务器上访问数据。
  5. 一旦任务完成,它就在控制平面上取消注册,以释放其资源。

Limitations of Pocket Resource Allocation

Pocket的资源分配的核心挑战是,它以作业的粒度分配内存。 在提交时,作业指定了它的内存需求;并且,Pocket在作业的整个生命周期内分配和保留与作业需求相等的内存资源,只有在作业明确取消注册时才释放这些资源。

由于以下两个原因,这种job-level的资源分配是有问题的

  1. 首先,准确预测中间数据大小对许多分析工作来说是很难的。
  2. 其次,即使可以准确地预测中间数据大小,Pocket的资源分配机制导致了性能下降和资源利用不足之间的标准权衡。

Jiffy design

Hierarchical Addressing

其实就是按照访问路径加前缀。比如T1.T4.B2_2代表T1->T2的中间数据存在了B2_2里。

几个设计问题

  • 分层寻址与serverless系统政策解耦。也就是上层用什么公平性策略和底下这套decouple
  • 地址转换在metadata服务器上执行。evaluation证明可扩展性已经够了
  • 块大小,为了兼容,它采用了分析框架中通常用于文件的块大小,例如HDFS中的128MB
  • 隔离粒度,虽然现在是根据task隔离的(前缀隔离),但是可以更细,手动添加前缀

Data Lifetime Management

现有的用于无服务器分析的远端内存系统按作业级资源分配,也按作业粒度管理数据寿命--在作业明确取消注册时回收存储。 无服务器分析的一个独特特点是,任务的中间数据与它的执行脱钩:虽然它的执行发生在无服务器计算平台上,但它产生和消耗的数据将驻留在远端内存系统上。 这也导致了它们的故障域的解耦:在标准的机制下(例如,参考计数方法),当任务失败时,其相应的中间数据在远端内存系统中成为悬空状态。 为了避免由此产生的低效率,我们需要额外的机制来有效地执行任务级数据寿命管理。

通过整合lease management机制和分层寻址来解决这一问题。 一个作业会定期更新目前正在运行的任务的地址前缀的租约。 在一个特定的地址前缀的租约到期时,Jiffy在将数据flush持久性存储后收回分配给它的所有内存。其实就是保持前一跳和后一跳的一起维持。

Flexible Data Repartitioning

通过让块自己repartition,而不是compute task。

分配给Jiffy数据结构的每个块都会跟踪当前用于存储数据的块内存容量的部分。 每当使用量增长超过一个高的阈值,Jiffy就会反过来为相应的地址前缀分配一个新的块。 随后,过载的区块会触发数据结构特定的补偿,将其部分数据转移到新区块。

同样,当区块的使用量下降到低阈值以下时,Jiffy在地址前缀中识别出另一个使用量低的区块,该区块可以与之合并其数据。 然后,该区块进行所需的重新分区,之后Jiffy将其deallocate。