首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

存储系统的引擎,从物理到虚拟的空间管理技术

前文我们介绍了很多如何将一个存储资源分享出去的方法。对于存储资源而言,可以是硬盘、RAID甚至是一个文件。简而言之,存储资源其实是可以非常简单的,但是在企业级存储系统中,存储资源却是非常复杂的,为什么?

原因很简单,因为企业级存储系统满足用户各种需求,所以存储系统通常不是简单的将裸设备共享出去,而是需要进行各种资源的整合(或者称为虚拟化)和保护。在本章第2节介绍存储系统软件架构的时候,我们曾经将存储系统数据平面的架构简化为3层,也就是协议层、映射与重定向层和设备层。并且我们了解到映射与重定向层是整个存储系统数据平面的核心,存储系统的主要功能都在这里实现。

映射与重定向层最基础的功能是为协议层提供逻辑卷和文件系统。逻辑卷本身就是一个线性空间,跟硬盘空间相仿。这个线性存储空间与传统硬盘和RAID等提供的线性空间有着明显的差异。传统空间硬盘或者RAID提供的线性空间都是真实的空间,在底层都有一一对应的物理空间。而现在企业级存储系统提供的线性存储空间是虚拟的线性空间,虚拟线性空间的数据块在底层有可能独享物理空间、可能共享物理空间,甚至根本就没有对应的物理空间。

映射与重定向层的核心原理在于将设备层的设备统一管理起来,为上层提供虚拟的逻辑卷。虽然各个厂商的实现细节不同,但大致原理是类似的。对于某一个逻辑卷,其线性空间是由若干个数据块构成的,通常数据块的大小是相等的,我们称这些数据块为虚拟数据块或者逻辑块。映射与重定向层的功能就是将虚拟逻辑卷的虚拟数据块与底层物理设备的数据块建立映射关系。

目前可见的存储系统大都基于上述原理实现,只不过商业存储实现的要更加复杂一些,但是基本原理就是这样。具体实现方面我们可以参考诸如Linux的存储栈、ZFS或者华为的RAID 2.0技术。

基于这种虚拟空间技术有很多好处,比如虚拟逻辑卷的大小不受限于物理空间、虚拟逻辑卷的大小动态可调以及存储空间利用率高等。基于虚拟空间技术,在存储系统中可以非常方便的实现快照、克隆、加密和压缩等更高级的特性。

接下来我们简要介绍一下这种虚拟逻辑卷是如何实现的。无论虚拟逻辑卷实现的多么复杂,在用户层面虚拟逻辑卷提供的就是一个线性空间。所以,映射与重定向层的功能就是将线性的逻辑地址映射到底层复杂的物理设备上。

那么如何管理逻辑空间呢?可以类比Linux文件系统中文件数据的管理来理解。我们知道文件的地址空间对于普通用户来说也是线性的,而其数据在硬盘上则是离散的。在本人拙著《文件系统技术内幕》中详细介绍过多种文件系统数据的管理方法,这里以基于索引的数据管理方式为例介绍一下。我们知道在Linux文件系统中,每一个文件都有一个inode,这个是文件的入口。基于索引的数据管理方式是在inode中保存着一个逻辑地址与物理地址之间的映射关系表。通过这个映射关系表,当访问某个逻辑地址的数据时,文件系统可以重新定位到硬盘的具体地址。

由于文件可能非常大,在inode中不可能存储所有的映射关系。于是在实际产品中普遍采用一种称为间接映射的方式。以Ext2文件系统为例,inode中除了存储逻辑地址直接到存储数据的硬盘物理地址的映射外,还存储着另外一种逻辑地址到间接地址块(Indirect Block)的映射。其中间接地址块存储的不是逻辑卷的数据,而是硬盘的物理地址或者下一级的间接地址块。

通过这种间接块的方式,inode中的一个映射项就可以管理更多的数据。以4KB粒度的文件系统为例,如果采用直接映射的方式,一个映射项可以管理4KB的逻辑空间。而采用一级间接块后,由于每个间接块可以存储512个物理地址(4096/8),这个时候inode的一个映射项就可以管理2MB(512*4KB)的逻辑空间。

虚拟逻辑卷与文件类似,在用户层面呈现的也是一个线性空间。所以,存储系统映射与重定向层的基本功能就是实现逻辑卷中逻辑块到物理硬盘上数据块的映射。对于逻辑卷的实现,目前其实后很多开源实现,比较常见的如前文介绍的Linux中的LVM和Solaris中的ZFS。当然,目前ZFS有一个称为OpenZFS的项目,目前已经可以同时支持Solaris和Linux两种不同类型的操作系统。

以ZFS为例,ZFS的整个架构如下图所示,整个架构分为三层。最上层是展示层,用于展示不同形态的存储资源,如ZPL(ZFS Posix Layer)用于展示兼容POXIS标准的文件系统访问接口,ZVol则展示逻辑卷接口。

底层是SPA层,其全称是Storage Pool Allocator,也就是存储池分配器。其核心功能是将底层的多个物理设备抽象为一个扁平的地址空间,并为上层提供数据块(默认大小为128KB)资源。对应企业级存储中的概念,其实就是构建了一个存储池,上层如文件系统和逻辑卷等所使用的存储资源都是从存储池中分配的。但是SPA的读写与传统块存储的读写有很大的差异,这里我们需要强调一下。对于写操作,DMU将存储数据的内存指针发送给SPA,SPA负责找到具体的设备写入内存中的数据,并返回给DMU一个地址。对于读操作,DMU会提交给SPA一个地址指针,SPA根据这个地址指针来返回数据。

中间层为DMU层,其全称是Data Management Unit,也就是数据管理单元。在DMU中实现了对象的概念,在ZFS中对象可以是文件或者其他ZFS内部需要记录的内容。在DMU中一个对象通过一个名为dnode的数据结构来维护对象中存储的数据,在dnode中最多可以有3个指针来存储对象数据的位置。由于ZFS默认块大小为128KB,所以如果对象的大小大于384KB的情况下就需要其他方法来保存数据了。具体怎么存储呢?具体方法与我们前文介绍的Ext2文件系统管理文件数据的方式类似。

如果通过dnode中的数据指针无法存储足够的数据,此时ZFS会通过一个称为间接块(Indirect Block,简称IB)的数据块来扩展指针的数量。如下图所示,间接块也是从SPA分配的数据块,但是间接块中存储的不是卷的数据,而是指针数据。我们知道ZFS数据块的默认大小是128KB,指针的大小是128字节,因此一个间接块可以存储1024个指针。基于上述数据,如果在dnode指针与用户数据之间只有一个间接块,此时一个dnode中的指针就可以管理128MB的空间。如果像下图这样,在dnode指针与用户数据之间有两个(两级)间接块,那么一个dnode中的指针就可以管理128GB的空间。所以说,通过间接块的方式可以极大的拓展dnode管理数据的能力,换而言之就是提高ZFS逻辑卷的最大容量。

到这里我们有必要介绍一下上文所述的指针。这个指针在源代码中是由结构体blkptr_t定义的,该结构体在硬盘上的布局如下所示。可以看到,这个指针还是非常复杂的,总大小占用128字节,其中与数据地址相关的是前48字节的内容,其中每16个字节表示一个地址。在该数据结构中,数据地址由两部分构成,一个是vdev,另外一个是在该vdev的偏移。这里的vdev就是ZFS存储池中虚拟设备的ID,而offset则是数据在该虚拟设备上的偏移,单位是512字节。

基于上述映射关系,逻辑卷中任意偏移地址的数据都可以通过上述间接块构成的树定位到具体的虚拟设备及在虚拟设备中的偏移。因此,通过这种映射,一个逻辑卷看似连续的数据实际上可能在多个物理设备的不同区域。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OhUtTRxmhJpi4I8oZ-9QbPKA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券