通过存储功能缩小无服务器计算与其状态之间的差距

    本文详细描述了一种通过后端特定实现的一种存储功能(功能传递function shipping)来实现:

    • (a) 您可以避免通过网络移动潜在的大量数据以进行处理,
    • 并且(b)如果函数遍历在单个调用中无法获取的结构,则可以将多个远程调用折叠为一个。实现类似计算层面的group aggregation.

    无服务器计算因其细粒度而受到关注资源调配、大规模多租户和按需扩展。但是,它还强制应用程序在远程
    存储,增加大量的管理费用。修复这个“数据传送”问题“我们构建了一个低延迟的多租户云存储,它允许直接执行小的计算单元在存储节点内。存储租户为Shredder提供JavaScript可以直接交互的函数(或WebAssembly程序)
    不需要在网络上移动数据。Shredder的关键挑战是安全隔离成千上万的租户存储功能,同时最小化数据交互成本。
    Shredder采用独特的方法,其数据存储和网络路径以本机代码实现以确保性能,独立的租户函数使用V8定制的
    避免昂贵的交叉保护的中间表示域调用和数据复制。因此,Shredder可以执行每秒400万个远程调用的租户函数
    数千名租户的中位和第99百分位反应分别小于50微秒和500微秒。我们的评价结果表明,Shredder的速度提高了14%到78%对比通过调用跨国远程存储来实现计算单元作业。我们还演示了Shredder有效地加速数据密集型应用程序,包括显示数量级的社交图的k-hop查询获得。

    Shredder是“一个低延迟的多租户云存储,允许在存储节点内直接执行小计算单元。”

    当然,在数据存储中运行最终用户计算并非没有挑战。从运营商的角度来看,这使得遵循传统的云本地设计变得更加困难,在这种设计中,一个全局存储层是分开进行计算的。用户函数需要彼此隔离,并且与不应允许它们看到的数据部分隔离。而且,随着CPU在租户和数据服务基础设施之间共享,一定程度的资源隔离可以确保失控(或恶意)的功能不会占用所有的资源。碎纸机解决了这些挑战的功能隔离部分——尽管承认侧通道总是很难完全消除——但对其他方面却保持沉默。然而,因为它非常适合无服务器计算的无状态模型,所以这是一个非常有趣的想法。

    一个关键的挑战…是无服务器函数是无状态的。云提供商依靠这一点来简化资源调配和容错。实际的应用程序需要访问数据和状态;这一限制迫使函数远程访问所有数据,并迫使它们将所有状态外部化到远程云存储中,以便在调用之间保留它或将状态传递给另一个函数。

    (请注意,函数传送并不能减少将状态外部化的需要)。

    Shredder的目标如下:

    • 租户应该能够在存储中嵌入任意函数,并且这些函数应该能够无缝地访问租户的数据
    • 租户不应该能够看到其他租户的代码或数据(隔离)
    • 支持数以千计的租户功能,具有细粒度的资源跟踪,以最大限度地利用资源
    • 高性能

    引进Shredder
    如果你想要一个轻量级,快速启动,易于编程,可嵌入的应用运行时,也提供了隔离,那么自然选择是V8隔离。作者测量了将控制权转移到V8运行时并在196ns时再次返回的开销。用户使用JavaScript(或Web程序集)编写函数,V8隔离与存储子系统(在存储子系统内)共有。
    V8足够轻量级,可以轻松地支持数千个并发租户。与基于硬件的隔离机制相比,进入/退出V8上下文的成本更低,从而使请求处理延迟和吞吐量保持在较低的水平。

    shredder-fig-2.jpeg

    这些V8隔离位于每个存储节点中作为存储功能层的三层设计的中间。其中的In是一个网络层,而In-memory存储层保存实际的数据。碎纸机的实现是建立在Seastar之上的。

    shredder-fig-1.jpeg

    进出V8运行时需要196ns,但每次在JavaScript函数和存储层之间传输控制时,也需要31ns的开销,如果每次访问数据都需要这样做的话,这个开销就会增加(注意上图中存储层中的实际数据位于V8之外的内存中)。Shredder有两种机制,可以保持较低的开销。首先,它支持使用映射到底层内存的arraybuffer进行零拷贝数据访问。其次,对于需要在上下文和可信存储代码之间持续传输控制的数据密集型操作(例如,遍历涉及多个密钥的链接数据结构),碎纸机具有使用V8的(内置v8 CodeStubAssembler(CSA))构建的上下文存储操作。(新的推荐方法以实现相同的v8特性现在的实现为Torque)。

    GSA()的CSA版本实现了与存储层中的哈希表的C++哈希函数相同的哈希算法,从而直接查找哈希表中的值。从存储函数的角度来看,存储仍然支持相同的get()和put()存储接口。使用从[CSA 中间表示层]生成的代码,租户可以在不离开V8运行时的情况下有效地遍历结构。

    shredder-fig-5.jpeg

    Shredder运行时

    评估结果表明,核心Shredder存储可以在50微秒内响应每秒400万次存储功能调用,尾部延迟约为500微秒。随着租户数量的扩大,吞吐量保持相当稳定(评估结果高达1024个租户)。根据不同的用例,CSA将服务器吞吐量提高了3.5倍。

    shredder-fig-6.jpeg


    因此,核心功能航运设计似乎运作良好。但真正的好处当然来自于这样一个事实:您可以首先设计您的解决方案以利用功能交付。考虑一个需要对服务器上存储的多个值进行简单投影的用例。在Shredder中,这可以在具有单行存储功能的服务器上完成。另一个例子是列表遍历,Shredder可以在服务器端执行此操作。
    shredder-fig-8.jpeg

    利用Facebook上的好友列表数据集,作者实现了一个随机生成的社交图密钥的k-hop查询应用程序(共有4039个节点和88234个边)。下表显示了具有存储功能的基于碎纸机的实现与传统远程get/put实现的吞吐量。

    shredder-fig-9a.jpeg

    总结
    Shredder朝着解决[计算和数据之间的差距]迈出了一步;虽然应用程序可以将其用作普通的键值存储,但它们也可以将compute直接嵌入到数据旁边。无服务器应用程序已经在逻辑上将应用程序分解为细粒度单元,以便于扩展;我们将Shredder视为开发这一功能的第一步,因为我们认识到逻辑分离计算和存储不需要强制物理分离。