Введение: зачем нужна отказоустойчивость хранения данных
Потеря данных и простой сервисов обходятся дорого. Для интернет-магазина час недоступности означает упущенную выручку, для медицинской системы - риск для пациентов, для SaaS-платформы - отток клиентов. Отказоустойчивость хранения данных решает две задачи: сохранить информацию при сбое оборудования и обеспечить непрерывный доступ к ней.
В статье разберем четыре уровня защиты. Локальная избыточность на уровне RAID защищает от выхода из строя отдельных дисков. Файловые системы ZFS и Btrfs добавляют контрольные суммы и самовосстановление данных. Репликация master-slave и multi-master обеспечивает высокую доступность на уровне сервисов. Распределенные СУБД вроде CockroachDB дают глобальную отказоустойчивость с горизонтальным масштабированием.
Каждый раздел содержит пошаговые команды и конфигурации, проверенные на практике. В конце статьи - таблица критериев выбора технологии под конкретный сценарий.
Основы отказоустойчивости: RAID и его уровни
RAID (Redundant Array of Independent Disks) объединяет несколько физических дисков в один логический массив. Цель - избыточность данных или производительность. Основные уровни:
- RAID 0 - чередование без избыточности. Увеличивает скорость, но отказ любого диска уничтожает все данные. Для отказоустойчивости не подходит.
- RAID 1 - зеркалирование. Данные дублируются на два диска. Переживает отказ одного диска. Полезная емкость - 50%.
- RAID 5 - чередование с распределенной четностью. Переживает отказ одного диска. Минимум три диска. Полезная емкость - N-1.
- RAID 6 - как RAID 5, но с двумя блоками четности. Переживает отказ двух дисков. Минимум четыре диска.
- RAID 10 - зеркалирование поверх чередования. Высокая производительность и отказоустойчивость. Переживает отказ одного диска в каждой зеркальной паре. Полезная емкость - 50%.
Для серверов баз данных с интенсивной записью выбирают RAID 10. Для файловых хранилищ с большим объемом - RAID 6. RAID 5 допустим для небольших массивов из 3-4 дисков, где риск второго отказа во время восстановления минимален.
Программный RAID в Linux: настройка mdadm
Программный RAID в Linux реализуется через утилиту mdadm. Он не требует аппаратного контроллера и работает на любом сервере. Настройка RAID 1 из двух дисков /dev/sdb и /dev/sdc:
# Установка mdadm
apt install mdadm -y
# Создание массива RAID 1
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
# Проверка статуса
cat /proc/mdstat
# Создание файловой системы
mkfs.ext4 /dev/md0
# Добавление в fstab для автомонтирования
echo '/dev/md0 /mnt/storage ext4 defaults 0 2' >> /etc/fstab
# Сохранение конфигурации массива
mdadm --detail --scan >> /etc/mdadm/mdadm.conf
update-initramfs -uПеред созданием массива убедитесь, что на дисках нет данных. Команда mdadm --create перезаписывает метаданные и уничтожает существующую информацию. Замена отказавшего диска выполняется так:
# Пометить диск как отказавший
mdadm --manage /dev/md0 --fail /dev/sdb
# Удалить из массива
mdadm --manage /dev/md0 --remove /dev/sdb
# Добавить новый диск
mdadm --manage /dev/md0 --add /dev/sddПодробный разбор программных RAID-массивов с командами для RAID 5, 6 и 10 есть в руководстве по mdadm, ZFS и LVM.
Файловые системы нового поколения: ZFS и Btrfs
RAID защищает от отказа диска, но не от повреждения данных. Ошибки контроллера, сбои питания, деградация носителя могут записать неверные данные, и RAID честно размножит эту ошибку. ZFS и Btrfs решают проблему через контрольные суммы каждого блока. При чтении система сверяет данные с контрольной суммой и при расхождении автоматически восстанавливает корректную копию с другого диска.
ZFS - зрелая файловая система, разработанная Sun Microsystems. Она объединяет функции файловой системы и менеджера томов. Пул хранения (zpool) состоит из виртуальных устройств (vdev), каждое из которых может быть зеркалом, RAID-Z или отдельным диском. Снапшоты в ZFS почти мгновенны и занимают место только при изменении данных.
Btrfs - встроенная в Linux файловая система с аналогичными возможностями. Она поддерживает подтома, снапшоты, сжатие и встроенный RAID. Btrfs проще в настройке, но для критически важных продакшен-систем ZFS остается более предсказуемым выбором.
ZFS: создание пула и настройка репликации снапшотов
Создание зеркального пула из двух дисков:
# Установка ZFS
apt install zfsutils-linux -y
# Создание зеркального пула
zpool create tank mirror /dev/sdb /dev/sdc
# Создание файловой системы с включенным сжатием
zfs create tank/data
zfs set compression=lz4 tank/data
# Проверка статуса пула
zpool statusРепликация снапшотов позволяет переносить данные на другой сервер или в резервное хранилище:
# Создание снапшота
zfs snapshot tank/data@backup-2026-08-17
# Отправка снапшота на удаленный сервер
zfs send tank/data@backup-2026-08-17 | ssh backup-server zfs receive backup-pool/data
# Инкрементальная отправка следующего снапшота
zfs send -i tank/data@backup-2026-08-17 tank/data@backup-2026-08-18 | ssh backup-server zfs receive backup-pool/dataСвязка ZFS с инструментами резервного копирования рассмотрена в практическом руководстве по резервному копированию сервера.
Btrfs: работа с подтомами и RAID
Btrfs позволяет создавать RAID средствами самой файловой системы без mdadm:
# Создание RAID1 из двух дисков
mkfs.btrfs -d raid1 -m raid1 /dev/sdb /dev/sdc
# Монтирование
mount /dev/sdb /mnt/storage
# Создание подтома
btrfs subvolume create /mnt/storage/data
# Создание снапшота
btrfs subvolume snapshot /mnt/storage/data /mnt/storage/snapshots/data-2026-08-17
# Проверка целостности данных
btrfs scrub start /mnt/storage
# Просмотр статуса scrub
btrfs scrub status /mnt/storageScrub - важная процедура. Она читает все данные, сверяет контрольные суммы и исправляет ошибки при наличии избыточности. Запускайте scrub еженедельно через cron для раннего обнаружения деградации дисков.
Репликация данных: master-slave и multi-master
RAID и ZFS решают проблему отказа оборудования. Репликация решает проблему отказа сервера целиком. Данные копируются на другой узел, который может принять нагрузку при сбое основного.
Master-slave репликация предполагает один узел для записи (master) и один или несколько узлов для чтения (slave). Запись всегда идет на master, изменения асинхронно или синхронно передаются на slave. Преимущество - простота и предсказуемость. Недостаток - единая точка отказа на запись. При падении master нужен механизм переключения.
Multi-master позволяет писать на любой узел. Это устраняет единую точку отказа и распределяет нагрузку. Недостаток - конфликты при одновременной записи одного и того же ключа на разных узлах. Решение конфликтов требует либо разрешения на уровне приложения, либо использования CRDT и векторных часов.
Выбор между подходами зависит от требований к доступности записи. Если приложение может пережить короткую паузу при переключении - master-slave достаточно. Если запись должна работать всегда - нужен multi-master.
Настройка master-slave репликации PostgreSQL
Потоковая репликация PostgreSQL передает WAL-записи с master на slave. Настройка master-узла в postgresql.conf:
listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1GB
hot_standby = onСоздание репликационной роли:
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secure_password';Добавление правила в pg_hba.conf:
host replication replicator 192.168.1.0/24 md5Клонирование данных на slave:
pg_basebackup -h master-host -U replicator -D /var/lib/postgresql/16/main -P -RПосле запуска slave проверьте состояние репликации на master:
SELECT client_addr, state, sync_state FROM pg_stat_replication;Детальная настройка кластеров PostgreSQL и MySQL с автоматическим переключением разобрана в руководстве по отказоустойчивой архитектуре ИС.
Patroni: автоматическое переключение и высокая доступность PostgreSQL
Patroni - это шаблон высокой доступности для PostgreSQL. Он управляет кластером из нескольких узлов, автоматически выбирает master и выполняет failover при отказе. Patroni использует распределенное хранилище конфигурации (etcd, Consul или ZooKeeper) для координации узлов.
Пример конфигурации patroni.yml:
scope: postgres-cluster
namespace: /db/
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.10:8008
etcd:
host: 192.168.1.10:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
initdb:
- encoding: UTF8
- data-checksums
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.1.10:5432
data_dir: /var/lib/postgresql/16/main
bin_dir: /usr/lib/postgresql/16/bin
pgpass: /tmp/pgpass
authentication:
replication:
username: replicator
password: secure_password
superuser:
username: postgres
password: postgres_password
parameters:
wal_level: replica
hot_standby: on
max_wal_senders: 10При отказе master Patroni автоматически повышает один из slave до master и перенаправляет трафик. Время переключения обычно составляет 10-30 секунд. Для приложений это означает короткую паузу, но не потерю данных при синхронной репликации.
Распределенные СУБД: CockroachDB и другие
Распределенные СУБД изначально проектируются для работы на множестве узлов без единой точки отказа. CockroachDB - это SQL-база данных, совместимая с PostgreSQL-протоколом. Она автоматически реплицирует данные на несколько узлов и использует консенсус Raft для согласования состояния.
Каждая строка в CockroachDB хранится в нескольких репликах (по умолчанию три). Запись подтверждается только после согласования большинства реплик. При отказе узла система автоматически перераспределяет данные на оставшиеся узлы. Это устраняет необходимость в ручном failover и дает непрерывную доступность записи.
CockroachDB подходит для сценариев, где требуется горизонтальное масштабирование и глобальная отказоустойчивость. Цена - более высокая задержка записи по сравнению с одиночным PostgreSQL из-за сетевых раундов для консенсуса.
Развертывание CockroachDB: пошаговое руководство
Установка и запуск первого узла:
# Скачивание и установка
curl https://binaries.cockroachdb.com/cockroach-v24.1.0.linux-amd64.tgz | tar -xz
cp cockroach-v24.1.0.linux-amd64/cockroach /usr/local/bin/
# Запуск первого узла
cockroach start --insecure --store=node1 --listen-addr=192.168.1.10:26257 --http-addr=192.168.1.10:8080 --join=192.168.1.10:26257,192.168.1.11:26257,192.168.1.12:26257 --backgroundЗапуск второго и третьего узлов выполняется аналогично на соответствующих серверах. Инициализация кластера:
cockroach init --insecure --host=192.168.1.10:26257Проверка состояния:
cockroach node status --insecure --host=192.168.1.10:26257Создание базы данных и таблицы:
cockroach sql --insecure --host=192.168.1.10:26257
CREATE DATABASE app;
USE app;
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email STRING UNIQUE,
created_at TIMESTAMP DEFAULT now()
);
INSERT INTO users (email) VALUES ('admin@example.com');Для продакшен-развертывания обязательно настройте TLS-сертификаты. Флаг --insecure допустим только для тестирования.
Критерии выбора технологии хранения
Выбор технологии зависит от требований проекта. Сравнительная таблица:
| Критерий | RAID (mdadm) | ZFS / Btrfs | Patroni + PostgreSQL | CockroachDB |
|---|---|---|---|---|
| Защита от отказа диска | Да | Да | Да (через RAID/ZFS) | Да |
| Защита от повреждения данных | Нет | Да (контрольные суммы) | Нет | Да |
| Защита от отказа сервера | Нет | Нет (только репликация снапшотов) | Да (автоматический failover) | Да |
| Горизонтальное масштабирование записи | Нет | Нет | Нет | Да |
| Сложность администрирования | Низкая | Средняя | Средняя | Высокая |
| Задержка записи | Минимальная | Минимальная | Низкая | Средняя |
| Стоимость | Низкая | Низкая | Средняя | Высокая |
Рекомендации по сценариям:
- Одиночный сервер, файловое хранилище - RAID 10 или RAID 6 + ZFS. Достаточно для NAS и файловых серверов.
- Одиночный сервер, база данных - RAID 10 + ZFS + PostgreSQL. Защита от отказа диска и повреждения данных.
- Кластер из 2-3 узлов, высокая доступность - Patroni + PostgreSQL. Автоматический failover за 10-30 секунд.
- Мультирегиональное развертывание, непрерывная запись - CockroachDB. Горизонтальное масштабирование и отсутствие единой точки отказа.
Сравнение объектного, блочного и файлового хранилищ для выбора базовой архитектуры приведено в отдельном руководстве.
Заключение: итоговые рекомендации
Отказоустойчивость хранения данных строится послойно. Начните с RAID для защиты от отказа дисков. Добавьте ZFS или Btrfs для контроля целостности данных. Внедрите репликацию PostgreSQL с Patroni для высокой доступности. Если проект требует горизонтального масштабирования и непрерывной записи - рассмотрите CockroachDB.
Не пытайтесь внедрить все сразу. Оцените реальные риски: какой простой допустим, какие данные критичны, какой бюджет доступен. Для большинства проектов связка RAID 10 + ZFS + Patroni закрывает 95% сценариев отказов. Распределенные СУБД нужны там, где простой записи недопустим в принципе.
Проверяйте каждую конфигурацию на тестовом стенде перед внедрением в продакшен. Регулярно тестируйте восстановление: замена диска, переключение master, восстановление из снапшота. Резервное копирование остается обязательным дополнением к любой отказоустойчивой архитектуре - оно защищает от логических ошибок и человеческого фактора, которые не покрываются репликацией.