作者:刘玮 RisingWave Labs 内核开发工程师
1. 背景
在「Hummock :专为 RisingWave 流处理而设计的云原生存储引擎」一文中里我们已经介绍了 Hummock 的设计理念与基本架构,本文主要介绍 Hummock 近期几个版本的重大改进与优化。
2. Fast Compaction
在设计之初,Hummock 的数据文件格式参考了 RocksDB Sstable 的设计。之后为了提升查询性能,Hummock 引入了 Xor Filter 用于替换原有的 Bloom Filter (RocksDB 也引入了基于 Xor Filter 改造的 Ribbon Filter 算法)。但是 Xor Filter 在构建过程中会短暂使用大量的内存,为了减少内存的使用,Hummock 改造了数据存储格式,转而为每个 block 单元的数据构建 Filter 而不是构建全局的单一 Filter,从而降低了构建过程中的内存峰值,使得 RisingWave 可以运行在更加低配的环境中。
LSM Tree 相比 BTree 类的数据结构而言,通过顺序写入+后台整理的方式换来了更高的写入吞吐,然而也付出写放大的代价的,也就是说同一份数据可能会被反复整理(compact),更多细节参考此处。对于 L1 及更旧的数据而言,当数据库试图把上层的一个文件的数据挪到下层时,往往会和下层的多个文件产生重合,为此不得不把远多于一个文件引入同一个 compact 任务中,这正是写放大的主要来源之一。我们注意到,即便上层的文件和下层的多个文件产生了范围重叠,依然不意味着上层的每一个 block (通常在 4KB ~ 256KB 之间)都和下层的某个 block 产生了范围重叠,除非每次写入的数据都在同一个范围内严格的等概率分布。因此,如果我们的 compact 算法不是按照 key 为粒度来遍历数据,而是以 block 为粒度,那么对于那些没有和任务中其他文件的 block 产生重叠的 block,可以避免解压以及再次压缩的开销,直接将这部分数据复制到新的文件中。
传统的 compact 算法如下图所示:
而改进后的算法如下图所示:
通过对比可以看出,SST2 中的 block-1 和 block-3 如果和 SST1 中的数据没有重复的话,可以直接复制到输出文件中,避免额外的解析以及压缩开销
我们测试了多种不同的读写负载,该优化能够节约20%~50%的 compactor CPU 资源。对于那些写入数据较多、吞吐较大的场景,该优化能够显著降低 compact 操作带来的成本问题。目前该功能还在测试中,默认不开启。
3. IO Prefetch
由于 Hummock 的存储设计和 RocksDB 一样,是基于 Block 为粒度来组织数据。当上层应用查询数据时,会逐个读取 block ,如果 block 不在 cache 中,则触发一次 IO 操作读取 remote storage (如果是 AWS 环境部署,则后端为 S3 存储)。然而对 S3 有所了解的开发者都知道,S3 的随机读延迟极高,更适合用于大对象的顺序读取。因此,当用户执行 OLAP 类型的查询时(例如:select count(*) from mv; ),Hummock 需要逐一发送 IO 操作,极大地增加了查询耗时。还有一种类似的场景,对于已经导入的数据表,用户希望再次创建出另外的 Materialize View, 此时也需要遍历所有的历史数据,因此也会受制于上面所提到的读取方式。
因此,对于 RisingWave 中的 batch 查询,我们在底层的存储中,当发现 cache 中没有当前 block 时,会一次性读取当前范围内的多个 block。通过这样的方式我们能够尽可能最大限度地利用用满 S3 的带宽吞吐,同时由于 S3 按照 IO 个数收费,而流式接口只算做一次 IO,因此该优化也同时降低了 S3 的 IO 成本。通过一些简单的测试,该优化可以提升部分 OLAP 查询速度至多 8 倍。当然这只是极端情况下,还有很多复杂的 SQL 瓶颈在于计算操作,实际提升还取决于查询类型与业务场景。
4. 总结
除了查询性能以外,成本也是数据库所关注的重点。对于 AWS S3 这样的存储后端来说,除了存储数据按照大小每月固定收费以外,IO 操作按照次数收费。因此,除了优化性能以外,如何利用 S3 的高吞吐高延迟的特征,尽可能提高 S3 的使用效率来降低成本,也是我们优化存储系统的重要方向之一。接下来我们会根据查询计划的不同更加精确地选择 IO 策略来进一步提高处理速度,以及基于本地磁盘作为二级缓存来进一步提高命中率,减少对 S3 的访问频率。
5.关于 RisingWave
RisingWave 是一款分布式 SQL 流处理数据库,旨在帮助用户降低实时应用的的开发成本。作为专为云上分布式流处理而设计的系统,RisingWave 为用户提供了与 PostgreSQL 类似的使用体验,并且具备比 Flink 高出 10 倍的性能以及更低的成本。
🔧如果你还不知道如何上手 RisingWave,请体验中文入门教程:www.risingwavetutorial.com/
💻想要更深入地理解并使用 RisingWave,请阅读中文用户文档:zh-cn.risingwave.com/docs