Linux中RAID介绍
1. 概述
RAID代表Redundant Array of Inexpensive/Independent Disks。
**我们用冗余构建我们的存储——关键功能的重复——这样任何一个部分都不会出现故障并导致我们的整个系统崩溃。**因为数据读取和写入分布在多个磁盘上,所以 RAID 还可以为我们提供性能优势。
ZFS 和btrfs 等现代文件系统 具有内置的 RAID 功能。同样重要的是,我们要记住 RAID 不是什么:它不是备份。例如,如果我们的数据库被擦除或损坏,镜像 RAID 会为我们提供两个空白或损坏数据库的副本。单独的备份为我们提供了恢复选项。
在本教程中,我们将探索在 Linux 中使用 RAID 的 方法。
2. RAID 类型
RAID 可以使用专用硬件控制器或完全在软件中实现。如今,软件 RAID 更为常见。
我们通过“RAID 级别” 的标准编号系统来指代不同类型的 RAID 。这些数字并不是指使用了多少磁盘。
RAID 最大的优势来自于数据的复制。我们的数据存在于我们的 RAID 系统上的多个位置,因此我们可以避免硬件故障期间的停机时间。复制可以通过镜像(保留所有内容的重复副本)或奇偶校验(我们数据的校验和计算)。
2.1. 硬件与软件
在本指南中,我们将探索通过软件内置于 Linux 中的 RAID 选项。硬件 RAID 超出了本文的范围;请注意,它仅在特殊情况下在 Linux 上有用,我们可能需要在计算机的 BIOS 中将其关闭。
2.2. 条带化和/或镜像(RAID 0、1 或 10)
RAID 级别 0 有一个适当的数字:它具有零冗余!
相反,**在 RAID 0 中,数据跨驱动器写入,或“条带化”。**这意味着它可能会同时从多个驱动器中读取。这可以给我们带来真正的性能提升。
但与此同时,现在我们有两个驱动器可能会发生故障,从而取出我们所有的数据。因此,RAID 0 仅在我们想要提高性能但不关心长期存储时才有用。
我们将 RAID 级别 1 称为“镜像”,因为它是使用一对相等的驱动器创建的。 每次将数据写入 RAID 1 设备时,它都会写入该对中的两个驱动器。
因此写入性能稍慢,但读取性能可能会快得多,因为数据是同时从两个磁盘读取的。
这两个级别的 RAID 可以组合或嵌套,创建所谓的 RAID 1+0 或只是 RAID 10。(还有其他排列,但 RAID 10 是最常见的。)
我们可以创建一个具有四个磁盘的 RAID 10 设备:RAID 0 中的一对磁盘,RAID 0 中的另一对磁盘镜像。
这种 RAID 的 RAID 尝试将 RAID 0 的性能与 RAID 1 的冗余结合起来,既快速又可靠。
2.3. 奇偶校验(RAID 5 或 RAID 6)
我们可以通过存储奇偶校验 数据来节省空间,而不是存储我们数据的完整副本。奇偶校验允许我们的 RAID 重建存储在故障驱动器上的数据。
RAID 5 至少需要三个大小相同的驱动器才能运行。在实践中,我们可以添加更多,但很少使用超过十个。
RAID 5 为校验和奇偶校验数据留出一个驱动器的空间。但是,它并非全部保存在一个驱动器上。相反,奇偶校验数据与文件系统数据一起在所有设备上进行条带化。
这意味着我们通常希望使用一组大小和速度相同的驱动器来构建 RAID。添加更大的驱动器不会为我们带来更多空间,因为 RAID 只会使用最小成员的大小。同样,RAID 的性能将受到其最慢成员的限制。
如果一个驱动器死机,RAID 5 可以恢复和重建而不会丢失数据。如果两个或更多驱动器崩溃,我们将不得不从备份中恢复整个事物。
RAID 6 类似于 RAID 5,但为奇偶校验数据预留了两个磁盘的价值。这意味着 RAID 6 可以从两个失败的成员中恢复。
RAID 5 为我们提供了比镜像更多的可用存储空间,但代价是一些性能。估计存储的一种快速方法是相等大小的驱动器的总量减去一个驱动器。例如,如果我们有 6 个 1 TB 的驱动器,我们的 RAID 5 将有 5 TB 的可用空间。这是 83%,而我们的驱动器中有 50% 被镜像到 RAID 1。
曾经,服务器制造商认为 RAID 5 是存储领域的最佳实践。由于所谓的“RAID 5 写入漏洞”,它在某种程度上已经失宠,这是下一代文件系统和 RAIDZ 解决的问题。
3. Linux内核RAID(mdraid)
让我们使用mdadm 工具创建一些新的 RAID 。
3.1. 基本 RAID
我们将从两个相同的磁盘或分区开始,并创建一个条带化 RAID 0 设备。
首先,让我们确保我们有正确的分区。我们不想破坏重要的东西:
# lsblk -o NAME,SIZE,TYPE
NAME SIZE TYPE
sdb 931.5G disk
└─sdb1 4G part
sdc 931.5G disk
└─sdc1 4G part
我们将使用mdadm 命令(多磁盘管理员):
# mdadm --verbose --create /dev/md0 --level=0 --raid-devices=2 /dev/sdb1 /dev/sdc1
mdadm: chunk size defaults to 512K
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
我们的第一个 RAID 设备已经创建!让我们分解一下我们与mdadm一起使用的选项:
- –verbose告诉我们更多关于正在发生的事情。
- –create告诉mdadm创建一个新的 RAID 设备,将其命名为我们想要的任何名称(在本例中为md0)。
- –level=0是我们的 RAID 级别,如上所述。0 级只是条带化,没有冗余。
- –raid-devices=2让mdadm知道该阵列需要两个物理磁盘。
- /dev/sdb1和*/dev/sdc1*是我们独立磁盘阵列中包含的两个分区。
所以我们的分区 RAID 已经创建,但是像任何设备一样,它还没有文件系统,也没有被挂载。
我们可以用lsblk再看一遍:
# lsblk -o NAME,SIZE,TYPE
NAME SIZE TYPE
sdb 931.5G disk
└─sdb1 4G part
└─md0 8G raid0
sdc 931.5G disk
└─sdc1 4G part
└─md0 8G raid0
请注意md0设备是如何将两个分区相加的大小,正如我们对 RAID 0 所期望的那样。
3.2. 管理我们的 RAID
我们还在*/proc/mdstat*中找到有用的信息:
# cat /proc/mdstat
Personalities : [raid0]
md0 : active raid0 sdc1[1] sdb1[0]
1952448512 blocks super 1.2 512k chunks
unused devices: <none>
要使用这个新的 RAID,我们需要使用文件系统对其进行格式化并挂载它:
# mkfs /dev/md0
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 2094592 4k blocks and 524288 inodes
Filesystem UUID: 947484b6-05ff-4d34-a0ed-49ee7c5eebd5
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
# mount /dev/md0 /mnt/myraid/
# df -h /mnt/myraid
Filesystem Size Used Avail Use% Mounted on
/dev/md0 7.8G 24K 7.4G 1% /mnt/myraid
像除 ZFS 之外的任何其他文件系统一样,我们将在*/etc/fstab*中添加一行以使此挂载点永久化。
如果我们想从我们的 RAID 设备启动(为了简单起见,我们可能不会),或者允许mdadm在启动或关闭期间管理阵列,我们可以将阵列的信息附加到可选的*/etc/mdadm/mdadm。配置*文件:
# mdadm --detail --scan
ARRAY /dev/md1 metadata=1.2 spares=1 name=salvage:1 UUID=0c32834c:e5491814:94a4aa96:32d87024
如果我们想取消我们的 raid,我们可以再次使用mdadm:
# mdadm -S /dev/md0
mdadm: stopped /dev/md0
我们可以使用不同的 –level 和 –raid-devices 选项创建类似的RAID。
例如,我们可以创建一个 5 磁盘 RAID 5:
# mdadm --verbose --create /dev/md1 --level=5 --raid-devices=5 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1 /dev/sdf1
mdadm: layout defaults to left-symmetric
mdadm: layout defaults to left-symmetric
mdadm: chunk size defaults to 512K
mdadm: size set to 4189184K
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md1 started.
然后,我们可以mkfs并挂载我们最新的 RAID。
3.3. 故障驱动器和热备件
如果其中一个驱动器发生故障,我们的新 RAID 5 会发生什么情况?让我们用mdadm模拟那个事件:
# mdadm /dev/md1 -f /dev/sdc1
mdadm: set /dev/sdc1 faulty in /dev/md1
现在,/proc/mdstat告诉我们什么?让我们来看看:
# cat /proc/mdstat
Personalities : [raid0] [raid6] [raid5] [raid4]
md1 : active raid5 sdf1[5] sde1[3] sdd1[2] sdb1[1] sdc1[0](/F)
16756736 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/4] [_UUUU]
unused devices: <none>
在这里,我们看到我们选择的分区,标记为 (F) 表示失败。
我们还可以向mdadm询问我们数组的更多详细信息:
# mdadm --detail /dev/md1
/dev/md1:
Version : 1.2
Creation Time : Tue Aug 10 14:52:59 2021
Raid Level : raid5
Array Size : 16756736 (15.98 GiB 17.16 GB)
Used Dev Size : 4189184 (4.00 GiB 4.29 GB)
Raid Devices : 5
Total Devices : 5
Persistence : Superblock is persistent
Update Time : Tue Aug 10 14:59:20 2021
State : clean, degraded
Active Devices : 4
Working Devices : 4
Failed Devices : 1
Spare Devices : 0
Layout : left-symmetric
Chunk Size : 512K
Consistency Policy : resync
Name : salvage:1 (local to host salvage)
UUID : 0c32834c:e5491814:94a4aa96:32d87024
Events : 24
Number Major Minor RaidDevice State
- 0 0 0 removed
1 8 34 1 active sync /dev/sdb1
2 8 35 2 active sync /dev/sdd1
3 8 36 3 active sync /dev/sde1
5 8 37 4 active sync /dev/sdf1
0 8 33 - faulty /dev/sdc1
我们的 RAID 仍然很强大。用户不应该能够分辨出任何区别。但是我们可以看到它处于“降级”状态,所以我们需要更换那个有故障的硬盘。
假设我们有一个替代我们的死驱动器。它应该与原件相同。
我们可以移除有故障的驱动器并添加一个新驱动器。我们应该记住,如果硬件发生变化, /dev/sd*设备列表有时会发生变化,因此请仔细检查lsblk。
首先,我们从阵列中移除故障驱动器:
# mdadm /dev/md1 --remove /dev/sdc1
mdadm: hot removed /dev/sdc1 from /dev/md1
接下来,我们实际更换驱动器并添加新驱动器。(这是热插拔驱动器硬件为我们节省大量时间的地方!)
我们可以查看/proc/mdstat*来观察 RAID 自动重建*:
# mdadm /dev/md1 --remove /dev/sdc1
mdadm: hot removed /dev/sdc1 from /dev/md1
blogdemo@itcodingman:~# mdadm /dev/md1 --add /dev/sdc1
mdadm: added /dev/sdc1
# cat /proc/mdstat
Personalities : [raid0] [raid6] [raid5] [raid4]
md1 : active raid5 sdc1[6] sdf1[5] sde1[3] sdd1[2] sdb1[1]
16756736 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/4] [_UUUU]
[==>..................] recovery = 10.7% (452572/4189184) finish=3.4min speed=18102K/sec
如果正常运行时间真的很重要,我们可以添加一个专用的备用驱动器,让 mdadm自动切换到:
# mdadm /dev/md1 --add-spare /dev/sdg1
mdadm: added /dev/sdg1
这可能是值得的;我们可以权衡所涉及的时间和金钱。
让我们再次检查一下我们的数组:
# mdadm --detail /dev/md1 | grep spare
7 8 38 - spare /dev/sdg1
五个磁盘带有数据和奇偶校验。一个磁盘未使用,只是等待需要。
4. 逻辑卷管理器
大多数现代 Linux 文件系统不再直接在驱动器或分区上创建,而是在使用LVM 创建的逻辑卷上创建。
简而言之,LVM 将物理卷(驱动器或分区)组合成卷组。卷组是我们可以从中创建逻辑卷的池。我们可以将文件系统放到这些逻辑卷上。
RAID 是在创建逻辑卷期间加入的。这些可能是线性的、条带的、镜像的或更复杂的奇偶校验配置。
我们应该注意,创建 RAID LVM 逻辑卷使用 Linux 内核 RAID (mdraid)。如果我们想要 LVM 的便利性,能够扩展卷组和调整逻辑卷的大小,我们可以同时拥有简单 mdraid 的可靠性。
但是,如果 LVM 听起来过于复杂,我们总是可以在物理驱动器上使用 mdraid。
另一个常见的选择是使用mdadm 创建我们的 RAID 设备,然后将它们用作带有 LVM 的 PV。
4.1.告诉 LVM 在 RAID 中使用我们的卷
LVM RAID 在逻辑卷级别创建。
这意味着我们需要首先创建分区,使用pvcreate 将它们标记为 LVM 物理卷,并使用vgcreate 将它们放入卷组。在此示例中,我们将卷组称为raid1vg0。
RAID 创建步骤指定 RAID 的类型以及用于镜像或条带化的磁盘数量。我们不需要指定每个物理卷。我们可以让 LVM 处理所有这些:
# lvcreate --mirrors 1 --type raid1 -l 100%FREE -n raid01v0 raid1vg0
Logical volume "raid01v0" created.
# mkfs.ext4 /dev/raid1vg0/raid01v0
像往常一样,我们然后格式化并安装我们的新 RAID 卷。如果我们想要一个自动处理所有这些的系统,我们有 ZFS。
5. 使用 ZFS 或 btrfs 集成文件系统 RAID
我们不会在本文中介绍下一代文件系统的细节,但软件 RAID 和 LVM 的许多概念都可以翻译过来。
ZFS 使用“vdevs” 虚拟设备,就像 LVM 使用卷组一样。这些 vdev 可能是物理磁盘、镜像、raidz 变体(ZFS 采用 RAID 5),或者从 OpenZFS 2.1 开始,droid。
例如,我们可以创建一个 RAID 1 镜像 zpool:
# zpool create -f demo mirror /dev/sdc /dev/sdd
ZFS 为我们处理所有其他事情,在*/demo*下格式化和安装我们的新卷池。 btrfs 中的等价物是:
# mkfs.btrfs -L demo -d raid1 /dev/sdc /dev/sdd
btrfs 的一个主要限制是它不支持 RAID5 或 RAID 6,至少不可靠 。因此,我们将远离生产系统。 这些下一代文件系统负责 RAID 和卷管理的许多细节。此外,它们通过块级校验和提供更高的数据完整性。
尽管它们完全是另一个话题,但我们可以通过研究 ZFS 或 btrfs 来解决更多的存储问题。