内附原文|论文解读:PolarDB计算存储分离架构性能优化之路
分享人:陈宗志(暴跳)
摘要:本篇论文收录在 VLDB 2022,介绍了云原生数据库PolarDB在计算存储分离架构下遇到的性能挑战,分析了云存储相对于传统本地存储的工作特性差异及其根因,讨论了将各类存储引擎部署至云存储上时所会遇到的问题挑战,并提出了统一的优化框架 CloudJump。最后通过实验证明优化框架CloudJump适用于PolarDB,也适用于 RocksDB。
01. 背景
1.计算存储分离架构云数据库存在的问题
下图左边是本地集中式数据库,右边是计算存储分离架构数据库。本地数据库通过本机 Cache 到 Local I/O再到 Local SSDs;计算存储分离架构数据库:在计算存储分离架构下会带来网络开销,同时也会产生其他存储副本。
2.项目目标
a. 计算存储分离云数据库的优势:
海量存储能力;
快速弹性能力;
服务高可用,数据安全可靠;
极致性能;
Serverless、pay-as-you-go;
b. 云端成熟的云存储服务的优势:
海量存储能力;
数据持久化、服务高可用;
聚合 I/O 吞吐性能高;
用量可选,弹性计费;
充分运用规模化云存储能力;
存储侧不暴露容错等复杂细节;
减少维护成本、加速数据库开发周期。
3.早期实验发现
下图对比了在稳态条件下,本地 SSD 与云存储在 I/O 延时、吞吐量与工作线程的关系,其中紫色线是本地 SSD,橙色线是云存储,灰色线是云存储打撒 I/O。
左图是 I/O 延迟与工作线程的关系,可以看到,本地 SSD 的 I/O 延迟远优于云存储;
右图是吞吐量和工作线程的关系,可以看到,云存储的吞吐量比本地 SSD 要高。
由于远端访问的高时延,采用云存储后出现慢 SQL;
I/O 时延大、聚合带宽高;
多节点一致性造成数据库网络带宽利用率低;
I/O 隔离性问题导致刷脏时 WAL 写入性能下降。
4.云存储差异化特性带来的挑战
下图中的表格总结了上述挑战对数据库设计的影响。对比基于 B-tree 结构(Update-in-place)和基于LSM-tree 结构(Append-only),其中有共性问题,如 WAL 路径写入变慢、共享存储(分布式文件系统)cache 一致性代价等;也有个性问题,如 B-tree 结构在独占资源情况下做远程 I/O、远程加剧 I/O LSM-tree 读放大影响等。
02. 设计思考
基于上述挑战以及云盘的特征,CloudJump提出7条优化准则:
依据 I/O 特性实验,采用(更)多线程的日志、数据 I/O 线程及多队列异步 I/O 模型,将数据打散到多个存储节点上,充分利用多个存储节点的 I/O 能力;
与本地 SSD 上相比,这些技术在云存储上更能获得收益;
云存储中较长的 I/O 延迟放大了同步开销,主要针对 B-tree,实现无锁刷脏、无锁 SMO 等;
在云存储中,多个节点之间的分散访问可以利用更多的硬件资源,例如将单个大 I/O 并发分散至不同存储节点 ,充分利用聚合带宽的能力;
通过 Bypassing Caches 来避免分布式文件系统的 cache coherence,并在 DB 层面优化 I/O 格式,匹配存储最佳 request 格式;
由于访问链路更长(如路径中存在更多的排队情况),不同 I/O 请求间的隔离性相对本地存储更低,因此需要在 DB 层面对不同 I/O 进行打标、调度优先级,例:优先 WAL、预读分级。
03. 案例实践:PolarDB
优化后的 PolarDB 架构如下图所示,左上是读写节点(RW node),右上是只读节点(RO node),下面是共享存储(云存储)。
1.WAL写入优化
WAL 写入性能优于 I/O 延迟高而降低;
I/O 串行化,带宽利用率低;
▶︎日志缓冲区(Log buffer)分片,写入并行化;
将 redo 的日志缓冲区按其修改的 page 进行分片(partition),分别写入不同的文件中,支持并发写 log,从而在适合并发写入的分布式文件系统上的获得写入性能优势;
▶︎异步多任务线程,带宽利用率高;
写入不同的文件就会映射到不同的存储节点,利用存储多节点的 I/O 能力可以提升带宽利用率;
下图左将redo日志缓冲区分片:Log Buffer1&2&3,其中绿色的小方块代表已经写满的连续的 redo 日志,旁边的小方块是有缓冲区的日志,橙色方块是 pending 日志,需要将绿色和橙色块之间的部分填满,形成连续的 redo 日志后,再继续往下写。
下图右是对于单个大 log I/O任务(如 group commit、BLOB record 等),log writer 会将I/O切片,并且并发的分发 I/O 请求至不同 split。
2.快速恢复
3.预读取
4.并行恢复
基于 Page Partition 分片,多任务并发恢复/日志解析和申请。
5.锁优化
首先对当前 page 构建内存副本,构建好内存副本后原有 page 的 sx 锁被释放,然后用这个 shadow page内容去做刷脏及相关刷写信息更新。
6. I/O对齐和调度
a. 针对分布文件 BypassCache 导致的直接 I/O
对齐最优化的 I/O offset&length,加速 directI/O;
去除无效 I/O 合并,发挥随机写特性;
多异步 I/O 任务队列,充分并行化,发挥带宽优势。
I/O 优先级调度,优先关键 I/O,消除低隔离影响。
7.数据测试结果
将 MySQL 分别运行在 PolarStore 和本地盘,以及优化后的 PolarDB 进行性能对比,从下面 Figure 10图中可以看到,优化后的 PolarDB 在 CPU-bound, I/O-bound sysbench, TPC-C 等各个场景下,都表现出明显的性能优势。
图11是不同的优化策略在 CPU-bound(只写、读写), I/O-bound(只写、读写), TPC-C 场景下的性能提升的力度和大小,可以看到优化策略在 CPU-bound场景下,性能普遍提升比较明显。
图12是不同优化策略在 WAL 加速方面的表现。
另外,还测试了云存储优化的 PolarDB 运行在 StorageX,、ESSD 等其他云存储上的性能, 发现均能获得非常好的性能提升。如下表所示,对比这个云存储,在延迟性能上,PolarStore 的延迟最低。
04. 实践案例:RocksDB
我们还将设计框架及部分优化策略拓展到基于云存储的 RocksDB 上,以验证其通用性。
1.优化后的RocksDB框架
2.数据测试结果
Scattered & Partitioned Global Log;
Multi-queue Scatter I/O with Schedule;
Direct I/O Alignment;
下图是 RocksDB 在优化前后各种性能的对比,柱状图最左边的是 Baseline,可以看到在不同场景下,RocksDB 的优化性能有不同的表现。
05. 总结
在这项论文工作中,主要分析了云存储的性能特征,将它们与本地 SSD 存储进行了比较,总结了它们对B-tree 和 LSM-tree 类数据库存储引擎设计的影响,并推导出了一个框架 CloudJump 来指导本地存储引擎迁移到云存储的适配和优化。并通过 PolarDB, RocksDB 两个具体 Case 展示优化带来的收益。
点击观看「论文解读」直播回放