当前位置: 首页 > news >正文

图数据库 | 11、图数据库架构设计——高性能图存储架构(下)

在上篇内容中,老夫着重讲了高性能图存储系统的特点,咱们继续往下讲重点——高性能存储架构的设计思路!!

2.高性能存储架构设计思路

首先呢,存储架构以及核心数据结构的设计思路通常围绕如下4个维度来进行:

一是:外存与内存使用占比(角色分配及分配比例)​;

·是否利用缓存,如何优化缓存

·是否进行数据或记录的排序,如何排序

·是否允许数据或记录的更改(可变性)​,以及如何更改

(1)内外存占比

100%使用外存的数据库是极为罕见的,甚至可以说和高性能数据库关系不大。同样地,100%使用内存的数据库也非常罕见,即便存在“内存数据库”这一门类,通常作为关系型数据库的一个子类或键值库,数据也会持久化在外存之上,原因不外乎是内存的“易失性”​。

在绝大多数现代数据库的架构设计中,都会利用外存与内存中的数据结构特性来实现某种存储加速。除了缓存设计、排序与否和数据可变性之外,对于图数据库而言,因为其存在特殊的数据空间网络拓扑结构,所以内存用来存放一些关键数据(如元数据、映射数据、临时算法数据、索引、需要实时计算的元数据之属性类数据等)​,外存用来存放不需要实时计算的海量剩余数据。这种内、外存按照一定比例来搭配的方式,通常会实现性能较大幅度的提升。

内外存占比并没有固定的方式。在很多传统的IT架构中,服务器的内存资源都占比较低,并且这种情况在云化的过程中愈演愈烈,不得不说是一种倒退——在数据库的应用场景中,内存的占比不应当低于外存的1/8(12.5%)​,也就是说如果有1TB的外存,至少应该有128GB的内存。而在高性能计算场景中,内外存占比可以达到1/4(25%)以上,如果有2TB的外存持久化层数据,内存至少可以是512GB。在这一点上,很多私有云部署的场景由于无法分配大内存,也无法管理大内存的虚拟机,因此不得不说这种云虚拟化本身是与高性能计算背道而驰的。

需要注意的是,为了磁盘访问而优化的数据库数据结构和代码逻辑,虽然可以直接在固态硬盘上运行,但是存在大量的优化和调整空间,这些细节也是数据库架构设计最为繁杂之处。如果我们再把持久化内存的硬件方案引入,就会让问题更复杂。很显然,一套代码逻辑、一套数据结构要泛化并适配到全部的硬件架构之上,并且都能获得最佳的性能,是不太现实的。在实际的数据库架构设计中,我们总在不断地取舍(平衡)​,包括面向底层硬件而做出相应的适配。我们认为那种忽略底层硬件而一味相信硬件透明的数据库设计方案是不可行的——尽管作为数据库下层的文件系统与操作系统已经做了很多抽象、适配的工作,然而高性能数据库依然需要面向具体的硬件环境进行精准的数据结构、架构及性能调优。

(2)缓存

存的目的本质上是为了降低I/O数量,提高系统吞吐率。几乎所有的落盘数据结构都会利用缓存来加速(帮助更快速地定位、读取或回写)​。另外,缓存的设计与数据可变性以及排序与否经常需要通盘考虑,因为是否允许数据被更改,以及数据是否需要排序后存储直接影响了缓存的设计逻辑与实现,反之亦然。

图数据库的存储引擎对于缓存的利用似乎较其他类型的数据库更多,这里不妨罗列一下可能用到缓存的情况:数据写入、数据读出、元数据索引、全文搜索索引、近邻数据、中间操作结果,以及高并发、多版本维护场景等。

需要注意的是,无论是机械硬盘还是固态硬盘,读取与写入的最小单位是块(block)​。机械硬盘通常在硬件层面用扇区(sector)表示,如下图所示,但是在操作系统层面,和固态硬盘一样统一用块表示,一个块通常可设定为固定大小,例如4KB,可能包含多个扇区。在Linux操作系统中,下面两个命令可以方便地判断block与sector的大小:

fdisk - 1 | grep "Sector size"
blockdev - getbsz/dev/sda
图3: 机械硬盘的存储部件示意图

在机械硬盘上,活动部件的寻址与磁盘转动时间占到了每次操作的90%以上,而在固态硬盘(及持久化内存、动态内存)中,由于不存在这个物理部件移动而消耗时间的环节,也因此指数级地缩短了每次操作的时耗(如图4所示)​,时间消耗从每次数毫秒降低到了几十到几百微秒(约40倍以上的性能提升)​。 

图4:机械硬盘与固态硬盘访问时延分解对比示意图


在固态硬盘中,最小颗粒度的存储单位是Cell,其次是String、Array、Page、Block、Plane、Die、Solid State Drive(SSD)​,最后的SSD就是我们熟知的固态硬盘(图5)​。而可编程(写)​、可读取的最小单位是Page(页)​,最小可擦除(erase)的存储单位是Block(块)​,每个Block通常由64~512个Pages构成。 

图5:固态硬盘的存储单元间的层层嵌套关系示意图


无论是机械硬盘还是固态硬盘,读写的单位不是操作系统、文件系统与数据库存储逻辑层面所需要存储的最细颗粒度的数据记录——比特,甚至都不是字节或者多个字节所构成的字符、整数、浮点数或字符串。在硬件层面这么设计是为了提高存储效率。举个例子,一个人从家里到公司的距离是20km,打车需要1小时,他需要从家里带10本书到公司,可以一次性运送10本书去公司,也可以多次运送,从运输成本、时间成本上综合考量,显然是一次性运送最划算。同样地,在面对存储媒介的时候,缓存设计就是这种“一次性”批量运送(存取)技术手段。类似地,在分布式架构设计中,如果每个操作都涉及网络请求与传输过程,合理地合并多个操作后再统一传输不失为一种优化方案。 

下图示意的是缓存与物理I/O之间的“反比”关系,理论上缓存越多,I/O越低,但实际上,缓存量到达C点后,对于I/O降低(性能提升)的效果就不明显了。这个C点就是我们在设计存储缓存时的一个“高规格”目标,而B或A则是低成本投入时的“中低规格”目标。

图6:缓存与I/O之间的“反比”关系

总之,缓存是一个贯穿整个计算机硬件和软件发展历程的核心技术。即便是在最极端的情况下,比如在数据库或应用软件设计中没有主动使用任何缓存技术,底层的文件系统、操作系统、像硬盘、CPU等硬件依然会通过缓存来实现存取与计算加速。缓存的出现让系统架构设计变得更为复杂,因为系统有更多的组件需要管理,例如保持更新、提升命中率、清空重置等。

(3)排序(与否)

数据排序是一个随着数据记录数量增长而越来越常见的存储优化技术。是否排序取决于具体的业务场景。如果是对插入数据进行排序,那么在连续存储类型的数据结构中,可以直接使用地址下标来以最低延迟访问一条记录,或者快速读取一段地址空间内存放的数据记录。再结合缓存的加速策略,连续存放的数据记录可以更充分、有效地利用缓存技术,但如果中间需要插入或删除一条记录,操作成本会比较昂贵。 

在之前的内容中,老夫就介绍过“近邻无索引”存储数据结构,可以以O(1)的时间复杂度来从任意一个顶点去定位它的近邻(即一度以内的邻居)顶点。这种数据结构设计本身的存取效率已经高于索引。在不考虑并发锁等复杂的情况下,增量写入、读取、更新效率都可以做到O(1),但是删除的复杂度会更大。因为像数组这类连续存储的数据结构,从中间位置删除记录会导致整个后序数据记录移位。这个时候,如果数据记录可以不按照Key或ID排序,则可以考虑在定位要被删除的数据记录后,与末尾的记录置换,完成置换后再删除尾部记录。这个操作称为接入-删除(swtich-on-delete)操作,其复杂度依然可以等同于O(1)(实际复杂度是最低延迟的O(1)的7~10倍)​,操作示意图如图7所示。

图7:接入— 删除操作

非连续存放的特点是可以把数据结构设计为删除单个记录,效率可能较高,如O(log N)(通常这一数值不大于5)​,但是连续读取的多条记录的范围查询成本则很高,例如,读取K条记录的时耗为KO(log N)。

范围查询在很多应用场景中被大量使用,但它似乎与非排序存储方式相冲突。在之前的内容中我们介绍过LSMT,这里介绍一种基于LSMT优化的WiscKey(Wisc是University ofWisconsin-Madison的缩写,Key指的是一种Key-Value Store的存储优化方案)​,数据结构可以兼顾写的效率与非排序存储的空间利用优势。

首先针对磁盘而言,LSMT的特点如下:
·批量、顺序写入;
·顺序访问高通量(顺序访问的效率是随机访问的数以百倍计)​;
·读写放大效应(并没有面向SSD优化,记录读写都会被放大很多倍)​。
其次,固态硬盘的特点如下:
·随机读性能高;
·并行操作能力。
WiskKey的设计核心理念是键值分离(仅键需要排序)​,它包含如下几个面向固态硬盘的优化策略(图8、图9):

图8: LSMT与WiscKey

图9:WiscKey中LSMT与vLog分离

 ·拆分排序与GC(垃圾回收)​;

·利用固态硬盘在范围查询时并发的能力;

·在线、轻量级GC;·最小化I/O放大;

·崩溃一致性。

经过WiskKey优化的固态硬盘上的顺序、随机访问性能如下图所示。可以看到,当访问的数据大小在64K~256KB范围内的时候,32线程并发访问的吞吐率已经和串行访问不相上下了。

图10: ”WiscKey串行、单线程随机、32线程随机范围查询性能比较

WiscKey是基于LevelDB的核心代码优化的,经过优化后,WiscKey在随机访问和顺序访问上都有一定程度的性能提升,特别是在键所对应值的占用空间大于4KB之后(下图11)​。

当然,有多少实际业务中的键值需要4KB以上的存储空间,是个需要具体探讨的问题。以老夫的经验,实际键值普遍在1KB以内。这个时候,WiscKey与常规的LSMT的性能相差无几。

图11:基于对LevelDB代码优化的WiscKey与LevelDB查询性能比较


(4)数据可变(与否)

数据是否可变(mutability)指的是数据记录的更新采用追加模式(append-only)还是允许本地更改。不同的模式适用于不同的场景,也因此而衍化出了不同的“加速”模式。

例如最早在Linux内核设计中实现的Copy-on-Write模式(COW)​,即不更改原数据,采用先拷贝再更改的方式。LSMT与B-Tree之间的区别也通常被归纳为不可变与就地更改两种缓存加速模式的区别。

COW所采用的一个技巧被称为无锁式记录更新,如图3-12所示。具体操作步骤如下:

图12:无锁式更新变量(记录)


1)定位变量(记录)A(内容为X)​;
2)拷贝A至A′(非深度拷贝,指针级拷贝)​,创建内容为Y;
3)在一个原子级操作(compare-and-swap)中,A指向Y,切断A′与该变量关联关系,之前的X记录被GC(垃圾回收)​。

把上面的操作放在一颗二叉树中,也是一样的逻辑,COW的核心在于尽可能地避免深度拷贝(deep-copy)​,使用指针来通过轻量级的操作实现浅层拷贝(copy-by-reference)​,并只在必要的时候再进行深度拷贝以及精准的记录更新操作。

在Linux操作系统的内核中,当父进程需要衍生子进程时就使用了这种COW的技术,节省了内存与CPU时钟的消耗。 

B-Tree类型的数据结构虽然实现了就地更新记录(in-place update)的功能,但是带来了写放大(write-amplification)的问题,以及处理锁和并发时的设计复杂度较高。Bw-Tree由此应运而生,它的全称是Buzzword-Tree,是一种内存级、可变页大小、高并发、无锁数据结构。

 Bw-Tree有4个核心设计(图13)​:

·基点(base nodes)和变化链(delta chains)​。

·映射关系表。

·合并与垃圾回收。

·结构化更改(SMO)​:为了实现无锁化。

确切地说,这4个设计都是为了实现无锁式高并发,当然,代价就是使用了更多的内存空间。其示范意义在于,高性能系统的设计思路无外乎以下几点:
1)使用和适配更快的存储设备(包括内存、包括分级存储)​;
2)尽可能实现更高的并发(配合数据结构支持)​;

图13:Bw-Tree的内部逻辑关系

3)避免使用过多的、颗粒度太粗的锁;
4)避免频繁地拷贝数据等操作(数据利用率太低)​;
5)贴近底层硬件,避免过多的虚拟化和过多的中间环节。

老夫在上一篇文章中就说过高性能存储架构设计思路要聊的东西非常多、非常细。今儿还没聊完,下一篇咱们接着叙——高性能图计算架构!

今天先这样,已经洋洋洒洒快五千字了,大家先吸收一下,明天或后天继续码字。

 

· END ·

(文/Ricky - HPC高性能计算与存储专家、大数据专家、数据库专家及学者)

相关文章:

图数据库 | 11、图数据库架构设计——高性能图存储架构(下)

在上篇内容中,老夫着重讲了高性能图存储系统的特点,咱们继续往下讲重点——高性能存储架构的设计思路!! 2.高性能存储架构设计思路 首先呢,存储架构以及核心数据结构的设计思路通常围绕如下4个维度来进行&#xff1a…...

【HTTP】HTTP协议

一个Web Server就是个服务器软件(程序),或者是运行这个服务器软件的硬件(计算机),其主要功能是通过HTTP协议与客户端进行通信,来接收,存储,处理来自客户端的HTTP请求&…...

大数据新视界 -- Hive 基于 MapReduce 的执行原理(上)(23 / 30)

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

SpringBoot源码解析(六):打印Banner

SpringBoot源码系列文章 SpringBoot源码解析(一):SpringApplication构造方法 SpringBoot源码解析(二):引导上下文DefaultBootstrapContext SpringBoot源码解析(三):启动开始阶段 SpringBoot源码解析(四):解析应用参数args Sp…...

【计算机网络】实验6:IPV4地址的构造超网及IP数据报

实验 6:IPV4地址的构造超网及IP数据报 一、 实验目的 加深对IPV4地址的构造超网(无分类编制)的了解。 加深对IP数据包的发送和转发流程的了解。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、了解IPV4地址的构造超网…...

easy excel 生成excel 文件

导包 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version> </dependency> 内容 List<类> limspjreport 值; String fileName sdf.format(new Date()) "-…...

Ajax:回忆与节点

一点回忆 面对我的Ajax学习&#xff0c;实现前后端交互&#xff0c;最开始我采用的使用网络寻找intellij IDEA Ultimate破解方法&#xff0c;然后最终成功&#xff0c;然后按照相关教程配置java ee项目&#xff0c;然后中间又去配置了Tomcat服务器&#xff0c;然后又去学习了一…...

Python+OpenCV系列:Python和OpenCV的结合和发展

PythonOpenCV系列&#xff1a;Python和OpenCV的结合和发展 **引言****Python语言的发展****1.1 Python的诞生与发展****1.2 Python的核心特性与优势****1.3 Python的应用领域** **OpenCV的发展****2.1 OpenCV的起源与发展****2.2 OpenCV的功能特性****2.3 OpenCV的应用场景** *…...

Ubuntu20.04 由源码编译安装opencv3.2 OpenCV

Ubuntu20.04 由源码编译安装opencv3.2.0 获取 opencv 及opencv_contrib源代码 创建目录以存放opencv及opencv_contrib源代码 mkdir ~/opencv3.2.0 cd ~/opencv3.2.0获取opencv源代码并切换到对应tag git clone https://github.com/opencv/opencv.git cd opencv git checkou…...

A058-基于Spring Boot的餐饮管理系统的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看项目链接获取⬇️&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600个选题ex…...

RDIFramework.NET CS敏捷开发框架 SOA服务三种访问(直连、WCF、WebAPI)方式

1、介绍 在软件开发领域&#xff0c;尤其是企业级应用开发中&#xff0c;灵活性、开放性、可扩展性往往是项目成功的关键因素。对于C/S项目&#xff0c;如何高效地与后端数据库进行交互&#xff0c;以及如何提供多样化的服务访问方式&#xff0c;是开发者需要深入考虑的问题。…...

Linux——命名管道及日志

linux——进程间通信及管道的应用场景-CSDN博客 文章目录 目录 文章目录 前言 一、命名管道是什么&#xff1f; 理解&#xff1a; 2、编写代码 makefile 管道封装成类&#xff0c;想用中管道时只需要调用实例化 读端 写端 日志 1、日志是什么&#xff1f; 2、日志有什么&#x…...

Flink 常见面试题

1、Flink 的四大特征&#xff08;基石&#xff09; checkpoin基于Chandy-Lamport算法实现了分布式一致性快照提供了一致性的语义 state丰富的StateAPI time实现了Watermark机制&#xff0c;乱序数据处理&#xff0c;迟到数据容忍 window开箱即用的滚动&#xff0c;滑动会话窗口…...

rtc-pcf8563 0-0051: low voltage detected, date/time is not reliable

解决方法&#xff1a; 1、先测量pcf8563电源电压&#xff0c;是否满足要求。 2、pcf8563首次操作。第一次读取pcf8563的时间&#xff0c;未初始化&#xff0c;非法&#xff0c;芯片门槛电压检测配置不合理。使用hwclock命令写入一次&#xff0c;即可解决。 hwclock -f /dev/…...

(简单5步实现)部署本地AI大语言模型聊天系统:Chatbox AI + grok2.0大模型

摘要&#xff1a; 本文将指导您如何部署一个本地AI大语言模型聊天系统&#xff0c;使用Chatbox AI客户端应用和grok-beta大模型&#xff0c;以实现高效、智能的聊天体验。 引言&#xff1a; 由马斯克X-AI发布的Grok 2大模型以其卓越的性能超越了GPT4.0。Grok模型支持超长文本…...

MAUI APP开发蓝牙协议的经验分享:与跳绳设备对接

在开发MAUI应用程序时&#xff0c;蓝牙协议的应用是一个重要的环节&#xff0c;尤其是在需要与外部设备如智能跳绳进行数据交换的场景中。以下是我在开发过程中的一些经验和心得&#xff0c;希望能为你的项目提供帮助。 1. 蓝牙协议基础 蓝牙协议是无线通信的一种标准&#x…...

最新版Node.js下载安装及环境配置教程

目录 初识&#xff1a;Node.js 一、下载&#xff1a;Node.js 二、安装&#xff1a;Node.js 1.下载【node.js】压缩包安装文件 2.解压下载的安装包 3.打开解压的【node-v22.11.0-x64】文件夹 4.双击启动安装程序 5.点击【Next】 6.勾选【I accept the terms in the Lic…...

51c自动驾驶~合集39

我自己的原文哦~ https://blog.51cto.com/whaosoft/12707676 #DiffusionDrive 大幅超越所有SOTA&#xff01;地平线DiffusionDrive&#xff1a;生成式方案或将重塑端到端格局&#xff1f; 近年来&#xff0c;由于感知模型的性能持续进步&#xff0c;端到端自动驾驶受到了来…...

单链表基础操作

文章目录 abstract定义结点结构初始化链表遍历链表求表长查找结点根据序号查找结点根据值查找结点 插入结点首尾位置插入一般位置插入(通用插入)找到尾元素|尾指针相关操作 删除结点 abstract 单链表是一种简单的动态数据结构&#xff0c;它由一系列结点组成&#xff0c;每个结…...

Asp.net MVC在VSCore中的页面的增删改查(以Blog项目为例),用命令代码

在VSCore中的页面的增删改查(以Blog项目为例) 1.创建项目&#xff08;无解决方案&#xff09;复杂项目才需要 dotnet new mvc -o Blog2.控制器 BlogsController.cs 控制器&#xff08;Controller&#xff09;名字和视图&#xff08;View&#xff09;中的文件名要一模一样 u…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

JavaScript 标签加载

目录 JavaScript 标签加载script 标签的 async 和 defer 属性&#xff0c;分别代表什么&#xff0c;有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...