Plasma Prototype: Arch and API

less than 1 minute read

Code analysis on the prototypical implementation of Plasma, a distributed in-memory object store.

Redis, Plasma and Lightening

arch

Danyang Zhuo, Kaiyuan Zhang, Zhuohan Li, Siyuan Zhuang, Stephanie Wang, Ang Chen, and Ion Stoica. 2021. Rearchitecting in-memory object stores for low latency. Proc. VLDB Endow. 15, 3 (November 2021), 555–568. DOI:https://doi.org/10.14778/3494124.3494138

Plasma Arch and API

plasma_arch

Redis 和 Plasma 架构相似,Server进程是其中的核心。Server接受(多个)Client进程的请求,在处理它们的过程中又向更底层的Store进程发送请求。这种架构实现简单,而且相比Lightening的共享内存方案是“直观”的。以plasma来说:

  1. Client定义上层应用可用的API:
    1. 连接/断开:plasma_connect/plasma_disconnect
    2. 查询本地对象:plasma_contains
    3. 写/读/删对象:plasma_create(plasma_seal)/plasma_get/plasma_delete
    4. 拉取远端对象:plasma_fetch(跨节点通信)
  2. Server是实现跨节点fetch的地方:
    1. process_fetch_requests(这里会发生一次redis,即GCS查询) -> process_fetch_request
    2. process_transfer_request
    3. process_data_request:这里接收方会调用plasma_create,然后从Socket中拷贝数据进去
    4. process_seal:封存对象,这里会发生一次redis更新
  3. Store是实现本地Create/get的地方:我关注进程如何共享内存实现Create和Get?

plasma_fetch的通信机制如图

plasma_send

这样Client API的操作流程就明确了:

  • plasma_contains 查询本地对象,成功后可以plasma_get
  • plasma_create 进行本地创建操作,填入数据后调用plasma_seal。seal会更新redis的元数据,使得其他Client可以看到对象,并且调用fetch
  • plasma_fetch 获取一个远端的对象。

这里有一个问题,plasma似乎需要对象在集群中一定是存在的,因为fetch操作需要ID,fetch一个不存在的ID程序会崩溃。并且ID是用户程序(例如Ray)提供的,而不是Plasma生成的。 因此对象管理的逻辑并不实现在这一层。

共享内存?

简单了解了多进程如何实现共享内存。其实是基于mmap这一神器,围绕着一个file descriptor(再一次感慨一切皆文件:Socket, etc.)

  1. 首先要有一个(内存)文件,大小和内存buffer相同。描述符为fd,然后进程1调用mmap将一段虚拟内存空间和fd绑定,返回地址指针。
  2. 使用ipc(Unix Domain Socket)将这个fd交给另一个进程2
  3. 进程2再次以fd使用mmap,返回的地址指针。

代码中,由Store进程维护fd表。这样plasma_get实际上就是在一个Client进程中,用recv_fd调用从Store拿到fd,然后以该fd执行了步骤3,和Store共享了虚拟内存空间。

Categories: ,

Updated:

Leave a comment