---
title: "RAID и надёжность хранения"
description: "Один диск — это ограниченная скорость (HDD даёт 100–200 случайных операций в секунду) и единая точка отказа. Производители указывают для дисков наработку на отказ (MTBF) в 1–2,5…"
canonical: https://graphlms.ru/os/book/raid
course: "Операционные системы"
updated: 2026-10-12
lang: ru
publisher: GraphLMS
---

# RAID и надёжность хранения

> Источник: https://graphlms.ru/os/book/raid — курс «Операционные системы», GraphLMS.

## Зачем объединять диски

Один диск — это ограниченная скорость ([HDD](/os/book/hdd) даёт 100–200
случайных операций в секунду) и единая точка отказа. Производители указывают
для дисков наработку на отказ (MTBF) в 1–2,5 млн часов, что соответствует
годовой частоте отказов меньше 1%. Реальная статистика больших парков
(например, ежегодные отчёты Backblaze) — порядка 1–2% в год. На ноутбуке это
«однажды не повезёт». В стойке из 500
дисков это пять-десять отказов в год, то есть отказ диска — плановое событие, а
не авария.

**RAID** (redundant array of independent disks, избыточный массив независимых
дисков) собирает несколько физических дисков в одно логическое устройство так,
чтобы получить скорость, устойчивость к отказу или и то и другое. Файловая
система (см. [реализацию ФС](/os/book/fs-implementation)) видит один большой
диск и не знает, что внутри их несколько.

```text
            ┌─────────────────────────────────────┐
   ФС       │  видит один диск                     │
            └───────────────────┬─────────────────┘
                                │
                      ┌─────────┴─────────┐
                      │   слой RAID        │  режет, копирует, считает чётность
                      └─┬──────┬──────┬───┬┘
                        ▼      ▼      ▼   ▼
                     [disk0][disk1][disk2][disk3]
```

Слой RAID бывает аппаратным (контроллер с батарейкой или конденсатором для
кэша) и программным: `mdadm` в Linux, RAID-Z в ZFS, LVM.

Каждый уровень RAID оценивают по трём вопросам:

- **полезная ёмкость** — сколько места доступно под данные;
- **сколько отказов переживёт** массив без потери данных;
- **скорость** чтения и записи по сравнению с одним диском.

Дальше N — число дисков, S — ёмкость одного диска.

## RAID 0 — чередование

**Striping** (чередование, «нарезка полосами»): данные режутся на куски (обычно
64–512 КБ, это размер страйп-юнита) и раскладываются по дискам по кругу.

```text
   RAID 0, 4 диска:

           disk0   disk1   disk2   disk3
   полоса0  A       B       C       D
   полоса1  E       F       G       H
   полоса2  I       J       K       L
```

Чтение A..D идёт со всех четырёх дисков одновременно, случайные запросы
расходятся по разным дискам. Скорость растёт примерно в N раз.

Избыточности нет никакой. Умер любой диск — пропала каждая четвёртая полоса
каждого файла, и восстановить её не из чего. Хуже того, вероятность потерять
массив в N раз выше, чем один диск: умереть может любой из четырёх.

- Полезная ёмкость: N·S.
- Переживает отказов: 0.
- Скорость: ~N× на чтение и запись.

Где уместен: временные данные, кэши, которые легко пересобрать, scratch-диски
для вычислений.

## RAID 1 — зеркало

**Mirroring** (зеркалирование): каждый блок пишется на все диски массива. Обычно
зеркало делают из двух дисков, но `mdadm` позволяет и три, и четыре копии.

```text
   RAID 1, 2 диска:

           disk0   disk1
            A   ═══  A
            B   ═══  B
            C   ═══  C

   disk0 умер → всё читается с disk1
```

После замены умершего диска массив копирует на новый все данные с живого — это
**rebuild** (ресинхронизация).

- Полезная ёмкость: S (объём одного диска, сколько бы копий ни было). Для двух
  дисков это 50%.
- Переживает отказов: N − 1 (данные живы, пока цела хотя бы одна копия).
- Скорость: чтение до N× (читать можно с любой копии), запись ~1× (пишем на
  все диски и ждём самый медленный).

## RAID 5 — чётность

Зеркало надёжно, но тратит половину ёмкости. RAID 5 обходится одним «лишним»
блоком на полосу. Это **блок чётности** (parity), который считают побитовым XOR
(«исключающее ИЛИ») всех блоков данных полосы.

У XOR есть свойство, на котором всё держится: `x ^ x = 0` и `x ^ 0 = x`. Поэтому
если `P = A ^ B ^ C`, то `A ^ C ^ P = A ^ C ^ A ^ B ^ C = B`. Любой один
потерянный блок восстанавливается XOR-ом всех остальных.

```text
   A = 1011
   B = 0110
   C = 1100
   P = A ^ B ^ C = 0001

   потеряли B:  A ^ C ^ P = 1011 ^ 1100 ^ 0001 = 0110 = B
```

То же самое на Go, с байтами вместо битов:

```go play
package main

import "fmt"

// parity считает XOR всех блоков страйпа.
func parity(blocks ...[]byte) []byte {
	p := make([]byte, len(blocks[0]))
	for _, b := range blocks {
		for i := range b {
			p[i] ^= b[i]
		}
	}
	return p
}

func main() {
	// Страйп из трёх блоков данных по 4 байта (в жизни — по 64 КБ и больше).
	d0 := []byte("GoOS")
	d1 := []byte("RAID")
	d2 := []byte("5!!!")
	p := parity(d0, d1, d2)
	fmt.Printf("parity: % x\n", p)

	// Диск с d1 умер. Восстанавливаем его блок из уцелевших и чётности.
	restored := parity(d0, d2, p)
	fmt.Printf("восстановлено: %q\n", restored)

	// Запись в один блок: новая чётность по дельте, без чтения остальных дисков.
	newD0 := []byte("gOos")
	newP := parity(p, d0, newD0) // P' = P xor старое xor новое
	fmt.Println("дельта совпадает с пересчётом:",
		string(newP) == string(parity(newD0, d1, d2)))
}
```

```text
parity: 20 0f 27 36
восстановлено: "RAID"
дельта совпадает с пересчётом: true
```

Чётность в RAID 5 не лежит на одном выделенном диске, а переходит с диска на
диск от полосы к полосе. Иначе каждая запись обновляла бы чётность на одном и том
же диске, и он стал бы узким местом (так был устроен RAID 4).

```text
   RAID 5, 4 диска (3 блока данных + 1 чётность в каждой полосе):

           disk0   disk1   disk2   disk3
   полоса0  A0      A1      A2      Pa
   полоса1  B0      B1      Pb      B2
   полоса2  C0      Pc      C1      C2
   полоса3  Pd      D0      D1      D2
```

Если умер, скажем, disk2, массив продолжает работать в **деградированном**
режиме: каждое чтение блока с disk2 вычисляется на лету XOR-ом трёх других
дисков. После замены диска контроллер проходит все полосы и заполняет новый
диск: A2 = A0 ^ A1 ^ Pa, затем Pb = B0 ^ B1 ^ B2 и так далее.

- Полезная ёмкость: (N − 1)·S.
- Переживает отказов: 1.
- Чтение: последовательное ~(N − 1)× (блоки чётности пропускаются), случайное
  до N× (чётность разбросана, работают все диски).
- Запись мелкими блоками: медленно, разбираем ниже.

### Цена мелкой записи

Изменить один блок в RAID 5 просто так нельзя: чётность полосы зависит от всех
её блоков. Перечитывать всю полосу не нужно — как показал пример выше, новую
чётность можно получить по дельте:

```text
   хотим заменить A0 на A0'

   1. прочитать старый A0
   2. прочитать старую Pa
   3. Pa' = Pa ^ A0 ^ A0'
   4. записать A0'
   5. записать Pa'

   одна логическая запись = 2 чтения + 2 записи = 4 операции с дисками
```

Это называют **штрафом на мелкую запись** (small write penalty). Для базы данных
с потоком случайных записей RAID 5 на HDD работает примерно вчетверо медленнее,
чем те же диски в RAID 0. Крупная запись целой полосы штрафа не платит: все
блоки новые, чётность считается из них, ничего читать не надо.

### Дыра записи

Шаги 4 и 5 — две независимые записи на разные диски. Если между ними пропадёт
питание, данные в полосе уже новые, а чётность ещё старая. Пока все диски живы,
этого никто не заметит. Но если потом умрёт диск, его блоки восстановят по
неверной чётности, и получится мусор. Это **дыра записи** (write hole).

Лечат её так же, как файловые системы лечат свою несогласованность после сбоя
(см. [журналирование](/os/book/journaling)): аппаратный контроллер держит
незавершённые записи в кэше с батарейкой, `mdadm` умеет вести журнал записей
на отдельном устройстве, а RAID-Z в ZFS никогда не перезаписывает полосу на
месте — пишет новую целиком и атомарно переключает указатель (copy-on-write).

## RAID 6 — две чётности

RAID 6 добавляет вторую, независимую контрольную сумму (её считают не простым
XOR, а кодом Рида — Соломона). Массив переживает отказ любых двух дисков.

- Полезная ёмкость: (N − 2)·S.
- Переживает отказов: 2.
- Мелкая запись ещё дороже: 6 операций (прочитать блок и две чётности, записать
  все три).

Зачем вторая чётность, если диски отказывают редко? Из-за времени
восстановления. Диск на 16 ТБ, переписываемый со скоростью 200 МБ/с, заполняется
за 16·10¹² / 200·10⁶ = 80 000 секунд, то есть больше 22 часов, а под рабочей
нагрузкой — несколько суток. Всё это время RAID 5 работает без запаса: второй
отказ означает потерю массива. А нагрузка rebuild (полное чтение всех
оставшихся дисков) как раз повышает шанс, что откажет ещё один диск из той же
партии, или что на нём всплывёт нечитаемый сектор. Производители пишут для
потребительских дисков порядка одной неисправимой ошибки чтения на 10¹⁴ бит
(это около 12,5 ТБ), для серверных — на 10¹⁵. При rebuild массива из
нескольких 16-терабайтных дисков читаются десятки терабайт. Поэтому для
больших HDD RAID 5 сегодня считается рискованным, и берут RAID 6 или RAID 10.

## RAID 10 — зеркала, объединённые чередованием

**RAID 10** (он же 1+0): диски объединяют в зеркальные пары, а поверх пар
делают чередование.

```text
   RAID 10, 4 диска = 2 зеркала:

      зеркало M0          зеркало M1
    disk0   disk1       disk2   disk3
      A       A           B       B
      C       C           D       D
```

Скорость чередования, надёжность зеркала, никакой чётности и никакого штрафа
на мелкую запись. Rebuild простой: скопировать один диск с его пары.

- Полезная ёмкость: N·S / 2.
- Переживает отказов: гарантированно 1. Два — если они в разных зеркалах
  (disk0 и disk2), а если умерли оба диска одной пары (disk0 и disk1), данные
  потеряны.
- Скорость: чтение ~N×, запись ~N/2× (каждый блок пишется дважды).

Это частый выбор под базы данных со случайной записью.

## Сводная таблица

| Уровень | Метод | Полезная ёмкость | Переживает отказов | Случайная запись | Когда |
|---|---|---|---|---|---|
| RAID 0 | чередование | N·S | 0 | ~N× | временные данные |
| RAID 1 | зеркало | S | N − 1 | ~1× | загрузочные диски, малые объёмы |
| RAID 5 | чередование + чётность | (N − 1)·S | 1 | ~N/4× | чтение, архивы, небольшие диски |
| RAID 6 | две чётности | (N − 2)·S | 2 | ~N/6× | большие массивы HDD |
| RAID 10 | зеркала + чередование | N·S / 2 | 1 (до N/2, если в разных парах) | ~N/2× | базы данных |

## Считаем на пальцах

Четыре диска по 4 ТБ:

```text
   RAID 0:   4 × 4         = 16 ТБ   переживает 0
   RAID 1:   (все 4 — копии) = 4 ТБ   переживает 3
   RAID 5:   (4 − 1) × 4   = 12 ТБ   переживает 1
   RAID 6:   (4 − 2) × 4   =  8 ТБ   переживает 2
   RAID 10:  4 × 4 / 2     =  8 ТБ   переживает 1 (2, если из разных пар)
```

Функцию полезной ёмкости для разных уровней вы напишете в Go-задаче
[«RAID: полезная ёмкость»](/os/tasks/raid-capacity).

## RAID — не бэкап

RAID защищает от одной беды: физической смерти диска. От всего остального он не
спасает. `rm -rf` или `DROP TABLE` мгновенно применятся ко всем копиям. Баг в
приложении, который записал мусор, запишет его на все диски. Шифровальщик
зашифрует весь массив. Пожар в стойке уничтожит все диски сразу. Для этого
нужны бэкапы: отдельные копии во времени, в другом месте, желательно такие,
которые нельзя удалить с того же сервера.

## RAID в облаке

В облаке диск виртуальной машины (AWS EBS, GCP Persistent Disk) — это не
физический диск, а сетевое блочное хранилище, которое провайдер сам
реплицирует на несколько серверов внутри зоны доступности. Смерть физического
носителя скрыта от вас.

```text
   свой сервер:  [сервер] ── SATA/NVMe ── [физический диск]   умер → нужен RAID
   облако:       [VM] ── сеть ── [том EBS] ── репликация внутри зоны
```

Поэтому:

- **RAID 1/5/6 поверх облачных томов** обычно не нужен: избыточность уже есть
  внутри сервиса, вы заплатите за неё дважды и потеряете в скорости записи.
- **RAID 0 из нескольких томов** иногда делают ради IOPS и пропускной
  способности, если один том упирается в лимит. Сегодня чаще проще взять один
  том с нужными параметрами.
- **Облачный том тоже может отказать.** AWS указывает для gp2/gp3 годовую
  частоту отказов 0,1–0,2% (для io2 — на порядок ниже). Это в разы лучше
  физического диска, но не ноль, и от удаления тома или порчи данных репликация
  не спасает. Нужны снапшоты и бэкапы.
- **Локальные NVMe-диски инстанса** (instance store, local SSD) быстрые, но не
  реплицируются и пропадают при остановке машины. Здесь RAID снова имеет смысл,
  но чаще данные защищают репликацией на уровне приложения.

От потери целой зоны или региона RAID не спасает в принципе. Для этого
реплицируют на уровне базы или приложения: реплики PostgreSQL в другой зоне,
кворумная запись в etcd или Cassandra. RAID защищает от смерти диска,
репликация — от смерти сервера, стойки, зоны.

> Квиз по разделу: см. вопросы в конце документа или на https://graphlms.ru/os/book/raid

## Частые ошибки

- Считать RAID бэкапом.
- Думать, что RAID 1 из четырёх дисков даёт половину суммарной ёмкости: копий четыре, полезный объём — один диск.
- Ставить RAID 5 на большие HDD под нагрузку и не считать время rebuild.
- Собирать RAID 1 или 5 поверх облачных томов, которые и так реплицированы провайдером.
- Полагаться на облачный том без снапшотов: он тоже отказывает, хоть и редко.

## Проверьте себя

1. Как XOR восстанавливает потерянный блок?
2. Почему мелкая запись в RAID 5 стоит четыре операции, а запись целой полосы — нет?
3. Почему для RAID 5 на дисках по 16 ТБ главный риск — время восстановления?
4. Шесть дисков по 8 ТБ. Посчитайте полезную ёмкость и число переживаемых отказов для RAID 5, RAID 6 и RAID 10. Какой выбрать под PostgreSQL с интенсивной записью?

Ответы. (1) `x ^ x = 0`, поэтому XOR всех оставшихся блоков полосы и чётности даёт пропавший блок. (2) Для мелкой записи нужны старые данные и старая чётность (2 чтения) и запись новых данных и чётности (2 записи); при записи всей полосы чётность считается из новых блоков, читать нечего. (3) Rebuild идёт сутки и дольше, всё это время запаса нет, а полное чтение оставшихся дисков повышает шанс второго отказа или нечитаемого сектора. (4) RAID 5: 40 ТБ, 1 отказ. RAID 6: 32 ТБ, 2. RAID 10: 24 ТБ, гарантированно 1, до 3 при отказах в разных парах. Под интенсивную запись — RAID 10: нет штрафа на мелкую запись и быстрый rebuild.

## Что спрашивают на собесе

- **RAID 5 или RAID 10 под базу?** RAID 10: нет штрафа на мелкую запись (2
  операции вместо 4), быстрый и простой rebuild. RAID 5 экономит ёмкость, но
  медленно пишет мелкими блоками и рискован при rebuild больших дисков.
- **Как XOR восстанавливает данные?** P = A ^ B ^ C, потерянный B = A ^ C ^ P,
  потому что x ^ x = 0.
- **Что такое write hole?** Сбой между записью данных и записью чётности
  оставляет полосу несогласованной. Лечат журналом, кэшем с батарейкой,
  copy-on-write (RAID-Z).
- **Посчитайте полезную ёмкость** для N дисков по S: RAID 0 — N·S, RAID 1 — S,
  RAID 5 — (N − 1)·S, RAID 6 — (N − 2)·S, RAID 10 — N·S / 2.
- **Зачем RAID 6, если есть RAID 5?** Rebuild больших дисков идёт сутками, и
  второй отказ или нечитаемый сектор в это время губит RAID 5.
- **Нужен ли RAID в облаке?** Обычно нет: том реплицируется провайдером. Но
  снапшоты и бэкапы нужны, а от потери зоны спасает только репликация БД.
- **RAID — это бэкап?** Нет: удаление, порча и шифрование применятся ко всем
  копиям.

## Вопросы для самопроверки

**Квиз «RAID и надёжность»**

1. 5 дисков по 2 ТБ собрали в RAID 5. Сколько ТБ полезной ёмкости?
   - Ответ: 8
   - Пояснение: RAID 5: usable = (N-1)*S = (5-1)*2 = 8 ТБ. Эквивалент одного диска уходит под распределённую parity.
2. Какой уровень RAID не переживает ни одного отказа диска?
   - RAID 5
   - RAID 10
   - RAID 1
   - RAID 0 (верно)
   - Пояснение: RAID 0 — чистый striping без избыточности. Смерть любого диска уносит часть каждого файла, и весь массив теряется.
3. Что такое write penalty в RAID 5 при изменении одного блока?
   - Parity пересчитывается раз в сутки фоном
   - Запись блокирует чтение со всего массива
   - Запись просто медленнее на 10%
   - Нужно read-modify-write: 2 чтения и 2 записи на одну логическую запись (верно)
   - Пояснение: Чтобы обновить parity страйпа, контроллер читает старые данные и старую parity, считает новую через XOR и записывает данные и parity — 4 физических операции.
4. Почему поверх облачного диска (EBS/PD) обычно не делают RAID 1/5?
   - Облако запрещает RAID технически
   - Это слишком дорого по CPU
   - Облачный том уже реплицирован внутри зоны, избыточность дублировалась бы зря (верно)
   - RAID работает только на HDD, а в облаке SSD
   - Пояснение: Облачное блочное хранилище само хранит несколько копий и переживает смерть физического носителя прозрачно. RAID поверх — лишние деньги и записи.
5. Выберите верные утверждения про parity и восстановление. (несколько)
   - RAID — это полноценная замена бэкапу
   - RAID 6 хранит две parity и переживает два отказа (верно)
   - В RAID 10 два отказа переживаются только если диски из разных зеркал (верно)
   - Потерянный блок данных восстанавливается XOR остальных блоков и parity (верно)
   - Пояснение: XOR обратим, RAID 6 держит 2 отказа, в RAID 10 важно, чтобы умершие диски были в разных зеркалах. А RAID не бэкап: от rm -rf и логической порчи не спасает.
6. 8 дисков по 4 ТБ в RAID 10. Полезная ёмкость в ТБ?
   - Ответ: 16
   - Пояснение: RAID 10: usable = N*S/2 = 8*4/2 = 16 ТБ. Половина уходит на зеркальные копии.
