深度干货 | 揭秘 YashanDB 融合存储引擎
第 2 期技术 Meetup《崖山论“见”》顺利举办,在这里将 YashanDB 存储引擎负责人郭藏龙的精彩分享整理成文章,方便大家学习回顾。本篇是 YashanDB 存储引擎总览,主要围绕以下三点展开:
融合存储引擎架构介绍
存储引擎关键技术实践
存储引擎技术探索与展望
全文 3827 字,阅读时长约 8 分钟。
01 融合存储引擎架构
存储引擎是数据库内核的重要组成部分,存储引擎的设计决定了以何种方式存储数据、如何读取和写入数据,也在很大程度上决定了数据库的读写性能与数据的可靠性。
YashanDB 是一款覆盖 OLTP/HTAP/OLAP 多场景的数据库产品,在存储引擎设计上采用融合架构,基于统一基础设施构建了不同的存储能力,支持 In-place Update 行存储,适应 TP 场景;支持原位更新(In-place Update)和追加式(Append-only)两种列式存储,具备原生 HTAP 能力和海量数据分析能力。
YashanDB 研发团队选择从零自研存储引擎,没有基于任何开源产品二次改造,保证架构、代码的自主可控与持续演进。
从架构上看,YashanDB 的存储引擎分为两个大的模块:
一是存储引擎的基础设施部分,是底层中的底层,包含事务引擎、持久化、高可用、故障管理以及资源管理的能力。
二是在基础能力之上构建的具体存储能力,包含对象管理、缓存管理、存储结构、数据空间以及数据持久化的能力。
本文将从 YashanDB 存储引擎的全场景高性能设计、高可用能力、基础设施优化三个方面进行介绍。
02 全场景的高性能设计
YashanDB 在高并发事务处理、海量数据分析以及混合负载场景下均表现出优异的性能,这与存储引擎的设计密不可分。
高并发事务处理
MVCC(Multiversion Concurrency Control,多版本并发控制)是主流的事务并发控制机制,但是不同数据库的实现差异较大。目前比较主流的实现方式是 Append-only 行级 MVCC 和 In-place Update 行级 MVCC。
Append-only 行级 MVCC,更新数据时新增一条数据,优点:不需要额外的 Undo 空间,管理方便。缺点:会带来较大的空间膨胀、垃圾回收开销大;查到最新版本的代价高;修改需要拷贝整行,对宽表的处理不友好。
In-place Update 行级 MVCC,更新记录时对原始数据进行覆盖,优点:解决了 Append-only 行级 MVCC 的几个痛点问题。缺点:需要引入独立的 Undo 空间管理机制;查询最新可见版本时回滚开销大;行存储开销大。
为追求极致的并发事务性能,YashanDB 采用 In-place Update 块级 MVCC,针对 In-place Update 行级 MVCC 作了进一步的优化:
相较于追加式行存,历史版本记录增量数据,实现历史版本的独立存储,数据不膨胀;
每个数据块的 Undo 数量与 Row 解耦,降低了多版本管理的空间开销;
一致性数据块按需全局缓存,会话内及会话间共享,减少并发场景构建开销;
基于块级的 MVCC 可以实现批量处理合并 Undo,提升效率。
Btree 索引是 YashanDB 存储引擎架构下最重要的索引结构,它直接影响事务的处理能力。但 Btree 索引在数据库实现方面会面临几个主要的痛点:
在分裂的过程中如果有搜索,由于索引结构的变化,可能导致结果不正确;
由于 Btree 的 Update 是删除再插入,所以随着业务的更新,会出现空洞以及空间膨胀问题,严重影响 Btree 的效率。
并发较高的情况下,较高层的节点(Root 或者第一层 Branch)访问冲突会比较大,影响扫描效率。
针对上述三个问题,YashanDB 对 Btree 索引做了如下优化:
通过全节点 MVCC 方式实现了无锁 Btree,访问时还原节点当前的可见版本,并不受当前分裂版本的影响,搜索与搜索、搜索与分裂、分裂与分裂之间均可以并发;
支持 DML 过程中动态回收空页以及合并系稀疏页,对于用户透明不感知,无需人为 DDL 操作定期回收空页,有效解决了空间膨胀问题,极大地降低了长时间运行后的 Btree 性能劣化;
引入热页缓存机制,针对 Btree 高频访问的 Block 可以做到 Latch-free,消除全局资源竞争,极大的提升了索引并发性能。
海量数据高性能分析
企业需要处理的数据量增长迅速,企业往往需要在成本、访问频率之间进行平衡。为解决这些挑战,YashanDB 存储引擎基于不同的存储结构提供透明分层存储能力,可以帮助企业根据访问频率的高低对数据进行冷热分离,并支持智能化透明转换,以此实现性能与成本的平衡。
热数据采用 In-place Update 的列式存储,保证分析能力的前提下兼顾事务处理能力;
冷数据采用 Append-only 列式存储,进行了极致压缩编码,并通过稀疏索引、条件下推、向量化计算等技术提供了高效的分析性能。冷数据支持对象化存储到远端,并通过本地缓存进行加速,在降低成本的同时也能保证性能。
HTAP 混合负载
混合负载存储的主流实现方式有三种:通过 CDC 或者 Log 实现 TP 节点到 AP 节点的数据转换;同节点内通过多副本实现行列转化同步;或者基于同一份数据通过内存转化同时支撑 TP 和 AP 业务。
YashanDB 采用统一的 SQL 引擎和存储引擎,对外提供原生 HTAP 能力。存储引擎在满足事务一致性的基础上提供多种数据组织结构算法,以满足不同业务场景的需求。当前通过三种方式实现混合负载:
在 TP 友好的 In-place Update 行式存储之上,基于内存行转列以及列式索引实现分析能力。列式索引也是 YashanDB 在混合负载方面的一个重要的技术实践,在行式存储的交易数据上创建实时同步的列式存储索引,发挥加速效果,例如聚合扫描、条件下推、向量化计算。
使用 In-place Update 列存引擎,避免空间膨胀与垃圾扫描,极大地提升存储和检索数据的效率,满足高性能分析场景,同时具备良好的事务处理能力,也可通过建立 Btree 索引满足 TP 场景。
生产的实时数据通过行存满足极致事务能力,并定期将其转化为列式存储用于分析,列式存储包含为实时数据(In-place Update 列存储)和稳态数据(Append-only 列存储)。
上述提到的不同数据结构可以通过透明数据迁移技术实现流转,无需使用者的干预;存储引擎的实现底层基于统一的事务引擎,因此能够支持完整的事务能力以及约束。
03 高可用设计
作为生产系统中极为关键的核心底座,数据库的高可用性 HA(High Availability)是企业非常关注的功能点,它是指数据库系统持续提供服务的能力。
YashanDB 支持主备复制、共享集群、分布式等多种高可用手段。其中主备模式采用物理日志复制模式,备库通过复制和回放主库日志,生成主库的数据副本,从而保证数据库系统的可用性,同时在一主多备情况下引入第三方仲裁者角色,基于 Raft 协议实现自动选举。
YashanDB 对性能进行了深度优化,在保证 RPO=0 的前提下,能实现高负载下的秒级 RTO。
多线程回放:引入协调器的概念,通过分析 Redo 数据,选择最高效的回放方式;回放速率接近生成速率,备库 Redo 不积累,RTO<10s;
会话级协调:完美复制主库 session 执行顺序,保证事务瞬时一致性,解决备库读一致性和回放性能难以兼顾的痛点问题;
读写分离:主库高并发业务下,备库查询延迟依然很低。
YashanDB 支持主备自选举、级联备、共享集群等解决方案级别的容灾,也同样支持多地多中心的部署方式。YashanDB 存储引擎从内核层面通过多种机制来支撑不同的容灾方案,例如支持不同的保护模式(最大保护、最大性能、最大可用)、级联备、自选主以及多写能力。
04 基础设施的优化
自适应 undo 管理
前面提到 YashanDB 事务引擎实现的是 In-place Update 块级 MVCC 机制,这就需要引入独立的 Undo 管理机制。Undo 数据用于还原可见历史数据版本,随时都有可能被使用,因此 Undo 的管理能力一定程度上决定了事务引擎的能力。
Undo 管理经历了从规则式管理到自适应 Undo 管理的演进。规则式管理通过配置决定 Undo 内部的参数,例如 Undo Segment 的数量、每个 Undo Segment 的 Block 数量或者 Undo 数据保留期,这就导致需要定制不同业务压力下的配置,并且无法实时处理业务波动,经常出现 Undo 分配冲突大导致事务性能下降,或者保留期配置不合理频繁出现 Snapshot too old 等问题。
自适应 Undo 管理基于运行时的统计信息,引入 Undo Segment 动态扩展、Segment Block 动态 rebalance、Undo Block 智能分配、Undo Retention 动态调整等机制,有效解决了之前 Undo 管理中存在的痛点问题,能应对不同负载的事务处理要求。
Redo 优化
YashanDB 通过 Write-ahead Log(WAL,预写日志)和异步 Checkpoint 的方式提供持久化的能力。其中 Redo 是用于实现 WAL 机制的基石。事务在提交的时候,必须等待 Redo 落盘来保证事务的持久性,因此 Redo IO 的性能会直接影响事务提交的性能。
因此我们针对 Redo 也进行了深入优化,目标是要保证不同负载下(尤其是高并发事务),数据库整体的事务提交性能以及稳定性。这里举两个例子:
Redo 批量提交:事务提交时主动等待一段时间,积攒更多 Redo,减少 IO 刷盘次数,提高事务吞吐量;
Redo 流量控制: 自动控制 Redo IO 流量,避免高峰期 Redo 消耗过快而追尾,导致的性能抖动。
这里 YashanDB 引入了基于原创大数据理论的启发式算法,用于实时调整批量提交和流量控制机制,以达到最理想的运行状态。
IO 与缓存优化
IO 问题是所有通用存储引擎面临的共同难题,YashanDB 存储引擎对不同场景下的 IO 问题进行了深入优化,优化的思路主要有三个方向: IO 减少,包括 Redo 压缩、Block 级压缩、编码压缩、归档/备份压缩等方式;IO 合并,包括 Redo 合并、同步/异步预读、Dirty Block 合并等;IO 并行,包括 Redo 并行 flush、Dirty Block 并行 flush、并行归档/备份等。
缓存是存储引擎的重要组件,YashanDB 采用的是多级缓存架构,对性能带来很大的提升,自下而上分别是:
Level 2 本地磁盘 cache,减少远程 IO 的概率,尽可能在本地磁盘完成访问;
Level 1 全局内存 cache,降低产生 IO 的概率,可以实现共享集群中多实例的共享;
Level 0 会话级内存 cache,降低全局资源冲突。
05 技术展望
下一步,YashanDB 将在 HTAP、存储引擎自治、多模数据以及多级存储等方面不断强化。具体来说:
真正的 HTAP:持续完善 HTAP 能力,尤其是在行列混合、负载隔离、透明转化等方面。
存储引擎自治:之前介绍的基于运行统计信息的实时机制优化是 YashanDB 在自治方面的一个尝试,未来将在查询优化、参数配置、自动运维等方面融入启发式算法、机器学习等自治能力。
多模数据管理:YashanDB 在空间数据、时序数据以及图数据方面也进行了探索和实践,接下来将重点打造原生多模内核。
多级存储应用场景的延伸:TP 场景随着数据量增长,也面临同样的诉求,后续我们会把多层存储机制进行延伸以支持不同负载场景。
本文是《YashanDB 融合存储引擎》系列文章的总览,后续我们会为大家带来该系列中关键能力的设计思路和适用场景。欢迎关注“YashanDB”公众号,持续关注本系列文章!
版权声明: 本文为 InfoQ 作者【YashanDB】的原创文章。
原文链接:【http://xie.infoq.cn/article/d561f392f97bd90240048903e】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论