RAID与其在Linux上的实现

参考资料:

RAID

data striping

spanned volume

从raid0到raid7,raid阵列各级别介绍

本文所使用的图片来源于互联网,若有侵权,烦请联系,谢谢。

简介

RAID出现的目的是为了数据的冗余,或者性能的提升,或者两者兼顾。早期想实现这样的功能,可能需要购买一些基于大型机(mainframe)的设备,但是价格过于昂贵,后来就有些人发明了RAID技术将多块廉价的磁盘组合在了一起,实现了和大型机设备同等的功能。

RAID,早期的全称是冗余廉价磁盘阵列(Redundant Array of Inexpensive Disks),主要是相比于以往的昂贵的SLED(Single Large Expensive Disk),后改名为冗余独立磁盘阵列(Redundant Array of Independent Disks),毕竟现在的RAID控制卡也已经不便宜了。

基于不同级别的冗余和性能要求,RAID有不同的级别(level)。不同的级别也决定了可靠性(reliability)、可用性(availability)、性能(performance)和容量(capacity)的不同。

许多RAID级别采用了一种错误保护机制,叫做奇偶校验(parity)。大部分情况使用的是异或运算(XOR),不过RAID 6则使用了两种独立的奇偶校验方法。

不同的RAID级别,使用不同的数字来表示,例如RAID 0、RAID 1等等。

RAID级别按照种类划分有标准(standard)级别、嵌套/混合(nested/hybrid)级别和非标准(non-standard)级别。RAID级别是由SINA(Storage Networking Industry Association)组织所定义的。

接下来我们就来一一介绍这几种RAID。

 

标准级别

RAID 0

基于striping方式(data striping是一种切割逻辑上连续数据的技术,例如切割文件,使得连续的片段可以被存储在不同的物理存储设备上。)来组织数据,不具备镜像(mirror,即数据冗余)和校验的功能。如图所示。

一个文件会被切割成多个block,假设有8个,有A1~A8表示,那么会依次存入阵列中的每个磁盘当中。

优点:

  1. 读写性能提升,理论上有n块磁盘,就可以带来n倍的性能提升,因为读写是并行的。
  2. 存储容量提升,阵列总容量为n块磁盘之和。如果磁盘的容量不是相等的,则总容量为n倍的最小磁盘容量。其他RAID级别遇到磁盘容量不同的时候,也是以最小磁盘容量为准。接下来我们假设所有RAID的磁盘容量都是相同的,一般在生产环境中,阵列中的磁盘的容量、型号等也都会是一模一样的。

缺点:

  1. 没有数据冗余能力,1块硬盘损坏则整个RAID无法使用,数据全部丢失。并且随着阵列中磁盘数量的增加,发生损坏的概率就越大。
  2. 没有校验能力,无法基于校验码进行数据恢复。

其他:

  1. 至少需要2块硬盘。

RAID 1

基于镜像(mirroring)的方式,当写入数据的时候,会同时写入每个磁盘设备。

优点:

  1. 具备数据冗余能力,只要阵列中还有一块硬盘处于工作状态,那么整个阵列就依然可用。
  2. 读性能提升,如果RAID控制器足够强大,则读性能可接近于RAID 0,不过实际实现中,应该无法达到。

缺点:

  1. 写性能下降。由于同一个block的数据需要被写入阵列中的每一个磁盘中,因此写性能下降。磁盘数越多,写性能下降越多。最慢的磁盘会限制整个阵列的写性能。
  2. 没有校验能力,无法基于校验码进行数据恢复。

其他:

  1. 存储容量保持不变。总容量为单块磁盘容量。
  2. 至少需要2块磁盘。

RAID 2

数据的组织方式类似RAID 0,通过striping技术以位(bit)为单位将数据切割至多块磁盘上。使用汉明码(hamming-code)作为校验码,具备数据恢复能力,但是需要多块磁盘作为校验盘。所有磁盘的主轴旋转是同步的。

目前已被弃用!!!

RAID 3

类似RAID 2。区别在于RAID 3是基于字节(byte)级别,使用非汉明码的校验码,所以校验码只需存储在一块磁盘中。

目前已被弃用!!!

RAID 4

类似于RAID 2和3。区别在于RAID 4是基于块(block)级别,校验码存储在一块磁盘上。RAID 4相对于2和3的最大优点在于I/O并行性(parallelism):在2和3中,一次简单的读操作会从阵列中的所有磁盘读取数据,而4则不需要。

由于只有一块校验盘,每次写入数据的时候需要计算校验码,随着磁盘数的增加,校验盘的性能会成为整个阵列的瓶颈。

目前RAID 4的实现大部分已被私有技术RAID DP所取代,RAID DP使用了两块校验盘。

注意:图片可能有点错误,DISK 2中存储的应该是BLOCK A3、B3、C3和D3的数据。

优点:

  1. 读写性能提升,读性能理论为n倍的数据盘,写性能理论小于n倍的数据盘且随着数据盘的增加,写性能越来越受制于校验盘。
  2. 具有数据恢复能力。
  3. 存储容量提升,为磁盘总容量减去校验盘容量(n-1)。

缺点:

  1. 无镜像能力,虽然存在数据恢复能力,但是数据盘损坏后,基于校验码恢复数据会有额外的计算开销。
  2. 校验盘瓶颈问题。

其他:

  1. 至少需要3块磁盘。

RAID 5

类似于RAID 4,RAID 5基于块(block)级别切割数据至多个磁盘,同样具备校验码。但是,最大的区别在于RAID 5的校验码不是存放在专门的磁盘上,而是分布式地存储在阵列中的每个磁盘中,这就解决了RAID 4的写性能受制于校验盘的问题了。截止目前,涉及校验的RAID,它们的校验码都是只计算一次并保留一份,这也叫做“单校验概念”(single-parity concept)。像这类单校验的设计,当阵列越来越庞大的时候,容易受到系统故障的影响,这里的系统故障指的是磁盘损坏阵列重建(rebuild)时间以及重建期二次磁盘损坏几率。详见:Increasing rebuild time and failure probability

优点:

  1. 读写性能提升,理论为n倍的磁盘,解决了RAID 4中的校验盘瓶颈问题。
  2. 具有数据恢复能力。
  3. 存储容量提升,为磁盘总容量减去校验码占用容量(n-1),校验码占用的容量约为一个磁盘容量。

缺点:

  1. 无镜像能力,虽然存在数据恢复能力,但是数据盘损坏后,基于校验码恢复数据会有额外的计算开销。
  2. 单校验问题,此前的所有具备校验能力的RAID亦均有此问题。

其他:

  1. 至少需要3块磁盘。

RAID 6

类似于RAID 5,RAID 6基于块(block)级别切割数据至多个磁盘,具备分布式校验码。只不过是使用了双校验码(double-parity)机制。双校验支持损坏至多2块磁盘。这使得更大的RAID阵列更加实用,尤其对于高可用系统,因为大容量的阵列需要更长的时间重建。至少需要4块磁盘。和RAID 5一样,单块磁盘故障会降低整体阵列性能,直到故障盘被替换。如果磁盘的容量和阵列的容量越大的话,那么越应该考虑使用RAID 6来替代RAID 5。RAID 10同样也最小化了这些问题。

优点:

  1. 读写性能提升,写性能可能稍微逊色于RAID 5,因为要计算2种校验码。
  2. 具备数据恢复能力,允许损坏至多2块磁盘。
  3. 存储容量提升,n-1。
  4. 新增双校验机制,解决单校验的问题,此类设计更适合支持大容量阵列并提高其可用性。

缺点:

  1. 必须牺牲2块磁盘的容量存放校验码。
  2. 无镜像能力,虽然存在数据恢复能力,但是数据盘损坏后,基于校验码恢复数据会有额外的计算开销。不过双校验应该可以加快数据恢复的时间。

其他:

  1. 至少需要4块磁盘。

 

嵌套级别

RAID中的每个元素(组成成分),可以是独立磁盘,也可以是一个RAID阵列。对于后者,我们称之为RAID嵌套。

RAID 01

也叫作RAID 0+1或者RAID 0&1,先将磁盘制作成RAID 0,再将每个RAID 0组合成RAID 1。如图所示。

任何一块磁盘损坏都会导致其中一个stripe(基于striping技术的RAID 0,也可叫stripe)不可用,此时整个RAID 01阵列实际上就降级为RAID 0阵列了。该阵列相比RAID 10在重建期会遭遇更高的风险,因为它需要读取剩下的stripe中的所有磁盘的所有数据而不是其中一块盘上的所有数据,增加了URE(Unrecoverable Rear Error)的概率并且明显扩大了重建窗口。

至少需要4块磁盘。可以采用更多的磁盘,但是这意味着磁盘故障率也会随之增加,如果阵列只有2个stripe,并且刚好每个stripe各损坏1块磁盘,那么整个阵列就完了。

按照此图示的存储容量为n/2。

因此,RAID 01是不好的,不建议使用。建议使用RAID 10来替代它!!!

RAID 10

也叫作RAID 1+0或者RAID 1&0,先将磁盘制作成RAID 1,再将每个RAID 1组合成RAID 0。如图所示。

这种阵列相对RAID 01可以承受更多的设备损坏,特别是在单个镜像卷中的磁盘数量较多的情况下。

按照此图示的存储容量为n/2。

 

非RAID架构

关于RAID的常用级别基本已经说明完毕,除了以上几个RAID级别,还有一些并不是基于RAID技术但是也可以将磁盘数据集合起来的技术,这些技术通常只是简单地将磁盘堆叠起来使用而已,并不一定具备像RAID一样的数据冗余和性能提升的功能。

  • JBOD:Just a Bunch Of Disks。
  • SPAN or BIG:字面意义,非缩略词。
  • MAID:Massive Array of Idle Drives。

详见:Non-RAID drive architectures

 

实现

RAID的实现主要有两种,一种是基于硬件俗称硬RAID,另一种是基于软件俗称软RAID。

硬RAID需要硬件(RAID卡,即RAID控制器)支持,一般是在OS启动之前,在BIOS中进行RAID的相关配置,并且在OS启动之后,会有对应RAID卡厂商的私有软件工具可以进行配置。因为本人没有相关硬RAID配置经验以及这只是实验环境,因此没有硬RAID相关实现的介绍。

软RAID的实现方式也有很多种,一般是基于操作系统的某些特性,例如基于Linux内核的md(Multiple Device)或者OpenBSD的softraid。

本文主要阐述如何基于Linux操作系统实现软RAID。

mdadm

基于Linux的md实现的命令是mdadm,它所支持的RAID级别:LINEAR(类似JBOD)、RAID 0、RAID 1、RAID 4、RAID 5、RAID 6和RAID 10。

OS:CentOS 7.5

mdadm:v4.0

我们的目标是,使用4块1GB的磁盘,创建RAID 5阵列,其中3块作为有效(active)盘,1块作为备用(spare)盘。

创建4块磁盘,分区,文件系统类型为Linux的RAID(ID:fd)。

[root@C7 ~]# fdisk -l | grep -i "raid"
/dev/sdb1            2048     2097151     1047552   fd  Linux raid autodetect
/dev/sdc1            2048     2097151     1047552   fd  Linux raid autodetect
/dev/sde1            2048     2097151     1047552   fd  Linux raid autodetect
/dev/sdd1            2048     2097151     1047552   fd  Linux raid autodetect

查看内核识别到的分区信息,确保我们刚才所创建的四个磁盘的分区已经被内核识别。

[root@C7 ~]# cat /proc/partitions 
major minor  #blocks  name

   8        0   20971520 sda
   8        1    1048576 sda1
   8        2   19921920 sda2
   8       16    1048576 sdb
   8       17    1047552 sdb1
   8       32    1048576 sdc
   8       33    1047552 sdc1
  11        0    4365312 sr0
   8       64    1048576 sde
   8       65    1047552 sde1
   8       48    1048576 sdd
   8       49    1047552 sdd1
 253        0   17821696 dm-0
 253        1    2097152 dm-1

如果未识别到,则使用partprobe告知内核。警告信息可以忽略。

[root@C7 ~]# partprobe 
Warning: Unable to open /dev/sr0 read-write (Read-only file system).  /dev/sr0 has been opened read-only.

创建磁盘阵列。

[root@C7 ~]# mdadm -C /dev/md0 -l 5 -n 3 -x 1 /dev/sd{b,c,d,e}1
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

查看阵列状态信息

方法一

[root@C7 ~]# cat /proc/mdstat 
Personalities : [raid6] [raid5] [raid4] 
md0 : active raid5 sdd1[4] sde1[3](S) sdc1[1] sdb1[0]
      2091008 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU]

阵列创建的过程需要时间,例如写入RAID元数据之类的,想动态查看的话,可以通过watch命令

[root@C7 ~]# watch -n 1 cat /proc/mdstat

方法二

[root@C7 ~]# mdadm -D /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Wed Apr  3 14:15:55 2019
        Raid Level : raid5    # RAID级别
        Array Size : 2091008 (2042.00 MiB 2141.19 MB)    # 4块磁盘,各1GB,1块备用盘,还有1块盘的容量为校验码,因此阵列可用容量为2GB。
     Used Dev Size : 1045504 (1021.00 MiB 1070.60 MB)
      Raid Devices : 3
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Wed Apr  3 14:16:00 2019
             State : clean    # 阵列的状态,clean表示干净状态,即阵列处于健康工作状态
    Active Devices : 3
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 1

            Layout : left-symmetric
        Chunk Size : 512K

Consistency Policy : resync

              Name : C7:0  (local to host C7)
              UUID : ebf794e8:8f01958a:f004744b:7be7a8cf    # 系统重启后,阵列的设备名称可能不再是/dev/md0,因此可使用UUID来代替设备名称写入/etc/fstab。
            Events : 18

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync   /dev/sdb1
       1       8       33        1      active sync   /dev/sdc1
       4       8       49        2      active sync   /dev/sdd1

       3       8       65        -      spare   /dev/sde1

格式化RAID设备并挂载使用

[root@C7 ~]# mkfs -t xfs /dev/md0
meta-data=/dev/md0               isize=512    agcount=8, agsize=65408 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=522752, imaxpct=25
         =                       sunit=128    swidth=256 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=8 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@C7 ~]# mkdir /raid_data
[root@C7 ~]# mount /dev/md0 /raid_data

创建一个测试的文本文件,输入一些信息。在下文标记阵列中磁盘为faulty状态时,我们可以通过测试此文件是否内容可读取来判断RAID是否可用。

[root@C7 ~]# cat /raid_data/raid.txt
this is a test file for RAID 5 !!!

手动标记阵列中的一块有效磁盘为faulty状态,并观察备用盘是否自动顶替。

[root@C7 ~]# mdadm /dev/md0 -f /dev/sdd1
mdadm: set /dev/sdd1 faulty in /dev/md0

再次查看状态会发现一些变化。

[root@C7 ~]# mdadm -D /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Wed Apr  3 14:15:55 2019
        Raid Level : raid5
        Array Size : 2091008 (2042.00 MiB 2141.19 MB)
     Used Dev Size : 1045504 (1021.00 MiB 1070.60 MB)
      Raid Devices : 3
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Wed Apr  3 14:45:28 2019
             State : clean, degraded, recovering    # 由于磁盘损坏了1块,且存在备用盘。备用盘自动顶替,阵列进入重建期,在重建完成前,阵列处于降级模式工作。重建完毕后,状态又会变回clean了。
    Active Devices : 2
   Working Devices : 3
    Failed Devices : 1
     Spare Devices : 1

            Layout : left-symmetric
        Chunk Size : 512K

Consistency Policy : resync

    Rebuild Status : 65% complete    # 数据重建进度。

              Name : C7:0  (local to host C7)
              UUID : ebf794e8:8f01958a:f004744b:7be7a8cf
            Events : 30

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync   /dev/sdb1
       1       8       33        1      active sync   /dev/sdc1
       3       8       65        2      spare rebuilding   /dev/sde1

       4       8       49        -      faulty   /dev/sdd1

待阵列重建完毕,再标记一块磁盘为faulty状态。

[root@C7 ~]# mdadm /dev/md0 -f /dev/sdc1
mdadm: set /dev/sdc1 faulty in /dev/md0

此时我们的阵列,就只能工作于降级模式而无法恢复clean了。

[root@C7 ~]# mdadm -D /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Wed Apr  3 14:15:55 2019
        Raid Level : raid5
        Array Size : 2091008 (2042.00 MiB 2141.19 MB)
     Used Dev Size : 1045504 (1021.00 MiB 1070.60 MB)
      Raid Devices : 3
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Wed Apr  3 14:47:55 2019
             State : clean, degraded 
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 2
     Spare Devices : 0

            Layout : left-symmetric
        Chunk Size : 512K

Consistency Policy : resync

              Name : C7:0  (local to host C7)
              UUID : ebf794e8:8f01958a:f004744b:7be7a8cf
            Events : 45

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync   /dev/sdb1
       -       0        0        1      removed
       3       8       65        2      active sync   /dev/sde1

       1       8       33        -      faulty   /dev/sdc1
       4       8       49        -      faulty   /dev/sdd1

无论阵列处于重建期或者降级模式,测试文件都是可读的。

如果该阵列不使用了,那么我们应该先卸载阵列,再关闭它。

[root@C7 ~]# umount /dev/md0
[root@C7 ~]# mdadm -S /dev/md0
mdadm: stopped /dev/md0
[root@C7 ~]# mdadm -D /dev/md0
mdadm: cannot open /dev/md0: No such file or directory

关闭后,阵列设备文件消失。

 

总结

  1. 实际生产环境中,数据的完整性和性能是重要的,因此不应该使用软RAID,而应该采用硬RAID。
  2. 不同的RAID卡厂商的配置方式不同,万变不离其宗,了解RAID原理各级别特性比RAID实现更重要。
  3. 本文关于Linux上的软RAID实现只是简单阐述,切勿直接拿来在生产环境使用。

 

posted @ 2019-04-03 17:06  阿龙弟弟  阅读(1875)  评论(0编辑  收藏  举报
回到顶部