Pocket -- Elastic Ephemeral Storage for Serverless Analytics


Pocket: Elastic Ephemeral Storage for Serverless Analytics

0x00 引言

Pocket是应对Serverless架构出现的一种Ephemeral Storage(暂时性存储)的解决方案。这类存储与诸如Spanner/ Amazon Aurora数据库存储、Haystack之类的图片存储或者是Dynamo之类的Key/Value存储系统存在很大的区别。对于 Elastic Ephemeral Storage(EES)系统被认为要满足这样的几点要求,

  • 对大范围的对象大小都有着很高的性能;
  • 自动地细粒度的拓展,在满足要求的情况下分配最小的资源,节约成本;
  • 对使用的存储技术有感知,以便能够能够用做合适的方式使用存储资源和满足应用的要求;
  • 容错,EES这类系统而言,生命周期一般只有10s - 100s,也就没必要项一般的存储系统那样对容错性有着很高的要求。
Pocket dynamically rightsizes resources across multiple dimensions (CPU cores, network bandwidth, storage capacity) and leverages multiple storage technologies to minimize cost while ensuring applications are not bottlenecked on I/O. We show that Pocket achieves similar performance to ElastiCache Redis for serverless analytics applications while reducing cost by almost 60%.

0x01 基本设计

Pocket的主要设计理念,

  • Separation of responsibilities,Pocket将系统分为3个plane。Controlplane主要负责集群和数据的位置。Metaplane追踪在dataplane数据在跨节点之间的存储。Dataplane主要就是存储数据;
  • Pocket要求亚秒级的反应时间;
  • 多层存储,Pocket要处理DRAM、Flaskh和磁盘的等的存储,Pocket将其分层管理;

pocket-arch

如上面的示例图所示,Pocket有一个逻辑上的中心的控制器,一个or多个元数据服务器,若干的数据存储服务器。控制器会分配给任务存储资源,并会动态分配/拓展元数据服务器和数据服务器的数量。控制还会决定使用那个服务器和那种存储介质来来服务这个任务(任务数据存储的位置)。元数据服务器以Block为粒度管理管理数据的存储,这里的Block的大小选择了64KB,如果一个对象大于来Block的大小就会被分为多个block存储,这样Pocket就能过支持任意大小的数据对象。元数据服务器负责施行控制器决定的数据存储位置策略,并会把客户端的请求引导到对应的存储位置。

pocket-api

Pocket的API的一个核心就是Job。Client会先创建一个Job,等的一个JobID,之后的客户端就使用这个得到的JobID来作为一个操作的参数。对于控制器的API主要就是Job的创建和关闭,元数据相关的API主要就是连接相关的操作,Bucket相观的操作和验证对象的存在和删除。对于最下面的两个存储的API主要是一种增加的对象的读写控制。Pocket另外的一些内容,

  • 客户端在注册Job的时候,hint参数会项控制器提供Job 的一些特性,以便于控制器决定控制器决定使用什么样的存储。注册号Job的时候,利用返回的时候提供的元数据服务器的IP地址去访问元数据服务器,客户端读写数据的时候是根据从从元数据服务器获取到的存储服务器的IP地址和Block的地址。在Job执行的时候,控制器会时刻监控资源的利用,动态分配资源。在Job完成的时候回收使用的资源;
  • Pocket不为提供数据的持久化保存设计。不过Pocket也提供了一些容错的措施,存储服务会发送心跳信息给控制器。在一个存储服务器故障的时候,元数据服务器会将相关的数据Blocks标记为无效的。目前是通过重新执行Job来重新生成数据。

0x02 调整资源分配

Pocket对资源的分配主要从容量、吞吐、和存储介质的选择的上。Pocket会根据注册Job的时候hint参数来使用启发式的方式来分配资源,在没有指定这个hint参数的时候,Pocket会默认认为Job是延迟敏感型的,会默认选择的高性能的资源分配方式,当然对应的就是高的成本。另外Pocket分配资源的一个条件是lambda的数量,

  Knowing a job’s maximum number of concurrent lambdas, N, allows Pocket to compute a less conservative estimate of the job’s throughput requirement. If this hint is provided, Pocket allocates throughput equal to N times the peak network bandwidth limit per lambda (e.g., ∼600 Mb/s per lambda on AWS). N can be limited by the job’s inherent parallelism or the cloud provider’s task invocation limit (e.g., 1000 default on AWS).

Pocket使用一个weight map的关联数组表示资源的分配。这个关联数组的Key为服务器的Key+Port,Value为0到1的一个数,表示保存在这个服务器上面的数据的比例。 Pocket使用的一些分配资源的规则,

pocket-hint

控制器会监控存储服务器和元数据服务器的资源使用率。在启动一个新的存储服务器的时候,控制器回向其提供所有的元数据服务器的IP地址的信息,这个存储服务器会向所有的元数据服务器建立连接,并向每一个元数据服务器注册一部分的资源,元数据服务器可以自由管理分配给它部分的资源。存储服务器也会向元数据服务器发送心跳。Pocket另外的几个内容,

  • 为了移除一个存储服务器,控制器会将其的权重设置为0,这样可以避免元数据服务器避免将新的Job的存储保存到要移除的存储服务器的,当等到等到上面的资源完全释放的时候,这个存储服务器就可以完全移除,释放资源。

  • 控制器启动一个新的元数据服务器的时候,元数据服务器会等待新的存储服务器启动并注册它们的容量。移除一个元数据服务器的时候,控制器通过call一个“Kill” RPC给这个元数据服务器,这个元数据服务器会等到它管理的资源都被释放的时候,然后通知存储服务器关闭它们的连接,之后这个元数据服务器就可以关闭了。存储服务器会新注册它们的容量。

  • Pocket可以配置一个目标资源利用率的区间(比如60% – 80%),会通过移除和添加服务器来调整资源的利用率。

    Pocket’s controller scales down the cluster by removing a storage server if overall CPU, network bandwidth and capacity utilization is below the lower limit of the target range. In this case, Pocket removes a storage server belonging to the tier with lowest capacity utilization. Pocket adds a storage server if overall CPU, network bandwidth or capacity utilization is above the upper limit of the target range. 
    
  • 在Pocket中使用数据迁移的方式来解决负载均衡的问题是不合适的,因为Pocket中的Job的生命周期都比较短。因此Pocket使用的方式是通过调整权重参数,对于低利用率的参数,就可以调高这个服务器的权重参数。

0x03 评估

这里具体的信息可以参看[1],

packet-perf

参考

  1. Pocket: Elastic Ephemeral Storage for Serverless Analytics, OSDI 2018.