共计 2841 个字符,预计需要花费 8 分钟才能阅读完成。
目录
openGauss 数据库 SQL 引擎
openGauss 数据库执行器技术
openGauss 存储技术
一、openGauss 存储概览
二、openGauss 行存储引擎
三、openGauss 列存储引擎
四、openGauss 内存引擎
Ⅰ. 内存引擎的兼容性设计
Ⅱ. 内存引擎索引
Ⅲ. 内存引擎的并发管制
Ⅳ. 内存引擎的内存管控
Ⅴ. 内存引擎的长久化
openGauss 事务机制
openGauss 数据库安全
openGauss 存储技术
四.openGauss 内存引擎
内存引擎作为在 openGauss 中与传统基于磁盘的行存储、列存储并存的一种高性能存储引擎,基于全内存态数据存储,为 openGauss 提供了高吞吐的实时数据处理剖析能力以及极低的事务处理时延,在不同业务负载场景下能够达到其余引擎事务处理能力的 3~10 倍不等。
内存引擎之所以有较强的事务处理能力,并不单是因为基于内存而非磁盘带来的性能晋升,而更多是因为其全面地利用了内存中能够实现的无锁化的数据及索引构造、高效的数据管控、基于 NUMA 架构的内存管控、优化的数据处理算法以及事务管理机制。
值得一提的是,尽管是全内存态存储,然而并不代表着内存引擎中的解决数据会因为系统故障而失落;相同的,内存引擎有着与 openGauss 原有机制相兼容的并行长久化、checkpoint(检查点)能力,使得内存引擎有着与其余存储引擎雷同的容灾能力以及主备正本带来的高牢靠能力。
内存引擎总的架构如图 37 所示。
图 37 内存引擎总体架构图
能够看到,内存引擎通过原有的 Foreign Data Wrapper(内部数据封装器)扩大能力与 openGauss 的优化执行流程相交互,通过事务机制的回调以及与 openGauss 相兼容的 WAL 机制,保障了与其余存储引擎在这一体系架构内的共存,保障了整体对外的统一体现;同时通过保护外部的内存治理构造、无锁化索引、乐观事务机制来为零碎提供极致的事务吞吐能力。
以下将逐渐开展解说相干关键技术点与设计。
内存引擎的兼容性设计 01
因为数据状态的不同以及底层事务机制的差异,此处如何与一个以段页式为根底的零碎对接是内存引擎存在于 openGauss 中的重点问题之一。
此处 openGauss 原有的 FDW(Foreign Data Wrapper)机制为内存引擎提供了一个很好的对接接口,优化器能够通过 FDW 来获取内存引擎外部的元信息,内存引擎的内存计算解决机制能够间接通过 FDW 的执行器接口算子实现间接调起、并通过雷同的构造将后果以合乎执行器预期的形式(比方 Scan(扫描)操作的 pipelining(流水线))将后果反馈回执行器进行进一步解决后(如排序、Group by(分组))返回给客户端利用。
与此同时内存引擎本身的 Error Handling(错误处理机制),也能够通过与 FDW 的交互,提交给上次零碎,以此同步触发下层逻辑的相应错误处理(如回滚事务、线程退出等)。
内存引擎借助 FDW 的形式靠近无缝的工作在整个零碎架构下,与以磁盘为根底的行列存储引擎实现共存。
在内存引擎中 Create Table(创立表)的实际操作流程如图 38 所示。
图 38 内存引擎操作流程图
能够看到 FDW 充当了一个整体交互 API 的作用。实现中同时扩大了 FDW 的机制,使得其具备更齐备的交互性能,包含:
(1) 反对 DDL 接口;
(2) 残缺的事务生命周期对接;
(3) 反对 checkpoint(检查点);
(4) 反对长久化 WAL;
(5) 反对故障复原(Redo);
(6) 反对 Vacuum(垃圾清理回收)。
借由 FDW 机制,内存引擎能够作为一个与原有 openGauss 代码框架异构的存储引擎存在于整个体系中。
内存引擎索引 02
内存引擎的索引构造以及整体的数据组织都是基于 Masstree 实现的。主体如图 39 所示。
图 39 内存引擎主体构造
在前序文章【如何把握 openGauss 数据库核心技术?秘诀三:拿捏存储技术(2)】中的图 15,很好地出现了内存引擎的组织架构。
图 15 MVCC 判断流程
Primary Index(主键索引)在内存引擎的一个表中是必须存在的因素,因而要求表在组织时尽量存在 primary index;如果不存在,内存引擎也会额定生成 surrogate key(代理键)来用于生成 Primary index。Primary Index 指向各个代表各个行记录的 Sentinel(行指针),由 Sentinel 来对行记录数据进行内存地址的记录以及援用。Secondary Index(二级索引)索引后指向一对键值,键值的 value(值)局部为到对应数据 Sentinel 的指针。
Masstree 作为 Concurrent B+ tree(并行 B + 树),集成了大量 B + 树的优化策略,并在此基础上做了进一步的改进和优化。其大抵实现如图 40 所示。
图 40 Masstree 实现形式
Masstree 实现比于传统的 B -tree,Masstree 实际上是一个相似于诸多 B +- 树以 trie(前缀树)的组织模式重叠的 Radix tree(基数树)模式,以 Key(键)的前缀作为索引,每 k 个字节造成一层 B +- 树结构,在每层中解决 Key(键)中这 k 个字节对应所需的 insert/lookup/update/delete 流程。图 41 为 k = 8 时状况。
图 41 k 等于 8 时的 Masstree
注:图来自于“Cache craftiness for fast multicore key-value storage”, Eddie Kohler et. al.
Masstree 中的读操作应用了类 OCC(Optimistic Concurrency Control,乐观并发管制)的实现,而所有的 update(更新)锁仅为本地锁。在树的构造上,每层的 interior node(外部节点)和 leaf node(叶子节点)都会带有版本,因而能够借助 version validation(版本查看)来防止 fine-grained lock(细粒度锁)的应用。
Masstree 除了 lockless(无锁化)之外,最大的亮点是 cache line(缓存块)的高效利用。Lockless 自身肯定水平防止了 lookup/insert/update 操作相互 invalidate 共享 cache line(生效共享缓存块)的状况。而基于 prefix(前缀)的分层,辅以适合的每层中 B +- 树 fanout(扇出)的设置,能够最大水平的利用 CPU prefetch(预取)的后果(尤其是在树的深度遍历过程中),缩小了与 DRAM 交互带来的额定时延。
Prefetch(预取)在 Masstree 的设计中显得尤为要害,尤其是在 Masstree 从 tree root(树根节点)向 leaf node(叶子节点)遍历、也就是树的降落过程中。此过程中的执行时延大部分因为内存交互的时延组成,因而 prefetch(预取)能够无效地进步 masstree traverse(遍历)操作的执行效率以及 cache line(缓存块)的应用效率(命中)。
未完待续 ……