存储介质管理
Unix/Linux存储就像乐高积木一样,由不同的存储设备组成。传统硬盘仍旧是本地存储的主要介质,但是为了提高应用性能,越来越多的固态硬盘也被加入到系统中。运行在硬件上的许多软件组件作为协调原始存储设备和文件系统结构的中介。这些组件包括设备驱动、分区规范、RAID实现、逻辑卷管理工具、网络上的虚拟硬盘系统和文件系统实现。
存储硬件
即使在今天的后因特网时代,也就仅有几种方式存储计算机数据:硬盘、闪存、磁带和光盘。后两种技术有很大的限制,一般不使用它们作为系统的主要文件系统。但是,它们经常用来备份和近线存储,此时即时访问和可重写性都不是考虑的重点。在硬盘技术发展了40年后,系统构建者们终于找到了实用的替代者——固态硬盘(SSD)。这种基于闪存的设备使用一组与标准硬盘的不同权衡,未来注定会对数据库、文件系统和操作系统的架构产生强烈影响。硬盘和固态硬盘可以互相替换,至少在硬件水平上。它们使用相同的硬件接口和接口协议。不过,它们在性能和价格上有着很多不同。
硬盘(hard disk drive):典型的硬盘包含几张覆盖礠膜的旋转碟片。这些碟片通过在金属臂上前后移动的小磁头来读写。这些磁头浮在碟片的表面上,但并不接触。从碟片上读是很快的,但是通过机械运动定位到某个扇区减慢了随机访问的吞吐量。主要用两中延迟:首先,磁头移动到相应的磁道上。这个部分叫寻道延迟。然后,碟片将所需要的扇区旋转到磁头下方。这部分叫旋转延迟。碟片上与旋转轴距离相同的所有磁道叫做柱面。
固态硬盘(solid state disk):固态硬盘是在一组闪存单元(flash memory cells)上读写,与现在硬盘比较单个读写是相当慢的。但是因为并行,固态硬盘整体上达到或者超过了传统硬盘的带宽。固态硬盘的巨大优点就是不断的进行随机读写,性能依旧表现很好。然而这种性能需要付出代价,固态硬盘不仅单位比特价格比硬盘贵,而且也向存储体制(storage equation)中引入了新的问题和不确定性。固态硬盘中闪存的每个页(page,目前产品上一般都是4KiB)只可以重写有限次(通常是100000次,依赖于底层技术)。为了防止某页损耗,固态硬盘的固件(firmware)维护着一个映射表,将写操作分布到不同的物理页上。这个映射操作对操作系统是不可见的,操作系统只将固态硬盘看成线性的块(block)序列。近一步的困难则是:闪存页在被重写之前必须要清除,并且清除操作比写操作还慢。此外,清除单独一页也不可能;相邻的页形成的簇(cluster,一般128页或者512KiB)必须同时清除。当清除过的页都用尽的时候,驱动器必须匆忙清除一些页来满足写的要求,此时固态硬盘的写性能急速下降。重建清除过的页的缓冲并没有看起来那么简单,因为文件系统通常不会标记和清除它们不在使用的数据块。存储设备并不知道文件系统要释放一个数据块,它只知道一段时间前有人给它数据存在那儿。为了SSD维护它的清除的页的缓存和写操作性能,文件系统应该通知SSD哪些页它不再使用。当前仅有ext4和win7的NTFS这两种常用文件系统提供这种功能。随着越来越多的人对SSD感兴趣,相信不久之后其他文件系统也会更加重视SSD。
存储硬件接口
现在通常只有几种接口在使用。如果系统支持几个不同的接口,选择那个最满足你需要(如速度、冗余度、可移动性和价钱)的接口。
ATA (Advanced Technology Attachment):早期版本叫做IDE,是给个人电脑开发的简单低廉的接口。早期叫Integrated Drive Electronics是因为它将硬件控制器与硬盘碟片放在了同一个盒子里并使用相对高级的协议在计算机和硬盘间通信。现在所有的硬盘都这样工作的,但是在那个时候算是一种创新。传统的并行ATA接口(PATA)用40或者80针脚的排线将硬盘连接到主板上。PATA硬盘经常标记成IDE以区别SATA驱动器,但事实上却是ATA驱动器。
SATA (serial ATA):这是一种完全不同于并行ATA的新型硬盘接口类型,由于采用串行方式传输数据而得名。除了支持比PATA更高的传输速率外,还原生支持命令队列和热插拔。
SCSI (Small Computer System Interface):虽然没有曾经那么普遍了,SCSI依旧是一种广泛被支持的硬盘接口。
光纤通道(Fibre Channel):在企业环境中非常流行的串行接口。高带宽,可以一次连接很多存储设备。
USB (Universal Serial Bus) 和 FireWire (IEEE 1394):很流行的连接外置硬盘的串行通信接口。
存储的软件组件
存储设备:可以是硬盘,闪存驱动器,固态硬盘,硬件实现的外部RAID阵列,甚至可以是提供块级别(block-level)远程访问的网络服务。
分区:是存储设备上一个固定大小的部分。每一个分区都有自己的设备文件,就像独立的存储设备一样。
RAID阵列:将多个存储设备虚拟成一个设备。
卷组和逻辑卷:和逻辑卷管理器有关。它们将所有的物理设备整合到一起形成叫做卷组的存储池。管理者可以将该存储池分成逻辑卷,就像将硬盘分区一样。
文件系统:协调由分区,RAID阵列或者逻辑卷呈现的原始块 与 程序所使用的标准的文件系统接口 间的工作。文件系统决定着文件内容存放在哪如何存放、文件系统名字空间如何在硬盘上表示和查找以及系统如何应对崩溃。多数存储空间都是文件系统的一部分,但是swap空间和数据库空间可以在不需要文件系统帮助的情况下运行的更有效些。内核和数据库使用它们自己的结构来管理存储。
硬盘分区
分区和逻辑卷管理都是将一个硬盘分成几个确定大小的部分的方法。可以将单个的分区放到逻辑卷管理器中使用,但不可以分割逻辑卷。分区是最低层次的硬盘管理。
传统分区
允许分区的系统在硬盘的起始部分写一个“标签”规定者每个分区的块的范围。具体的实现各部相同,这个标签通常都和其他的启动信息(例如一个启动块)共存,它通常包含着其他信息(例如名字、标示整个硬盘的唯一ID号等)。在Windows系统中,这个标签是MRB(master boot record)。
负责表示磁盘的设备驱动器读取标签并利用分区表计算出每个分区的物理位置。通常,一个或两个设备文件(device file)表示每个分区(一个块设备,一个字符设备;Linux仅使用块设备)。一组设备文件的集合代表着整个硬盘。裸设备(raw device,原始设备)是块设备文件的一种特殊情况,可以绕开操作系统的cache和buffer,允许直接访问存储设备如硬盘等(虽然此时仍旧使用硬件cache)。数据库管理系统就直接使用原始设备。
windows风格的分区
Windows MRB使用一个512字节的硬盘块,启动代码使用掉其中大部分字节。剩下的空间只运行定义4个主分区,称为主分区是因为在MBR中直接定义的。可以将其中一个主分区定义为扩展分区,这意味着它拥有一个子分区表。字分区表存储在扩展分区数据的起始位置。那些在扩展分区中创建的分区称谓逻辑分区。
每一个分区都有一个字节的类型属性标识着分区的内容,通常这个类型码代表着文件系统类型或者操作系统类型。Windows分区系统允许一个分区标记成“活跃的”(active)。启动器查找活跃的分区并尝试从该分区加载操作系统。
GPT:GUID partition tables
Intel's 可扩展固件接口(EFI, extensible firmware interface)项目提供全新类型的 PC 固件的体系结构,旨在取代传统的BIOS。虽然完全使用EFI固件的系统还不常见,EFI的分区模式却在操作系统中取得了广泛支持。主要原因是MBR不支持容量大于2T的硬盘。
EFI的分区模式——“GUID partition table”或GPT——去除了MBR的明显错误。它只定义了一种分区类型,但是你可以创建任意数量的分区。每个分区都拥有一个16个字节的ID码(the globally unique ID,GUID)来表示分区类型,不需要中央仲裁。在GPT分区表的最开头(磁盘的第一个块),处于兼容性考虑仍然存储了一份传统的MBR(protective MBR),用来防止不支持GPT的硬盘管理工具错误识别并破坏硬盘中的数据,这个MBR也叫做保护MBR。这使得硬盘看起来像被一个大的MBR分区使用着(至少,直至MBR的2T限制)。在支持从GPT启动的操作系统中,这里也用于存储第一阶段的启动代码。在这个MBR中,只有一个标识为0xEE的分区,以此来表示这块硬盘使用GPT分区表。不能识别GPT硬盘的操作系统通常会识别出一个未知类型的分区,并且拒绝对硬盘进行操作,除非用户特别要求删除这个分区。这就避免了意外删除分区的危险。另外,能够识别GPT分区表的操作系统会检查保护MBR中的分区表,如果分区类型不是0xEE或者MBR分区表中有多个项,也会拒绝对硬盘进行操作。
windows从vista之后才开始支撑GPT,但是只有支持EFI固件的系统才能从它启动。Linux和它的GRUB启动加载器就好得多:Linux操作系统就支持GPT并可以从任何系统上启动(不一定需要EFI固件)。虽然操作系统内核已经很好地支持GPT了,但是支持GPT的磁盘管理工具却很少。GPT依旧是“前沿”格式,没有什么可以令人信服的理由将它必须应用到容量小于2T的硬盘上。
linux的主要分区命令是fdisk和gparted。
RAID:Redundancy Arrays of Inexpensive Disks
RAID主要做两件基本事情:1.将数据切割成许多区段,分别存放在各个硬盘上,这样允许多个硬盘同时工作服务统一数据流,提高性能。这个过程称作数据条带化。条带(strip)是把连续的数据分割成相同大小的数据块,把每段数据分别写入到阵列中的不同磁盘上的方法。简单的说,条带是一种将多个磁盘驱动器合并为一个卷的方法。 许多情况下,这是通过硬件控制器来完成的。条带化后,条带卷所能提供的速度比单个盘所能提供的速度要快很多,由于现在存储技术成熟,大多数系统都采用条带化来实现系统的I/O负载 分担,如果OS有LVM软件或者硬件条带设备,决定因素是条带深度(stripe depth)和条带宽度(stripe width)。条带深度:指的是条带的大小,也叫条带大小。条带宽度:是指同时可以并发读或写的条带数量。这个数量等于RAID中的物理硬盘数量。2.可以在多个硬盘上再现(replicate)数据,降低了单个硬盘坏掉丢失数据的风险。
再现(replication)主要包括两种形式:1.镜像策略:在几个不同的驱动器上按位去复制数据块。2.校验码策略:在一个或者多个驱动器上保存可以修正其他数据驱动器上数据块错误的校验和。镜像策略更快但是需要更多的磁盘空间。校验码策略则相反,更剩空间但是速度比较慢。
传统上RAID使用“级别”来表示磁盘阵列实现的并行性和冗余性的细节。“级别”这个词容易使人误解,因为“越高”的级别并不一定代表着“越好”。不同的级别简单地代表着不同的配置,请选择那个能满足需求的版本。
在下面的描述中,数字用来表示不同的区段,字母a、b和c代表着区段内的数据。标记p和q的块代表着校验块。
- 线性模式(linear mode):也称作JBOD(Just a Bunch Of Disks),并不是真的RAID级别。但是,每个RAID控制器都实现了它。JBOD将多个硬盘驱动器中的块地址依次连接起来形成一个大的虚拟驱动器。它没有数据冗余也没有性能优势。现在,可以通过逻辑卷管理器而不是RAID控制器来提供最好的JBOD功能性。
- RAID 0:只能用来提高性能,本质上讲并不能算RAID级别,因为它没有提供数据冗余。它将两个或者多个容量相同的驱动器组合在一起,不是通过驱动器栈连在一起,而是将数据条带化到驱动器池中的不同磁盘上。顺序读写就分布到几个磁盘上,减少了读写的时间。注意RAID 0的可靠性明显地低于单个磁盘。两个磁盘的阵列的年故障率几乎是单个磁盘的二倍。
- RAID 1:直白地讲就是镜像,即,将相同的数据同时写入两块或者多块磁盘。这种安排使得写操作略微慢于在单个磁盘上的写操作。然而,它的读操作速度却可以和RAID 0相媲美,因为读可以分摊到几个内同复制的磁盘驱动器上。RAID 1是磁盘阵列中费用最高的, 但提供了最高的数据可用率。当一个磁盘失效, 系统可以自动地交换到镜像磁盘上, 而不需要重组失效的数据。
- RAID 2:将数据条带化分布于不同的硬盘上,条带单位为比特或字节。RAID 2使用称为“加重平均纠错码(又称为海明码)”的编码技术来提供错误检查及恢复,这种编码技术需要多个磁盘存放检查及恢复信息,使得RAID 2技术实施非常复杂,并且冗余信息的开销很大。因此,在商业环境中很少使用,基本上已被淘汰。
- RAID 3:同RAID 2类似,也是将数据条带化分布于不同的硬盘上,条带单位为比特或字节。但与RAID 2不同的是,RAID 3使用单块磁盘存放校验信息。如果一块磁盘失效,校验盘与其他数据盘可以重新产生数据;如果校验盘失效,则不影响数据使用。RAID 3对于大量的连续数据可提供很好的传输率,但对于随机数据,校验盘会成为写操作的瓶颈。
- RAID 4:同RAID 3一样,RAID 4也同样将数据条带化并分布于不同的磁盘上,但条带单位为块或记录。RAID 4使用一块磁盘作为校验盘,每次写操作都需要访问校验盘,成为写操作的瓶颈,在商业中很少使用。
- RAID 5:同RAID 4相同,也是将数据条带化并分布于不同的磁盘上,条带单位为块或记录。但不同的时,RAID 5没有单独指定的校验盘,而是将数据及奇偶校验信息交叉地存取于所有磁盘上。在RAID5 上,读/写指针可同时对阵列设备进行操作,提供了更高的数据流量。RAID 5更适合于小数据块、随机读写的数据。与RAID 3相比,重要的区别在于RAID 3每进行一次数据传输,需涉及到所有的阵列盘;对于RAID 5来说,大部分数据传输只对一块磁盘操作,可进行并行操作。在RAID 5中有“写损失”,即每一次写操作,将产生四个实际的读/写操作,其中两次读旧的数据及奇偶信息,两次写新的数据及奇偶信息。
- RAID 6:在RAID 5的基础上增加了第二个独立的奇偶校验信息块。两个独立的奇偶系统使用不同的算法,使得数据的可靠性非常高。即使两块磁盘同时失效,也不会影响数据的使用。但需要分配给奇偶校验信息更大的磁盘空间,相对于RAID 5会有更大的“写损失”,RAID 6的写性能非常差。随着SATA磁盘的使用率日益提高,Raid6也正在被越来越多的人所使用。SATA盘相对于SCSI盘来讲更加廉价,但是可靠性不及后者,所以对SATA盘使用Raid6是最合适不过了。
RAID基本2,3,4虽然定义了但是很少部署使用。逻辑卷管理器通常包括条带化(RAID 0)和镜像化(RAID 1)的特征。
linux软RAID命令:mdadm
Linux标准的软件RAID的实现是md(multiple disks)。mdadm是它的前端命令。md支持几乎所有的RAI配置(RAID 0,1,4,5,6,1+0,0+1等)。以前的工具raidtools已经不再使用了。
逻辑卷管理器
逻辑卷管理器实质上是硬盘分区的增强和升级版本。它将独立的存储设备组成“卷组”(volume groups)。卷组中的块(block)被分配到使用块设备文件表示的“逻辑卷”(logical volumes)上。逻辑卷像硬盘分区,不过,却比硬盘分区灵活和强大的多。下面是一些卷管理器允许你执行的神奇操作:
- 在不同物理设备间移动逻辑卷
- 动态调整逻辑卷的大小
- 快照功能允许用户对逻辑卷进行实时的备份
- 在不中断服务的情况下替换联机的设备
- 将镜像化或条带化集成到逻辑卷
逻辑卷允许按照多种方式将它的各部分放在一起。串联方式就是将各个设备的物理块放在一起,依次相连。条带化方式将多个部分交织在一起,使得相邻的虚拟块分配到多个物理盘上。通过降低单个磁盘的瓶颈,条带化可以提供更高的带宽和更低的延迟。
Linux的逻辑卷管理器叫做LVM2。除了操作卷组和逻辑卷的命令外,下表还提供了一些与“物理卷”(physical volumes)相关的命令。一个物理卷就是一个带有应用的LVM标签的存储设备;应用这个标签是通过LVM使用设备的第一步。Linux使用 pvcreate来应用标签。除了记录信息外,标签还包括一个唯一的ID来标示设备。“物理卷”是个有些让人误解的词汇,因为物理卷并不需要和物理设备直接对应。它们可以是硬盘,也可以是硬盘分区和RAID阵列。
Operation | Linux commands | |
physical volume |
create | pvcreate |
inspect | pvdisplay | |
modify | pvchange | |
check | pvck | |
volume group |
create | vgcreate |
modify | vgchange | |
extend | vgextend | |
inspect | vgdisplay | |
check | vgck | |
enable | vgscan | |
logical volume |
create | lvcreate |
modify | lvchange | |
resize | lvresize | |
inspect | lvdisplay |
你可以使用一大组简单的命令(上面表格描述的)或者使用单个lvm命令和它的子命令来控制Linux的LVM实现(LVM2)。这些选项对于所有目的和意图都是相同的;因为那些单个的命令看起来像怎么调用就知道怎么操作,实际上都只是lvm命令的软连接而已。man lvm是对逻辑卷管理器及其工具的很棒介绍。
一个Linux的LVM的配置需要按照以下几个不同步骤进行:
- 创建(实际上是定义)和初始化物理卷
- 将物理卷添加到卷组中
- 在卷组上创建逻辑卷
LVM命令的开始的几个字母表示着他们操作在那个抽象层次上:pv开始的命令操作物理卷(physical volumes),vg开始的命令操作卷组(volume groups),lv开始的命令操作逻辑卷(logical volumes)。少数以lvm开头的命令则从整体上操作逻辑卷管理器。