本部分开始为最新的学习笔记。包含 PolarDB Serverless。
PolarDB Serverless: A Cloud Native Database for Disaggregated Data Centers
https://users.cs.utah.edu/~lifeifei/papers/polardbserverless-sigmod21.pdf
INTRODUCTION
大概有三种 cloud 数据库的架构:
- monolithic
- virtual machine with remote disk
- shared storage
后两种也被统称为存算分离的架构。
存算一体的架构缺点:
- 将 db 分配到对应的机器类似于解决 bin-packing 问题
- 难以满足客户的灵活的资源需要
- 资源之间没法独立地进行恢复
下面两种存算分离的架构:CPU 和内存同样存在 bin-packing 的问题,内存开销大。
因此 PolarDB Serverless 共享了内存。
和 Aurora、HyperScale 以及 PolarDB 一样,它有一个 RW 的主节点,以及多个 read only replica。它也可以通过提出的 disaggregation 架构支持多个 RW 主节点,但不在这个论文中讨论。
一些挑战:
- 引入共享内存后,事务的正确性。
- read after write 不会在节点间丢失修改 -> cache invalidation
- RW 节点在 split 或者 merge 一个 B+Tree 的时候,其他的 RO 节点不能看到一个不一致的 B 树 -> global page latch
- 不能脏读 -> 在不同的 database node 间同步 read view
- 网络延迟
- 使用 RDMA CAS 技术提优化 global latch 的获取
- page materialization offloading 技术将 dirty page 从 remote memory 中驱逐,而不是将它们 flush 到存储中
BACKGROUND
PolarDB
介绍了 PolarFS。
RW 和 RO 节点通过 redo log 同步内存状态。通过 LSN 实现一致性,其执行流程是:
- 将所有的 redo log flush 到 PolarFS 中
- 提交事务
- RW 异步广播消息:read log 以及最新的 LSN 即 LSN_rw。
- 当 ROi 收到 RW 的消息后,从 PolarFS 上拉取所有的 redo log,将它们 apply 到 buffer pool 中的 buffered page 里面
- ROi 此时就和 RW 完成了已同步
- ROi 将自己的 LSN_ro 发送给 RW
- RW 可以在后台将 read log 去 truncate 到所有的 LSN_roi 的最小值
- ROi可以处理 LSN_roi 之前的读取,提供 SI 隔离级别
假设某个 ROk 落后了,比方说落后超过 1M,这样的节点会被发现,并且被踢出集群。
Disaggregated Data Centers
在 disaggregation 架构下,一个数据库实例所需要的计算、内存和存储资源将被分配到同一个 PoD 下面。不同的 db instance 则看见恶意分配到不同的 PoD 下面。计算和内存资源会被尽可能分配到同一个 ToR 下面。
一台机器有两个 RDMA NIC,他们会被连接到两个 ToR 交换机上面,从而避免网络连接失效。一个 leaf switch group 由多个 leaf switch 组成。ToR switch 连接到 leaf switch 上。
Serverless Databases
pay-as-you-go model。
一个 ACU 包含了 2GiB 的内存以及对应的虚拟处理器。这个设定 fixes the resource ratio。比如,分析数据库可能需要更多的内存,而不是 CPU,因为它们可能要 cache 大量的数据。对应的,事务数据库需要大量的 CPU 去处理业务的尖峰。而一个小内存,只要能满足 cache hit,那也是足够的了。
DESIGN
Disaggregated Memory
Remote Memory Access Interface
这里内存也是按照 Page 来组织的。一个 PageID 可以表示为 (space, page_no)。使用 page_register 和 page_unregister 去做类似 RC 一样的内存管理。page_read 从 remote memory pool 拉数据到 local cache。page_write 将 page 从 local cache 写到 remote memory pool。page_invalidate 被 RW 调用,用来将所有 RO 的 local cache 上的 page 设置为无效。
Remote Memory Management
内存分配的单位是 slab,一个 slab 是 1Gb。
Page Array(PA)
一个 slab 被一个 PA 结构实现。一个 PA 是一个连续的内存,包含 16KB page 的 array。PA 中的 page 可以被 remote node 通过 RDMA 直接访问,因为他们在启动的时候就已经被注册到 RDMA NIC 上了。
一个 memory node 也被称为一个 slab node。一个 slab node 管理多个 slab。一个实例可以对应到多个 slab node 上,其中第一个 slab node 称为 home node。home node 中有一些 instance 级别的元数据。
Page Address Table (PAT)
PAT is a hash table that records the location (slab node id and physical memory address) and reference count of each page. 也就是前面 page_register 和 page_unregister 所操作的东西。
【Q】这个结构保存在哪里?
Page Invalidation Bitmap (PIB)
PIB is a bitmap. For each entry in the PAT table, there is an invalidation bit in PIB. Value 0 indicates that the copy of the page in the memory pool is of the latest version, while value 1 means that the RW node has updated the page in its local cache and haven’t written it back to the remote memory pool yet. There is also a local PIB on each RO node, indicating whether each page in the RO node’s local cache is outdated.
Page Materialization Offloading
Aurora 提出 log is database 的理论。将 redo log 看做是增量的 page 修改。Socrates 进一步地,将 log 从 storage 分离。Log 被存在 XLOG 服务中,然后被异步地发送到一系列 page server 中,每一个 page server 负责一个 database partition,独立地重放日志,生成 page 并处理 GetPage@LSN 请求。
PolarDB 类似于 Socrates,将 PolarFS 设计为分别存放 log 和 page 到两个 chunck 中。redo log 首先被持久化到 log chunkc 中,然后被异步地发送到 page chunck 中。在 page chunck 中,logs 被 apply,从而更新 page。不同于 Socrates,为了重用 PolarFS,log 只会被发送到 page chunk 的 leader 节点,这个节点会物化 page,然后将 update 通过 ParallelRaft 通知给其他的 replica。This method adds additional latency to the ApplyLog operation due to the replication cost. However, it is not a critical issue because ApplyLog is an asynchronous operation not in the critical path. Moreover, since the replicated state machine guarantees data consistency between page chunks, there is no need for an extra gossip protocol among storage nodes like in Aurora.