Какие стратегии и технологии вы бы применили для минимизации потери данных при отказе диска между плановыми бэкапами?

Ответ

Чтобы минимизировать потерю данных (снизить RPO — Recovery Point Objective) между бэкапами, необходимо использовать комбинацию подходов на разных уровнях:

  1. Аппаратный уровень: RAID

    • Использование массивов избыточных независимых дисков (RAID). RAID 1 (зеркалирование) дублирует данные на два или более диска. При отказе одного диска система продолжает работать со вторым без потери данных.
  2. Уровень базы данных: Репликация и журналирование

    • Write-Ahead Logging (WAL): Это фундаментальный механизм. Все изменения сначала записываются в журнал (WAL-файл) на диске, и только потом применяются к файлам данных. В случае сбоя, СУБД может восстановить своё состояние из журнала, гарантируя, что закоммиченные транзакции не будут потеряны.
    • Репликация: Создание копий (реплик) базы данных на других серверах.
      • Синхронная репликация: Транзакция не считается завершённой, пока не будет подтверждена и основной базой, и репликой. Это гарантирует нулевую потерю данных (RPO=0), но увеличивает задержку записи.
      • Асинхронная репликация: Транзакция подтверждается сразу после записи на основной сервер, а на реплику данные передаются с небольшой задержкой. Это обеспечивает высокую производительность, но допускает минимальную потерю данных при отказе мастера.
  3. Уровень бэкапов: Point-in-Time Recovery (PITR)

    • Помимо полных бэкапов, необходимо настроить непрерывное архивирование WAL-файлов. Это позволяет восстановить состояние базы данных на любой момент времени, а не только на момент создания последнего бэкапа, эффективно закрывая "окно" между ними.

Пример настройки репликации в PostgreSQL:

-- На основном сервере (primary) в postgresql.conf:
wal_level = replica          -- Уровень журналирования, достаточный для репликации
max_wal_senders = 3        -- Количество процессов, отправляющих WAL на реплики
archive_mode = on            -- Включаем архивирование WAL для PITR
archive_command = 'cp %p /path/to/archive/%f' -- Команда для архивации

-- Для синхронной репликации:
synchronous_commit = on
synchronous_standby_names = 'replica_name' -- Имя реплики, подтверждения которой нужно ждать

Комбинация RAID, WAL, репликации и PITR создаёт многоуровневую защиту, которая сводит риск потери данных к минимуму.

Ответ 18+ 🔞

А, слушай, смотри, вот ты тут про RPO, про потерю данных... Да это же, блядь, как в том анекдоте про Муму, только наоборот! Там Герасим сам топил, а тут мы как раз от этого и спасаемся, чтобы данные не утонули, блядь, в пизду! Ну, короче, давай по полочкам, а то ты сейчас начнёшь метаться, как Герасим, когда совесть загложила.

Первое, железо. Это как здоровый немой татарин, который молчит, но сила в нём есть. RAID 1 (зеркало). Берёшь два диска и пишешь на них одно и то же. Один, сука, сдохнет — второй продолжает работать, нихуя не потеряв. Просто, как три копейки. Без этого — ты как тот мудак, который на одном диске всё хранит и потом орет "Муму!", когда всё накрывается.

Второе, сама база данных. Тут уже начинается магия, блядь. Write-Ahead Logging (WAL). Это, ёпта, как дневник у параноика. Прежде чем что-то сделать с основными данными, база всё записывает в отдельный журнал. "Так, блядь, сейчас я изменю запись номер 666". Записала в журнал — ок, теперь можно и в сами данные лезть. Если посередине процесса накрылся медным тазом — она при старте посмотрит в этот журнал и доведёт всё до ума. Гарантия, что то, что ты уже закоммитил, не испарится. Без этого — чистая рулетка, волнение ебать.

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

  • Синхронная репликация. Это максимализм, как у того Герасима, только в хорошем смысле. Транзакция не считается выполненной, пока и мастер, и клон не скажут "ОК". Потеря данных? Ноль, блядь, нихуя! RPO=0. Но, сука, задержка вырастает, потому что ждём подтверждения от этого клона, который может быть за тридевять земель. Если он тормозит — тормозят все.
  • Асинхронная репликация. А вот это уже по-русски, с расчётом. Мастер говорит "Записал, ок, свободен!" и сразу тебе отвечает. А клону данные прилетают чуть позже, с небольшой задержкой. Производительность — огонь, но если мастер вдруг ебнулся в этот момент — те несколько записей, что не успели долететь до клона, могут потеряться. Минимально, но могут. Подозрение ебать чувствую, когда про это говорю.

Четвёртое, бэкапы с восстановлением на любой момент (PITR). Это, блядь, твоя палочка-выручалочка, когда всё уже на самом деле пиздец. Ты делаешь полный бэкап раз в сутки, допустим. А между ними непрерывно архивируешь вот эти самые WAL-журналы. И если что-то пошло не так, ты можешь откатиться не на вчерашнее утро, а на 14:25 сегодняшнего дня, прямо за секунду до того, как какой-то пидарас шерстяной накосячил. Окно между бэкапами закрывается нахуй!

Вот, смотри, пример, как этого клона в PostgreSQL завести, чтоб не матерился потом:

-- На главном сервере (основном) в postgresql.conf:
wal_level = replica          -- Включаем режим журнала, чтоб хватило для клонирования
max_wal_senders = 3        -- Сколько клонов сможет одновременно кушать наши журналы
archive_mode = on            -- Включаем архивацию WAL для PITR (это важно, блядь!)
archive_command = 'cp %p /путь/к/архиву/%f' -- Куда складывать журналы

-- Если хочешь эту самую синхронную репликацию, чтоб потерь ноль:
synchronous_commit = on
synchronous_standby_names = 'имя_твоего_клона' -- Ждём подтверждения именно от этого парня

Итог, ёпта: комбинация RAID (чтоб диск не подвёл), WAL (чтоб транзакции не потерялись), репликации (чтоб сервер не подвёл) и PITR (чтоб откатить любую хуйню) — это и есть многослойная защита. Как матрёшка, блядь, только от пиздеца. Одна оболочка пробита — вторая держит. Так и живём, в рот меня чих-пых.