RAID

出自 Arch Linux 中文维基

獨立磁盤冗餘陣列 (Redundant Array of Independent Disks,RAID) 是一種將多個磁盤驅動器組件(通常是多塊硬盤或多個分區)組合為一個邏輯單元的存儲技術。根據 RAID 的部署情況,這個邏輯單元可以是單個的文件系統,也可以是一個能在其上建立多個分區的透明中間層。根據所需的冗餘量和性能要求,數據按照 #RAID 級別 中的某一種方式分布在驅動器中。所選的 RAID 級別決定了是否可以防止數據丟失(硬盤故障時)、是否提高性能或結合兩者優勢。

本文介紹如何使用 mdadm 創建並管理一個軟件磁盤陣列。

警告: 確保在操作前 備份 所有數據。

RAID 級別[編輯 | 編輯原始碼]

儘管大部分 RAID 級別都或多或少地包含了數據冗餘,RAID 並不能完全保證數據安全。如果遇到火災、計算機被盜或者多塊硬盤同時損壞,RAID 將無法保護數據。此外,配置一個帶有 RAID 的系統是一個複雜的過程,可能會破壞現有數據。

基本 RAID 級別[編輯 | 編輯原始碼]

有多種不同的 基本 RAID 級別,下面列出了最常用的幾種。

RAID 0
將多塊硬盤組合為一個帶區卷,儘管它 並不提供數據冗餘,它仍可以被當做是 RAID,而且它確實提供了 巨幅的速度提升。如果提高速度比數據安全更重要(比如作為 swap 分區),可以選擇這種 RAID 級別。在服務器上,RAID 1 和 RAID 5 陣列更加合適。在 RAID 0 陣列中,塊設備的大小是最小組成分區的大小乘以組成分區的數量。
RAID 1
這是最直接的 RAID 級別:完全鏡像。與其他 RAID 級別一樣,它只在分區位於不同物理硬盤上才有效。如果某一塊硬盤損壞,由 RAID 陣列提供的塊設備將不受影響。可以使用 RAID 1 的情境包括了除 swap 和臨時文件外的其他所有情境。請注意,如果使用由軟件實現的 RAID,引導分區只能選擇 RAID 1,因為讀取引導分區的引導器通常無法辨識 RAID,但一個 RAID 1 的組成分區可以像常規分區一樣讀取。RAID 1 陣列塊設備的大小是最小組成分區的大小。
RAID 5
需要至少 3 塊物理硬盤,並結合了 RAID 1 的數據冗餘和 RAID 0 的速度與可用空間上的優勢。RAID 5 使用了類似 RAID 0 的條帶化技術,同時也將奇偶校驗塊分布式地存儲在每一塊磁盤上。如果遭遇硬盤損壞,這些奇偶校驗塊就可以用來在替代的新磁盤上重建損壞的數據。RAID 5 僅可彌補一個組成磁盤損壞帶來的損失。
注意: RAID 5 是結合了速度與數據冗餘優勢的常用選擇。但值得注意的是,當一塊硬盤損壞而沒有及時更換,此時若再有硬盤損壞,則所有數據都將丟失。此外,考慮到現代磁盤的超大容量和消費級硬盤無法恢復的讀取錯誤率 (Unrecoverable read error, URE),超過 4TiB 的陣列在重建數據時出現至少一處讀取錯誤 (URE) 的概率幾乎在預料之中(概率大於 50%)。因此,存儲行業不再推薦使用 RAID 5。
RAID 6
需要至少 4 塊物理硬盤,提供了和 RAID 5 一樣的優勢並且在兩塊硬盤損壞時仍能保證數據安全。RAID 6 使用了和 RAID 5 類似的條帶化技術,但是把兩個不同的奇偶校驗塊 分布式地存儲在每一塊磁盤上。如果磁盤發生故障,這些奇偶校驗塊將用於重建替換磁盤上的數據。RAID 6 可以承擔兩個組成磁盤的損失。在抵禦無法恢復的讀取錯誤 (Unrecoverable read error, URE) 時也某種程度上更加可靠,因為磁盤陣列在重建某一塊損壞硬盤的數據時仍然有奇偶校驗塊可以校驗數據。但是,總體而言,RAID 6 開銷較大,大多數時候 far2 布局的 RAID 10(參見下文)提供了更快的速度和更強的可靠性,因此更傾向於採用 RAID 10。

嵌套 RAID 級別[編輯 | 編輯原始碼]

RAID 1+0
RAID1+0 是一種結合了兩種基本 RAID 級別的嵌套級別,它相對基本級別提高了性能且增加了冗餘量。它通常被稱為 RAID10,但是,Linux MD(內核自帶的 RAID 實現)支持的 RAID10 不是簡單的兩層 RAID 重疊,請看下文。
RAID 10
Linux 下的 RAID10 建立在 RAID1+0 的概念上,但它將其實現為單一的一層,這一層可以有多種不同的布局。可參考 創建複雜 RAID 10
在 Y 塊硬盤上的 近 X 布局 在不同硬盤上重複儲存每個數據塊 X 次,但不需要 Y 可以被 X 整除。數據塊放在所鏡像的磁盤上幾乎相同的位置,這就是 近布局 名字的來源。它可以工作在任意數量的磁盤上,最少是 2 塊。在 2 塊硬盤上的近 2 布局相當於 RAID1,4 塊硬盤上的近 2 布局相當於 RAID1+0。
在 Y 塊硬盤上的 遠 X 布局 設計用於在鏡像陣列中提供與條帶化技術一樣快的讀取速度。它通過把每塊硬盤分成前後兩部分來實現這一點,寫入第一塊硬盤前半部分數據也會寫入第二塊硬盤的後半部分,反之亦然。這樣可以達到一個效果,那就是把對連續數據的讀取條帶化,而這正是 RAID0 和 RAID5 讀取性能高的原因。它的缺點在於寫入連續數據時有輕微性能損失,因為硬盤磁頭要運動到另一片區域來寫入鏡像。當數據讀取性能和可用性/冗餘性一樣重要時,比起 RAID1+0 RAID5,更應該優先考慮遠 2 布局的 RAID10。需注意這種方式仍無法代替備份。詳情請閱讀維基百科相關頁面。
警告: mdadm cannot reshape arrays in far X layouts which means once the array is created, you will not be able to mdadm --grow it. For example, if you have a 4x1TB RAID10 array and you want to switch to 2TB disks, your usable capacity will remain 2TB. For such use cases, stick to near X layouts.

RAID 級別對比[編輯 | 編輯原始碼]

RAID 級別 數據冗餘 物理設備利用率 讀取性能 寫入性能 最少磁盤數量
0 100% n 倍

最優

n 倍

最優

2
1 50% 如果有多個進程同時讀取,最多 n 倍,否則 1 倍 1 倍 2
5 67% - 94% (n−1) 倍

較優

(n−1) 倍

較優

3
6 50% - 88% (n−2) 倍 (n−2) 倍 4
10,far2 50% n 倍

最優; 與 RAID0 相當但加入了數據冗餘

(n/2) 倍 2
10,near2 50% 如果有多個進程同時讀取,最多 n 倍,否則 1 倍 (n/2) 倍 2

* 其中 n 表示用於組成陣列的磁盤數量。

實現方式[編輯 | 編輯原始碼]

RAID 設備可以用不同方式來管理:

軟件 RAID
這是最簡單的實現方式,因為它不依賴於專用固件或專有軟件。這種陣列由操作系統通過以下方式進行管理:
  • 通過抽象層管理(比如 mdadm);
    注意: 這是在本指南下文將要使用的方法。
  • 通過邏輯卷管理器來管理(比如 LVM);
  • 通過文件系統的某個組件來管理(比如 ZFSBtrfs)。
硬件 RAID
這種陣列由安裝在計算機上的專用硬件卡直接管理,硬盤直接連接在該計算機上。RAID 的處理邏輯由板載的處理器完成,它獨立於 主處理器 (CPU)。儘管這種方案獨立於任何操作系統,但卻需要驅動程序來使硬件 RAID 控制器正常工作。取決於不同的製造商,硬件 RAID 陣列可以在 option ROM 裡設置或者操作系統安裝完成後另行安裝配套軟件來設置。這種設置是獨立於 Linux 內核的:內核並不能看到單獨的每塊硬盤。
FakeRAID
這種類型的 RAID 應當稱為 BIOS 或板載 RAID,卻常被錯誤地當做硬件 RAID 來宣傳。這種陣列由偽 RAID 控制器來管理,RAID 邏輯由 option ROM 或安裝了 EFI Sata 驅動程序的 固件本身(UEFI 情況下)來完成,但並不是實現了 所有 RAID 功能的完整硬件 RAID 控制器。因此,這種 RAID 有時被稱為 FakeRAID。dmraid 會被用於處理這種控制器。這裡列出一些 FakeRAID 控制器:Intel Rapid Storage,JMicron JMB36x RAID ROM,AMD RAID,ASMedia 106x 和 NVIDIA MediaShield。

我正在使用哪一種 RAID?[編輯 | 編輯原始碼]

由於軟件 RAID 是由用戶部署的,因此用戶很容易就知道 RAID 的類型。

但是,辨別 FakeRAID 和真正的硬件 RAID 是很困難的。如上所述,製造商經常錯誤地混淆這兩種類型的 RAID,還可能進行虛假宣傳。這種情況下應該採取的最好方式是運行 lspci 命令並在輸出信息中找到你的 RAID 控制器,然後根據這些信息進行更進一步的搜索。硬件 RAID 控制器會在這一列表中出現,但 FakeRAID 不會。同時,真正的硬件 RAID 控制器通常價格很高,如果這個系統是自行組裝的,那麼很可能安裝一個硬件 RAID 會使電腦的價格顯著提高。

安裝[編輯 | 編輯原始碼]

安裝 mdadmmdadm 用於管理在純塊設備上建立起來的純軟件 RAID:底層硬件不提供任何 RAID 邏輯,只是一些磁盤而已。mdadm 可以在任何塊設備集合上工作,甚至是那些非常規的設備。比如,你可以用一堆 U 盤來建立 RAID 陣列。

準備設備[編輯 | 編輯原始碼]

警告: 這些步驟會擦除指定設備上的所有數據,輸入命令請小心!

如果設備是舊設備重用或剛從一個現有的陣列上拆下來,請擦除所有舊的 RAID 配置信息:

 # mdadm --misc --zero-superblock /dev/drive

或者是刪除設備上的某個特定的分區:

 # mdadm --misc --zero-superblock /dev/partition
注意:
  • 清除一個分區的 superblock 不會影響到磁盤上的其他分區。
  • 考慮到 RAID 本身的功能特點,在運行中的磁盤陣列中完全地 安全擦除磁盤 是很困難的。請在創建陣列前考慮要不要安全擦除磁盤。
  • You can do the whole disk preparation procedure from a GUI with blivet-guiAUR.

對磁盤進行分區[編輯 | 編輯原始碼]

強烈推薦對用於陣列的硬盤進行分區。考慮到大多數 RAID 用戶會用到超過 2 TiB 的硬盤,因此推薦並要求使用 GPT。參閱 Partitioning 獲取關於磁盤分區的更多信息以及可供使用的 分區工具

注意: 也可以在裸磁盤(沒有分區的磁盤)上直接創建 RAID,但不推薦這麼做,因為這樣可能會導致更換損壞硬盤時出現問題
注意: 當更換 RAID 中的某塊損壞的硬盤時,新硬盤的大小必須恰好等於或大於損壞的硬盤,否則無法完成陣列重建過程。即使是同一廠商相同型號的硬盤也可能有容量上的細微差別。通過在磁盤末尾保留一些未分配的空間可以消除磁盤容量上的細微差異,這樣可以使替代磁盤的型號選擇更加容易。因此,最好在磁盤末尾留出大約 100 MiB 的未分配空間。

GUID 分區表[編輯 | 編輯原始碼]

  • 創建分區以後,這些分區的 類型標識符 (GUID) 應該是 A19D880F-05FC-4D3B-A006-743F0F84911E(在 fdisk 裡將分區類型改為 Linux RAID 或在 gdisk 裡改為 FD00 可以給所選分區分配這個標識符)。
  • 如果使用了一個更大的磁盤陣列,可以考慮分配 文件系統標籤[損壞的鏈接:無效的章節]分區標籤[損壞的鏈接:無效的章節] 用於以後區分每塊單獨的硬盤。
  • 建議在每個設備上創建大小相同的分區。

主引導記錄 (MBR)[編輯 | 編輯原始碼]

對於在使用 MBR 的硬盤上創建分區的用戶,可用的 分區類型 ID 包括:

  • 0xDA:無文件系統(fdisk 中稱為 Non-FS data)。這是推薦用於 Arch Linux 上 RAID 陣列的 mdadm 分區類型。
  • 0xFD:自動檢測的 RAID(fdisk 中稱為 Linux RAID autodetect)。This partition type should only be used if RAID autodetection is desireable (non-initramfs system, old mdadm metadata format).

更多信息請參閱 Linux Raid Wiki:Partition Types

創建陣列[編輯 | 編輯原始碼]

使用 mdadm 來創建陣列。參閱 mdadm(8) 獲取支持的選項。下面列出部分使用範例。

警告: 不要簡單地複製/粘貼下面的示例,確保你已經使用正確的選項和設備名稱替代了示例中相應的內容。
注意:
  • 如果有一個從 Syslinux 啟動的 RAID1 陣列,在 syslinux v4.07 中要求元數據值為 1.0,而不是默認的 1.2。
  • 當用 Arch 安裝鏡像 創建磁盤陣列時,請使用 --homehost=yourhostname 選項設置 主機名(或者 --homehost=any 選項無論在什麼主機上都用相同的主機名),否則主機名稱 archiso 會被寫入陣列的元數據中。
提示:要為 RAID 設備指定一個自定義的名稱,可以使用 --name=MyRAIDName 選項或將 RAID 設備路徑改為 /dev/md/MyRAIDName。Udev 會使用該名稱創建指向 /dev/md/ 內 RAID 陣列的符號鏈接。如果 homehost 與當前 主機名 匹配(或者 homehost 設為了 any)則鏈接將會是 /dev/md/name,如果 homehost 不匹配那麼鏈接將會是 /dev/md/homehost:name

下面這個例子展示了在 2 個設備上建立 RAID1 陣列:

# mdadm --create --verbose --level=1 --metadata=1.2 --raid-devices=2 /dev/md/MyRAID1Array /dev/sdb1 /dev/sdc1

下面這個例子展示了使用 4 塊磁盤作為工作 (active) 磁盤,1 塊作為備用 (spare) 磁盤建立 RAID5 陣列:

# mdadm --create --verbose --level=5 --metadata=1.2 --chunk=256 --raid-devices=4 /dev/md/MyRAID5Array /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1 --spare-devices=1 /dev/sdf1
提示:--chunk 可用於修改默認的區塊大小。更多關於優化區塊大小的內容請參閱 Chunks: the hidden key to RAID performance

下面這個例子展示了在 2 個設備上建立遠 2 布局的 RAID10 陣列 (RAID10, far2):

# mdadm --create --verbose --level=10 --metadata=1.2 --chunk=512 --raid-devices=2 --layout=f2 /dev/md/MyRAID10Array /dev/sdb1 /dev/sdc1

這樣,陣列就會在虛擬設備 /dev/mdX 下建立起來,容量已經合併且可以使用(但處於降級模式)。mdadm 在後台同步數據時你已經可以直接開始使用這個陣列了。儲存奇偶校驗位可能要花很長時間,可以用這個命令查看進度:

$ cat /proc/mdstat

更新配置文件[編輯 | 編輯原始碼]

默認情況下,mdadm.conf 中的大部分內容都被注釋掉了,它應該只包含如下內容:

/etc/mdadm.conf
...
DEVICE partitions
...

這一指令告訴 mdadm 檢查由 /proc/partitions 引用的所有設備並儘可能將其中的陣列組合起來。如果你確實想啟動所有可用的陣列並且確信不存在意料之外的超級塊(比如安裝了新的存儲設備),那麼這樣的配置就很好。當然有一種更精準的控制方法,就是顯式地將陣列添加到 /etc/mdadm.conf

# mdadm --detail --scan >> /etc/mdadm.conf

這將會在配置中添加類似這樣的內容:

/etc/mdadm.conf
...
DEVICE partitions
...
ARRAY /dev/md/MyRAID1Array metadata=1.2 name=pine:MyRAID1Array UUID=27664f0d:111e493d:4d810213:9f291abe

這也會使 mdadm 檢查由 /proc/partitions 引用的設備。但是,只有超級塊的 UUID 是 27664… 的設備才會被組合成激活的陣列。

更多信息請參閱 mdadm.conf(5)

組合成磁盤陣列[編輯 | 編輯原始碼]

更新配置文件後即可用 mdadm 組合磁盤陣列:

# mdadm --assemble --scan

格式化 RAID 上的文件系統[編輯 | 編輯原始碼]

提示:To create multiple volumes inside a RAID array, follow the LVM on software RAID article.

現在磁盤陣列已經可以像普通分區一樣被格式化成某個 文件系統,但要記住:

計算 stride(跨度大小)和 stripe width(帶區寬度)[編輯 | 編輯原始碼]

優化文件系統結構以適應底層 RAID 結構需要 2 個參數:stridestripe width。它們對應於 RAID 的 chunk size(區塊大小) 、文件系統的 block size(塊大小) 以及 "data disks"(數據盤)的數量

Chunk size(RAID 區塊大小)是 RAID 陣列的一個屬性,在陣列創建時就已經定好了。目前 mdadm 默認該值為 512 KiB。這個參數可以用 mdadm 讀取:

# mdadm --detail /dev/mdX | grep 'Chunk Size'

Block size(塊大小)是文件系統的一個屬性,在文件系統創建時就已經定好了。在大部分文件系統上(包括 ext4)默認是 4 KiB。更多關於當前系統 ext4 的信息可以查看 /etc/mke2fs.conf 文件。

"Data disks"(數據盤)的數量指的是陣列能夠完全重建數據所要求的最少可用設備。例如,對於 N 個設備的 raid0 來說這個數量是 N,對於 raid5 來說是 N-1。

當你獲得了這三個參數時,stride 和 stripe width 可以用下列公式來計算:

stride = chunk size / block size
stripe width = number of data disks * stride
範例 1. RAID0[編輯 | 編輯原始碼]

本範例使用了正確的 stride 和 stripe width 將合併後的分區格式化成了 ext4:

  • 假設這一 RAID0 陣列是由 2 塊物理硬盤組成的。
  • Chunk size(RAID 區塊大小)是 512 KiB。
  • Block size(文件系統塊大小)是 4 KiB。

因為 stride = chunk size / block size。在這個例子中,stride 大小是 512/4 = 128。

因為 stripe width = # of physical data disks * stride。在這個例子中,stripe width 的大小是 2*128 = 256。

 # mkfs.ext4 -v -L myarray -b 4096 -E stride=128,stripe-width=256 /dev/md0
範例 2. RAID5[編輯 | 編輯原始碼]

本範例使用了正確的 stride 和 stripe width 將合併後的分區格式化成了 ext4:

  • 假設這一 RAID5 陣列由 4 塊物理硬盤組成,3 塊是數據盤,1 塊是奇偶校驗盤。
  • Chunk size(RAID 區塊大小)是 512 KiB。
  • Block size(文件系統塊大小)是 4 KiB。

因為 stride = chunk size / block size。在這個例子中,stride 大小是 512/4 = 128。

因為 stripe width = # of physical data disks * stride。在這個例子中,stripe width 的大小是 3*128 = 384.

 # mkfs.ext4 -v -L myarray -b 4096 -E stride=128,stripe-width=384 /dev/md0

關於 stride 和 stripe width 的更多信息,請參閱:RAID Math

範例 3. RAID10,far2[編輯 | 編輯原始碼]

本範例使用了正確的 stride 和 stripe width 將合併後的分區格式化成了 ext4:

  • 假設這一 RAID10 陣列由 2 塊物理硬盤組成。考慮到遠 2 布局的 RAID10 的自身特性,兩塊硬盤都是數據盤。
  • Chunk size(RAID 區塊大小)是 512 KiB。
  • Block size(文件系統塊大小)是 4 KiB。

因為 stride = chunk size / block size。 在這個例子中,stride 大小是 512/4 = 128。

因為 stripe width = # of physical data disks * stride。 在這個例子中,stripe width 的大小是 2*128 = 256。

 # mkfs.ext4 -v -L myarray -b 4096 -E stride=128,stripe-width=256 /dev/md0

在 Live CD 中掛載 RAID[編輯 | 編輯原始碼]

如果你需要在 Live CD 中掛載 RAID 分區,用這個命令:

 # mdadm --assemble /dev/mdnumber /dev/disk1 /dev/disk2 /dev/disk3 /dev/disk4

如果缺一塊盤的 RAID 1 被錯誤地識別為了 RAID 1(參照 mdadm --detail /dev/mdnumber)並報告為非活動狀態(參照 cat /proc/mdstat),需要先停止磁盤陣列:

 # mdadm --stop /dev/mdnumber

在 RAID 上安裝 Arch Linux[編輯 | 編輯原始碼]

注意: 本節僅適用於根文件系統在磁盤陣列上的情況。如果你的磁盤陣列上只是一個數據分區,那麼可以跳過本節。

你應該在安裝過程中的 分區格式化 步驟之間創建 RAID 陣列。這將會把一個位於 RAID 陣列上的分區格式化成根文件系統,而不是直接格式化一個分區。 按照 #安裝 一節的步驟創建 RAID 陣列。,然後繼續安裝過程,直到 pacstrap 步驟完成。 當使用 UEFI 啟動 時,還需要閱讀 EFI system partition#軟件 RAID1 上的 ESP[損壞的鏈接:無效的章節]

更新配置文件[編輯 | 編輯原始碼]

注意: 這些操作應該在 chroot 以外完成,因此要在文件路徑前加上 /mnt

在基本系統安裝完成以後,RAID 的默認配置文件 mdadm.conf 需要這樣來更新:

# mdadm --detail --scan >> /mnt/etc/mdadm.conf

在運行這個命令以後一定要用文本編輯器檢查 mdadm.conf 配置文件來確保它的內容看起來是合理的。

注意: 為防止系統啟動時 mdmonitor.service 啟動失敗(默認設為自動啟動),你需要取消 MAILADDR 的注釋,並且在 mdadm.conf 結尾留下可處理磁盤陣列出錯通知的郵件地址和/或應用程序。參閱 #啟用事件郵件通知

現在繼續安裝過程直到 Installation guide#Initramfs 步驟之前為止,然後按照下一節的步驟做。

配置 mkinitcpio[編輯 | 編輯原始碼]

注意: 這些操作應該在 chroot 時完成。


安裝 mdadm,並向 mkinitcpio.conf 中的 HOOKS 部分添加 mdadm_udev 來為初始化內存盤添加 mdadm 支持:

/etc/mkinitcpio.conf
...
 HOOKS=(base udev autodetect keyboard modconf block mdadm_udev filesystems fsck)
...

如果在一個 FakeRAID 陣列上使用 mdadm_udev 鈎子,建議在 BINARIES[損壞的鏈接:無效的章節] 列表中添加 mdmon

/etc/mkinitcpio.conf
...
BINARIES=(mdmon)
...

然後 重新生成初始化內存盤

注意: Every time when you make changes to /etc/mdadm.conf, the initramfs needs to be regenerated.

配置 boot loader[編輯 | 編輯原始碼]

Root device[編輯 | 編輯原始碼]

root 參數指向映射的磁盤,例如:

root=/dev/md/MyRAIDArray

如果按上述用內核設備節點來指定映射磁盤的方法之後,從軟件 RAID 分區啟動失敗了,那就用 持久化命名塊設備 中的某種方法來指定映射的磁盤,例如:

root=LABEL=Root_Label

參考 GRUB#RAID

RAID0 layout[編輯 | 編輯原始碼]

注意: This also affects existing mdraid RAID0 users that upgrade from an older version of the Linux kernel to 5.3.4 or newer.

Since version 5.3.4 of the Linux kernel, you need to explicitly tell the kernel which RAID0 layout should be used: RAID0_ORIG_LAYOUT (1) or RAID0_ALT_MULTIZONE_LAYOUT (2).[1] You can do this by providing the kernel parameter as follows:

raid0.default_layout=2

The correct value depends upon the kernel version that was used to create the raid array: use 1 if created using kernel 3.14 or earlier, use 2 if using a more recent version of the kernel. One way to check this is to look at the creation time of the raid array:

mdadm --detail /dev/md1
/dev/md1:
           Version : 1.2
     Creation Time : Thu Sep 24 10:17:41 2015
        Raid Level : raid0
        Array Size : 975859712 (930.65 GiB 999.28 GB)
      Raid Devices : 3
     Total Devices : 3
       Persistence : Superblock is persistent

       Update Time : Thu Sep 24 10:17:41 2015
             State : clean
    Active Devices : 3
   Working Devices : 3
    Failed Devices : 0
     Spare Devices : 0

        Chunk Size : 512K

Consistency Policy : none

              Name : archiso:root
              UUID : 028de718:20a81234:4db79a2c:e94fd560
            Events : 0

    Number   Major   Minor   RaidDevice State
       0     259        2        0      active sync   /dev/nvme0n1p1
       1     259        6        1      active sync   /dev/nvme2n1p1
       2     259        5        2      active sync   /dev/nvme1n1p2

Here we can see that this raid array was created on September 24, 2015. The release date of Linux Kernel 3.14 was March 30, 2014, and as such this raid array is most likely created using a multizone layout (2).

維護 RAID[編輯 | 編輯原始碼]

數據清掃 (Scrubbing)[編輯 | 編輯原始碼]

定期運行數據 清掃 (Scrubbing) 來檢查並修復錯誤是一種很好的做法。一次完整數據清掃可能會花費數個小時,具體取決於磁盤陣列的大小和配置。

啟動數據清掃:

# echo check > /sys/block/md0/md/sync_action

數據檢查操作會掃描驅動器來檢查壞扇區並自動修復它們。如果找到了包含損壞數據的好扇區(本扇區中的數據與另一塊硬盤中記錄本扇區應有的數據不符,例如奇偶校驗塊和另一塊數據塊相結合可以證明本數據塊是錯誤的),那就不動作,但記錄下這一事件(見下文)。這種「不動作」允許管理員自行檢查壞扇區中原本的數據和從冗餘數據中重建的數據,然後決定保留哪個。

與許多 mdadm 相關的任務/事項一樣,數據清掃的進度也可以通過查看 /proc/mdstat 文件來查詢。

例如:

$ cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4] [raid1]
md0 : active raid1 sdb1[0] sdc1[1]
      3906778112 blocks super 1.2 [2/2] [UU]
      [>....................]  check =  4.0% (158288320/3906778112) finish=386.5min speed=161604K/sec
      bitmap: 0/30 pages [0KB], 65536KB chunk

安全地停止當前的數據清掃操作:

# echo idle > /sys/block/md0/md/sync_action
注意: 如果在數據清掃暫停時重啟了系統,將繼續進行清掃。

數據清掃完成後,管理員可以檢查有多少數據塊(如果有的話)被標記為壞塊:

# cat /sys/block/md0/md/mismatch_cnt

關於數據清掃的一般說明[編輯 | 編輯原始碼]

注意: 用戶也可以 echo repair/sys/block/md0/md/sync_action 裡面,但是這是不明智的,因為一旦遇到數據不一致就被自動改寫為一致。危險之處在於我們實際並不知道奇偶校驗塊和數據塊哪個是對的(在 RAID1 中是不知道哪個數據塊是對的)。因此自動清掃操作能不能用正確數據替換錯誤數據取決於運氣。

以 root 身份設定一個 cron 任務來定期執行清掃是很好的。raid-checkAUR 會對此有所幫助。如果要用 systemd 定時器而不是 cron 來執行定期清掃,raid-check-systemdAUR 中包含了相同的腳本和配套的 systemd 定時器單元文件。

注意: 對於常規的大容量驅動器,清掃工作耗時大約 6 秒每 GB(即每 TB 大約需要 1 小時 45 分鐘),因此應合理確定 cron 任務或定時器的開始時間。

對清掃 RAID1 和 RAID10 的說明[編輯 | 編輯原始碼]

由於 RAID1 和 RAID10 本質上就是沒有數據緩衝的,所以即使陣列工作正常,它的不匹配計數仍然可能是個非零值。這些不匹配計數隻存在於正在寫入數據的區域,且它們不反映任何問題。但是,我們無法區分非零的不匹配計數到底代表正在寫入數據還是確實存在問題。這是造成 RAID1 和 RAID10 陣列誤報錯誤的根源。即使如此,仍然建議定期清掃以發現並糾正驅動器上可能出現的壞扇區。

從陣列中移除設備[編輯 | 編輯原始碼]

要從陣列中移除一個塊設備,先將這個設備標記為 faulty(故障):

 # mdadm --fail /dev/md0 /dev/failing_array_member

現在從陣列中移除這個設備:

 # mdadm --remove /dev/md0 /dev/failing_array_member

If the device has not failed entirely, but you would like to replace it, e.g. because it looks like it is dying, you can actually handle replacement more gracefully by first adding a new drive and then telling mdadm to replace it.

For example, with /dev/sdc1 as the new one and /dev/sdb1 as the failing one:

# mdadm /dev/md0 --add /dev/sdc1
# mdadm /dev/md0 --replace /dev/sdb1 --with /dev/sdc1

The --with /dev/sdc1 part is optional, but more explicit. See [2] for more details.

永久移除設備(比如想把一個設備拿出來單獨使用): 先使用上述兩個命令,然後:

# mdadm --zero-superblock /dev/failing_array_member
警告:
  • 不要在 RAID0 陣列或者其他線性存放數據的陣列中進行這個操作!否則數據會丟失!
  • 重新使用已經移除的硬盤卻不清除它的超級塊將會導致下次啟動時丟失所有數據。(因為 mdadm 將會把它當做磁盤陣列的一部分來使用)。

停止使用某個陣列:

  1. 卸載 (umount) 目標陣列
  2. 用這個命令停止磁盤陣列運行:mdadm --stop /dev/md0
  3. 將本節開頭的三個命令在每塊硬盤上都運行一遍。
  4. /etc/mdadm.conf 中的相關行移除。

向陣列中添加設備[編輯 | 編輯原始碼]

可以在系統正在運行且設備已經掛載的情況下使用 mdadm 添加新設備。 按照前文所述的方法,使用現有陣列中相同的布局對新設備進行分區。

如果 RAID 陣列尚未組合,先組合它們:

# mdadm --assemble /dev/md0 /dev/sda1 /dev/sdb1

向陣列中添加新設備:

# mdadm --add /dev/md0 /dev/sdc1

這一步 mdadm 不會花費很長時間。

根據不同的 RAID 類型(比如 RAID1),mdadm 可能會把部分設備添加為備用設備,而不在這些設備上存放數據。可以使用 --grow 加上 --raid-devices 選項來增加 RAID 利用的磁盤數量。例如,將一個陣列增加至四塊硬盤:

# mdadm --grow /dev/md0 --raid-devices=4

可以這樣檢查進度:

# cat /proc/mdstat

用這個命令檢查已經添加的設備:

# mdadm --misc --detail /dev/md0
注意: 對於 RAID0 設備可能會收到以下錯誤信息:
mdadm: add new device failed for /dev/sdc1 as 2: Invalid argument

這是由於上述命令會將新磁盤添加為 "spare"(備用)盤,但是 RAID0 中不存在備用盤。如果想往 RAID0 陣列中添加磁盤,你需要同時使用 "grow" 和 "add" 參數。如下所示:

# mdadm --grow /dev/md0 --raid-devices=3 --add /dev/sdc1

增大 RAID 卷的大小[編輯 | 編輯原始碼]

如果給陣列安裝了更大的磁盤,或者增大了分區大小,可能就需要增大 RAID 卷的大小以適應更大的可用空間。這一過程可用首先按照上文中關於更換磁盤的步驟來做。當 RAID 卷在更大的磁盤上重建完成後,這個卷需要 "grow" 來填充多出來的空間。

# mdadm --grow /dev/md0 --size=max

接着,在 RAID 卷 /dev/md0 上的現有分區可能需要調整大小。參閱 Partitioning 獲取更多信息。最後,上述分區上的文件系統也需要重新調整大小。如果用 gparted 來完成分區操作,這些都會自動完成。如果用的是其他工具,請手動卸載 (unmount) 文件系統並調整其大小。

# umount /storage
# fsck.ext4 -f /dev/md0p1
# resize2fs /dev/md0p1

修改同步速度限制[編輯 | 編輯原始碼]

同步工作需要一定的時間。如果本機不需要完成其他任務,可以提高速度限制值。

# cat /proc/mdstat
 Personalities : [raid10]
 md127 : active raid10 sdd1[3] sdc1[2] sdb1[1] sda1[0]
     31251490816 blocks super 1.2 512K chunks 2 far-copies [4/4] [UUUU]
     [=>...................]  resync =  5.2% (1629533760/31251490816) finish=2071.7min speed=238293K/sec
     bitmap: 221/233 pages [884KB], 65536KB chunk

In the above example, it would seem the max speed is limited to approximately 238 M/sec.

查看當前速度限制:

# sysctl dev.raid.speed_limit_min
dev.raid.speed_limit_min = 1000
# sysctl dev.raid.speed_limit_max
dev.raid.speed_limit_max = 200000

Set a new maximum speed of raid resyncing operations using sysctl:

# sysctl -w dev.raid.speed_limit_min=600000
# sysctl -w dev.raid.speed_limit_max=600000

然後查看同步速度和預計完成時間:

# cat /proc/mdstat
 Personalities : [raid10] 
 md127 : active raid10 sdd1[3] sdc1[2] sdb1[1] sda1[0]
     31251490816 blocks super 1.2 512K chunks 2 far-copies [4/4] [UUUU]
     [=>...................]  resync =  5.3% (1657016448/31251490816) finish=1234.9min speed=399407K/sec
     bitmap: 221/233 pages [884KB], 65536KB chunk

RAID5 performance[編輯 | 編輯原始碼]

To improve RAID5 performance for fast storage (e.g. NVMe), increase /sys/block/mdx/md/group_thread_cnt to more threads. For example, to use 8 threads to operate on a RAID5 device:

# echo 8 > /sys/block/md0/md/group_thread_cnt

See git kernel commit 851c30c9badf.

Update RAID superblock[編輯 | 編輯原始碼]

To update the RAID superblock, you need to first unmount the array and then stop the array with the following command:

# mdadm --stop /dev/md0

Then you can update certain parameters by reassembling the array. For example, to update the homehost:

# mdadm --assemble --update=homehost --homehost=NAS /dev/md0 /dev/sda1 /dev/sdb1

See the arguments of --update for details.

監視運行情況[編輯 | 編輯原始碼]

可以顯示當前 RAID 設備狀態的一行簡單命令:

# awk '/^md/ {printf "%s: ", $1}; /blocks/ {print $NF}' </proc/mdstat
md1: [UU]
md0: [UU]

用 watch 監視 mdstat[編輯 | 編輯原始碼]

# watch -t 'cat /proc/mdstat'

或者最好用 tmux

# tmux split-window -l 12 "watch -t 'cat /proc/mdstat'"

用 iotop 追蹤 IO[編輯 | 編輯原始碼]

iotop 可以顯示各個進程的輸入輸出狀態。請用這個命令來查看 RAID 線程的輸入輸出。

 # iotop -a $(sed 's/^/-p /g' <<<`pgrep "_raid|_resync|jbd2"`)

用 iostat 追蹤 IO[編輯 | 編輯原始碼]

sysstat 包中的 iostat 實用程序可以顯示各個設備和分區的輸入輸出統計。

# iostat -dmy 1 /dev/md0
# iostat -dmy 1 # all

啟用事件郵件通知[編輯 | 編輯原始碼]

mdadm 提供了名為 mdmonitor.servicesystemd 服務,可幫助監控 RAID 陣列的健康度,並在出現問題時通過郵件通知你。

這個服務較為特殊,它無法用通常的方法來激活;mdadm 按下面的步驟為通知配置郵件地址後,它才會在系統啟動階段組裝陣列時,通過 udev 激活該服務。

警告: 郵件地址配置錯誤會導致監控服務啟動靜默失敗。
注意: 在發送郵件前,需要有一個配置好的郵件傳輸代理

通過編輯 /etc/mdadm.conf 並配置郵件地址來啟用該功能:MAILADDR user@domain

接下來,通過如下命令來驗證功能是否正常:

# mdadm --monitor --scan --oneshot --test

如果測試成功並郵件正常送達,則配置完成;在下次陣列完成組裝時,mdmonitor.service 將開始監控陣列錯誤。

故障排除[編輯 | 編輯原始碼]

如果你在重啟計算機時遇到類似 "invalid raid superblock magic" 的錯誤,並且除了已經配置好的硬盤外又接了其他硬盤,請檢查硬盤順序是不是正確的。在安裝 RAID 時,硬盤編號可能是 hdd、hde 和 hdf,但是重啟後它們的編號可能變成了 hda、hdb 和 hdc。請相應地調整你的內核參數。這種情況經常發生。

Error: "kernel: ataX.00: revalidation failed"[編輯 | 編輯原始碼]

如果你突然(在重啟、修改 BIOS 設置後)遇到類似錯誤信息:

Feb  9 08:15:46 hostserver kernel: ata8.00: revalidation failed (errno=-5)

這並不意味着設備已經損壞。儘管你可能會在網上看到一些講內核崩潰的鏈接指向最壞的結果,但總而言之,並不是內核崩潰。可能你不知怎麼的在 BIOS 裡或內核參數裡修改了 APIC 或 ACPI 設置。把它改回來就好了。通常關閉 APIC 和/或 ACPI 就好了。

磁盤陣列以只讀模式啟動[編輯 | 編輯原始碼]

當由 md 啟動磁盤陣列時,超級塊將被改寫,數據同步可能已經開始了。要以只讀模式啟動,可以向內核模塊 md_mod 傳遞參數 start_ro。設置了這個參數以後,新的磁盤陣列進入 'auto-ro' 模式,該模式停止了所有內部讀寫操作(更新超級塊、再同步、數據恢復),並且會在第一個寫入請求到來時自動切換至 'rw' (讀寫)模式。

注意: 在第一個寫入請求到來前使用 mdadm --readonly 命令可以將陣列設置為真正的 'ro' (只讀)模式,還可以用 mdadm --readwrite 命令直接開始再同步而不用等待寫入請求。

要在啟動時設置該參數,在內核啟動參數中添加 md_mod.start_ro=1

或者通過 內核模塊#使用 /etc/modprobe.d/中的文件 在模塊加載時傳遞該參數,也可以直接從 /sys/ 傳遞:

# echo 1 > /sys/module/md_mod/parameters/start_ro

在損壞或缺失磁盤的情況下恢復 RAID[編輯 | 編輯原始碼]

當磁盤陣列中的一個驅動器由於任何原因損壞時,也可能會發生上述錯誤。如果在缺失一塊硬盤的情況下你仍需要強制啟動磁盤陣列,輸入以下命令(根據實際修改):

# mdadm --manage /dev/md0 --run

現在你應該可以用類似下面的命令來掛載它(如果在 fstab 裡有它的話):

# mount /dev/md0

現在磁盤陣列應該已經工作並且可以使用,但仍舊是缺一塊盤的狀態。因此需要按照上文 #準備設備 所述再添加一個磁盤分區,然後就可以將新磁盤分區加入到磁盤陣列中:

# mdadm --manage --add /dev/md0 /dev/sdd1

如果輸入:

# cat /proc/mdstat

你就能看到磁盤陣列已經激活並正在重建。

你可能還需要更新你的配置文件(參閱:#更新配置文件)。

基準測試[編輯 | 編輯原始碼]

用於 RAID 基準測試的工具有很多種。不同 RAID 最顯著的不同是多個線程在讀取 RAID 卷時的速度提升程度。

bonnie++ 測試對一個或多個數據庫類型文件的讀寫,以及對小文件的創建、讀取、刪除,這樣可以模擬 Squid、INN 和 Maildir format e-mail 等程序的文件讀寫。其附帶的 ZCAV 程序可以測試硬盤不同區域的性能,且不用向硬盤寫入任何數據。

不應該 使用 hdparm 來對 RAID 進行基準測試,因為它多次返回的結果會非常不一致。

參考資料[編輯 | 編輯原始碼]

mailing list

mdadm

Forum threads