Pull to refresh

Backup — дело тонкое

Reading time 5 min
Views 17K
Практически все согласны, что бакапы делать надо. Но, тем не менее, эта проблема всплывает снова и снова. Недавний опрос продемонстрировал два любопытных момента: во-первых половина из нас бакапы не делает вообще, а во-вторых автору даже не пришло в голову включить в опрос пункт «раз в день». Что же не так с простой, на первый взгляд, задачей — запаковать свои файлы и положить архив в тёплое и сухое место?

Основная проблема в том, что бакап не относится к тем вещам, которые можно сделать не думая! Если попытаться тупо запаковать всё содержимое винта, то во-первых вам негде будет эти архивы (ежедневные! :)) хранить, и во-вторых ваша машина будет круглосуточно заниматься архивированием себя, любимой, вместо выполнения ваших задач. А когда начинаешь думать (что уже непросто), то оказывается, что данные на винте очень разные, и бакапить их желательно тоже по-разному (что окончательно осложняет ситуацию). Как следствие, либо принимается решение не делать бакапы вообще (замаскированное под «отложить на потом»), либо ставится первая попавшаяся утилита и кое-как быстро настраивается, в надежде, что этого будет достаточно.

Поэтому нет, и не может быть, такого решения для бакапов, которое бы подошло всем. Кому-то нужно бакапить свои тексты под виндой на сетевой диск, кому-то нужно бакапить сервер целиком на ленту, кто-то использует вместо традиционных бакапов Venti, а кому-то нужно просто делать регулярные бакапы своего веб-проекта и отправлять себе на GMail. А это, в свою очередь, сильно осложняет выбор подходящего для вас софта.

Поэтому IMHO лучший способ помочь кому-то с бакапами — рассказать что, как и почему бакапите вы. Я сталкивался с двумя разными сценариями, и хочу рассказать о своих решениях. Надо отметить, что в обоих случаях для меня самым критичным фактором была надёжность — зачем нужен бакап, из которого нельзя гарантированно корректно восстановить свои данные?

Backup своего большого веб-проекта


Большой проект очень не просто забакапить надёжно — так, чтобы после восстановления из бакапа он гарантированно продолжил работать и не возникло никаких проблем (кроме отсутствия новых данных, которые были добавлены после последнего бакапа, конечно). Дело в том, что и файлы на диске и база данных далеко не всегда находятся в «целостном» (consistent) состоянии. Выполняются какие-то транзакции в базе (которые далеко не всегда явно оформлены как SQL-транзакции, кстати), создаются временные файлы, пишутся логи… Причём в большом проекте зачастую много других «точек входа» помимо HTTP: обработка входящих писем, RPC-запросов, cron-задачи, работают разные TCP/UDP сервисы. Застать всю эту махину в целостном состоянии, да ещё и продержать в нём всё то время, что выполняется бакап — задача для внешней софтины просто невыполнимая!

В связи с этим, наше решение заключается в том, что проект сам должен поддерживать возможность создания целостных бакапов. Подход примерно такой же, как и с тестированием — чтобы проект было возможно (и удобно) тестировать его код изначально пишется с учётом требований тестирования.
Реализуется это тривиально «в лоб» — все приложения проекта поддерживают единую систему блокировок, и на время бакапа проект блокируется.

Но это привело к новой проблеме — ведь бакап дело не быстрое, особенно бакап большой базы данных… а если проект надолго блокировать раз в сутки, то наши пользователи нам за это спасибо точно не скажут. Эту проблему мы решили реорганизацией базы данных таким образом, что все таблицы были разделены на два типа: статические и динамические. Со «статическими» таблицами выполняются только SQL-запросы SELECT и INSERT, а «динамические» могут меняться как угодно. Разумеется, все объёмные данные были вынесены в статические таблицы. Это позволило сократить время блокирования проекта для бакапа до нескольких секунд: для архивирования (tar-ом, без сжатия) файлов проекта, создания дампа динамических таблиц, и запоминания id последней записи в статических таблицах.

После чего блокировка снималась, и, уже без спешки, дампились статические таблицы (до запомненного id), tar сжимался и отправлялся в хранилище. Разумеется, статические таблицы и файлы проекта можно (и нужно) бакапить инкрементально.

Не смотря на универсальность подхода (мы его используем во всех своих проектах), наш скрипт для бакапа будет малополезен для других, т.к. заточен на использования с нашим фреймворком. Если любопытно на него посмотреть: asdfBackup.

Backup обычного dedicated сервера


Обдумав свои требования к софту для бакапа сервера, я пришёл к следующему списку:
  • Софт для бакапа должен быть простым и надёжным. Зависимость количества багов от размера софта все знают, и мне только багов в бакапах нехватало для полного счастья!
  • При бакапе сервера целиком невозможно учесть все нюансы установленных на нём проектов и обеспечить их гарантированную целостность после восстановления из бакапа. Поэтому описанный ниже подход используется не вместо, а вместе с описанным выше бакапом конкретных проектов. Но, тем не менее, есть вещи которые необходимо обеспечить и при бакапе сервера — например, целостность базы данных (она может не быть целостной с точки зрения конкретного проекта, но она должна быть целостной с точки зрения MySQL-сервера).
  • Бакап должен выполняться быстро, чтобы не мешать серверу выполнять свою основную функцию. (На сервере одного знакомого админа я как-то обнаружил, что его cron-задача архивирующая винт раз в сутки в .tar.bz2 выполняется два часа, причём ничего другого в это время на сервере делать практически невозможно!) В частности, с учётом предыдущего пункта, это означает, что блокировать базу данных нужно не на всё время бакапа сервера, а только на время бакапа файлов самой базы данных.
  • Формат файлов. Ставить такую критичную вещь как бакапы в зависимость от нестандартных форматов файлов очень не хотелось. Стандартных утилит более чем достаточно для архивирования и шифрования бакапов (например tar + gzip + gpg).
  • Система должна позволять достаточно гибко обрабатывать бакапы — шифровать, заливать на другие сервера, etc.
  • Интерфейс должен быть достаточно информативным для отлаживания и настройки бакапов, но при этом не должен спамить меня раз в сутки письмами с каждого сервера «всё в порядке, бакап сделан», я хочу получать письмо только если произошла ошибка.
powerbackup

Может я не там искал, но мне не удалось найти софт, соответствующий этим требованиям. Поэтому я его написал сам: powerbackup. :) Получился небольшой и простой sh-скрипт (70 строк, 2 KB), полностью отвечающий описанным выше требованиям и решивший для меня проблему бакапа серверов.

Необходимой гибкости с сохранением простоты удалось достичь с помощью двух архитектурных решений:
  1. Общая задача «бакап сервера» разделяется на несколько подзадач, например: бакап настроек сервера, бакап базы сервера, бакап домашних каталогов пользователей.
  2. Создание бакапа разделено на два этапа: подготовка файла (инкрементально через tar) и его архивация (gzip). И для каждой задачи можно указать индивидуальные hook-и для этих этапов. Например, задача бакапа базы перехватывает первый этап, чтобы заблокировать MySQL на время архивации файлов в /var/lib/mysql/. А задача бакапа пользовательских каталогов может перехватить второй этап, чтобы заменить сжатие через gzip на шифрование через gpg и заливание файла через scp.
Более детальные примеры настройки есть на сайте.

Лицензия, как обычно, public domain.
Tags:
Hubs:
+23
Comments 69
Comments Comments 69

Articles