Сегодня я хочу поговорить о том, каких преимуществ в вопросах резервного копирования и аварийного восстановления можно добиться за счет смены архитектуры архива и правил хранения информации. Разумеется делать я это буду на примере нового формата архивов, который используют продукты КИБЕРПРОТЕКТ. Из интересного сразу выделю, что мы добились увеличения плотности до 5 раз! (это реальный показатель), а также повысили скорость, удобство и надежность. Не обошлось конечно и без проблем обратной совместимости и некоторых нюансов. Под катом — отличия нового формата, примеры оптимизаций, которые мы сделали, подробнее о плюсах инкрементного бэкапа, а также рекомендации по работе с резервными копиями в современных условиях. Всех заинтересованных приглашаю обсудить архитектурные подходы к работе с резервными копиями.
Ранее, когда деревья были большие, а сервер управления еще не умел в web, резервные копии хранились в предыдущем, 11 формате (tib). Он был относительно простой по своей структуре, неплохо поддерживал сжатие данных, каждая новая копия создавала новый файл в хранилище, а дедупликация работала на уровне управляемого (узлом хранения) хранилища.
Но простота привносила массу ограничений при работе с большими объемами данных, большим количеством объектов в архиве, а также с длинными цепочками резервных копий. Поэтому как в старом анекдоте про «14 конкурирующих форматов», было решено создать новый формат, в котором будет учтен опыт прошлого и реализованные смелые идеи для ответа на вызовы будущего.
При создании нового формата резервной копии хотелось сделать более эффективное и быстрое уплотнение данных, упростить организацию хранения точек восстановления архива, а также оптимизировать процесс восстановления при большой цепочке резервных копий.
Так появился архив формата 12 / Archive 3 /.tibx
При резервном копировании в новом формате сразу заметна ключевая особенность нового формата архива - все инкрементные копии, зависимые от одной полной копии, хранятся в одном файле (не всегда это именно один файл на цепочку, иногда деление файла требуется в первую очередь для обхода ограничений файловой системы, но в рамках одной цепочки такой "набор" файлов все равно рассматривается как единое целое и работа архива с ним не отличается от работы с одним огромным файлом).
Итак, мы создали полную копию, получили файл archive.tibx, добавили в него инкрементную копию, получили все тот же файл archive.tibx который немного подрос на диске. Еще одна копия — и снова архив вырос. Новый файл появится только после создания новой полной или дифференциальной копии, а новые инкрементные копии продолжат эти файлы раздувать. Таким образом количество файлов одного архива значительно уменьшилось.
Далее была добавлена дедупликация на источнике, в рамках файла резервной копии (одной цепочки полная + дифференциальная + инкременты). Таким образом, при хранении длинных цепочек инкрементов, эффективность хранения данных в архиве очень сильно выросла. Больше данных, больше база дедупликации. Работа по дедупликации и сжатию происходит прямо на агенте во время резервного копирования, он держит базу дедупликации в своей оперативной памяти и передает в архив только уникальные блоки. Блоки, кстати, переменного размера, а для работы дедупликации не нужно какое-то особое хранилище: агент будет сжимать и дедуплицировать сохраняемый архив одинаково – будь то локальный диск, smb, nfs или управляемое хранилище.
Плотность
Таким образом, благодаря сжатию и дедупликации на агенте, мы можем иногда получить эффективность уплотнения данных до 1:5 (данные реальные — не маркетинг). Например, в сценарии с резервным копированием рабочей станции на базе Windows 10: диск 256 ГБ, объем данных - 50 ГБ, получаемый архив занимает 12 ГБ.
Но стоит создать новую полную копию, как вся наша экономия превращается в тыкву, так как рядом создается новый файл архива размером в те же самые 12 ГБ. Поэтому хочу еще раз отметить, что максимальная эффективность хранения данных достигается в рамках одной цепочки полная + N инкрементов.
Скорость
Про хранение все понятно: полная + инкременты — это хорошо для уплотнения, но если посмотреть на резервное копирование, то тут мы тоже поймем, что создание инкрементной копии происходит на порядок быстрее, чем создание полной копии. И чем больше объём исходных данных, тем эффективнее использовать именно инкрементный подход резервного копирования. Почтовый сервер весит 10ТБ, его полная копия может спокойно выполняться сутки и займет 3-4 ТБ. А инкремент можно сделать за 0,5-2 часа, и занимать он будет порядка 50-200 ГБ, которые к тому же будут серьезно изъедены сжатием и дедупликацией. Если мы организуем цепочку в 60 копий, то получаем возможность, при необходимости, откатывать почтовый сервер на 2 месяца назад затрачивая в день не более 2-х часов на резервное копирование и примерно половину объема исходных данных на хранение всей цепочки резервной копии.
Так же часто клиенты задают вопросы, когда мы реализуем обратный инкремент и синтетическую полную копию (по смыслу они с обратным инкрементом сильно похожи: данные переносятся/копируются из предыдущих резервных копий с целью ускорения восстановления). На что я отвечаю, что, видимо, никогда, так как это операция очень трудозатратная для агента, а по скорости восстановления наш инкремент и так очень эффективно собирает все данные обратно из резервной копии. Деградация производительности при увеличении количества инкрементов в формате Archive 3 минимальна. Такая же история, кстати, и с синтетической полной копией.
Восстановление
Плотность и скорость — это хорошо, но как же восстановление? Собрать вместе 60 копий и восстановить эти данные — это допустимо для холодного хранилища и слишком дорого для основного (боевого) сценария восстановления. Но это не совсем так, вернее в нашем случае - совсем не так. Благодаря хитрому хранению метаданных для каждой резервной копии (архив = множество резервных копий/точек восстановления) и принципу хранения данных, чем-то похожему на игру «маджонг»: при восстановлении даже очень далекого инкремента мы сразу понимаем путь (Самурая) для оптимального восстановления в один проход. Тем самым, даже на длинных цепочках резервных копий мы практически не теряем в скорости восстановления данных. Судя по нашим тестам и заверениям коллег из отдела разработки, заметная деградация скорости восстановления начинается после 500 (инкрементных) резервных копий в архиве. Как по мне, то 500 это, наверное, все же чересчур, но 100 копий в одной цепочке – это вполне себе рабочий сценарий.
Зачем же нам дифференциальная копия?
В связи с таким подходом к обеспечению эффективности инкрементных копий реализовывать дифференциальную копию для архива мы вообще не планировали, но поддержка обратной совместимости заставила внести изменения в планы. В итоге дифференциальная копия ломает структуру архива, создавая новый файл, так же как и полная копия, но имеет меньший размер. Новые инкрементные копии уже прилипают к этой дифференциальной копии и раздувают ее. Эффективность дедупликации тут сильно падает, так как она начинает работать еще в рамках дополнительной цепочки дифф+инкременты. Поэтому дифференциальную копию имеет смысл использовать только на очень больших цепочках, раз в 100 точек (тут она даст хоть какой-то выигрыш во времени восстановления) или не использовать вообще, последнее подчеркиваю.
Правила и ротация
Про скорость и плотность мы договорились: делаем длинные цепочки инкрементов и радуемся жизни, но как же быть с правилами хранения и ротации резервных копий?
Тут тоже есть свои хитрости. Если в правилах хранения указано хранить не более 60-и резервных копий, то при создании 61-й копии нам придется удалять самую первую, а она (неожиданно!) – полная и от нее зависят как минимум 6 следующих(неделя), а как максимум и все остальные 60 резервных копий. Ситуация не очень приятная. Обычно резервная копия в таком случае просто помечается на удаление и ждет момента, когда все зависимые резервные копии тоже пометят на удаление (либо выполняется дефрагментация - то, что у нас всегда называлось "консолидация” цепочки, что затратно по ресурсам и требует дополнительного места на диске) и только потом, вся цепочка со свистом удаляется из хранилища. Но в схеме «Всегда инкремент» это произойдет никогда, и до самой тепловой смерти вселенной мы будем растить архив, пока он не захватит все доступное пространство в хранилище. Звучит классно. Но мы так не делаем, вернее мы делаем совсем не так.
При необходимости удаления одной из резервных копий, мы добавляем зависимые данные из нее к следующей копии, после чего исходную удаляем, а свободное место внутри файла резервной копии помечаем как неиспользуемое. По возможности мы освобождаем место с помощью функционала разреженных файлов и при следующем резервном копировании используем для размещения новых данных.
Рассмотрим этот вопрос на примере. Пусть 1-го сентября у нас была полная копия, а после нее 2 месяца каждый день создавались инкременты. Настал день Х и полную копию попросили на выход, агент взялся за дело и объединил вместе две точки восстановления от 1-го и 2-го сентября и на выходе получил полную копию, но по состоянию на 2-е сентября. Магия.
Таким образом, в цепочках «всегда инкремент» мы действительно можем хранить только N точек восстановления и не иметь лишнего «мусора» в архиве, который хранится из-за зависимостей и блокировок. Храним только полезные данные.
В случае регулярной полной копии, когда, допустим, раз в неделю создаются новые файлы архива с новыми цепочками, старые файлы (прошлая, позапрошлая неделя) так и будут лежать в хранилище, сохраняя внушительный вес несмотря на стремительное удаление из них точек восстановления (это сделано для повышения надежности: в случае, если файл(-ы) последующих цепочек будут потеряны/повреждены, предыдущая(-ие) цепочка будет нормально доступна, и можно восстановиться на пусть относительно устаревшее, но все же валидное состояние).
Но в определенный момент, когда все точки восстановления в одной из цепочек станут не актуальными, весь файл будет немедленно удален из хранилища на радость систем мониторинга. Отметим, что такой подход с неизменяемостью завершенных цепочек несколько повышает надежность хранения.
А компот…то есть надежность?
Так-с, хорошо, скорость, плотность, ротация – здорово, но как же надежность?
Это ключевой вопрос, который мы слышим от заказчиков. Все знают, что схема «всегда инкремент» — это как непьющий коллега. Вроде все хорошо, но какой-то он «ненадежный». Кто-то, где-то повредит одну из резервных копий, диск даст ошибку, или появятся пресловутые космические лучи и все, боевое восстановление почтового сервера из единственного архива на NASе приведет к новой записи в трудовой книжке системного администратора. Вот тебе и эффективное хранение и быстрое восстановление. И тут трудно спорить, потому что полная копия, всегда лучше, чем инкремент - это совершенно очевидно. И здесь я хочу поделиться с вами некоторой информацией о структуре нашего архива и опытом эксплуатации нашей системы. А нужные выводы, надеюсь, вы уже сделаете сами.
Архив tibx под капотом состоит из последовательности сущностей и на высоком уровне — это структура зависимостей. Например, есть архив с определенным ID, внутри него есть резервные копии/точки восстановления (это все одно и то же) каждая со своим ID и в каждой из резервных копий есть блоки переменного размера (как правило, это несколько десятков кБ). Каждая из этих сущностей при записи финализируется контрольной суммой и некой хэш-суммой, плюс каждая из резервных копия содержит информацию о своих «близких родственниках». В итоге, при каждой операции резервного копирования, агент быстро проверяет структуру архива и как он «финализирован» при последнем резервном копировании. Если все хорошо, то в архив добавляется новая резервная копия с новым ID и наполняется блоками свежих данных, после чего создаются метаданные для быстрого восстановления, резервная копия финализируется, архив закрывается. Если дополнительно использовать валидацию архива как дополнительный этап политики резервного копирования или как отдельную задачу, то проверяется и целостность данных - их соответствие записанным контрольным суммам.
Если агент обнаружит, что резервная копия финализирована некорректно, то он, по возможности, пытается дописать данные с того места, где запись закончилась в прошлый раз. Если агент обнаруживает нарушение структуры и это относится к последней резервной копии, то агент откатывается до последней финализированной копии, исправляет структуру (как будто и не было предыдущей попытки) и потом записывает новую копию поверх не финализированной резервной копии в конце архива. Самый типовой сценарий нарушения структуры архива — это ошибки на уровне файловой системы тома хранения, ошибки работы RAM или внешнее воздействие - ручное удаление/изменение части архива, например, в Проводнике). В этом случае архив переводится в режим «только чтение» и восстановление возможно (не всегда, в зависимости от типа повреждения) только для тех точек восстановления, которые предшествуют точке со сбоем. Здесь надо отметить, что алгоритмы работы архива могут предотвратить искажение данных даже при некоторых типах ошибок оперативной памяти (например, инвертирование битов), и я считаю, что это очень круто.
В заключение
Несмотря на все сказанное ранее, хочу напомнить простые вещи: хоть наш архив и довольно надежный, хранить все яйца в одной корзине не следует. Выполняйте периодическую репликацию архивов на дополнительные носители, сетевые папки, узлы хранения, выполняйте регулярную проверку архивов чтобы контролировать согласованность данных. Для контроля согласованности данных в архиве используйте валидацию. Держите 2-3 линии обороны с разной длинной цепочки в каждой и периодически отчуждайте экспортированные/реплицированные резервные копии в сухое и теплое место, в здании с другим цветом стен. Это важно, потому что космические лучи не дремлют.
Этой статьей я хотел осветить внутренние механики работы нашего архива, а также подчеркнуть его плюсы при работе с длинными инкрементами. Возможно, вы посмотрите на такие сценарии работы немного под другим углом, и эта информация позволит оптимизировать ваши планы резервного копирования, и, как результат, немного улучшит качество вашей жизни.
Пользуясь случаем, хочу поблагодарить нашего системного архитектора Алексея Сергеева за ценные комментарии в процессе подготовки данного материала. Всем пока и до новых, волнительных встреч.
Latsitus
Отличная статья, спасибо!
А какой максимальный размер файла tibx, Вы наблюдали?
Если дедупликация делается на агенте, а в случае бэкапа платформы VMware может одновременно использоваться несколько виртуальных эплаинсов, то каждый эплаинс будет создавать свой tibx, или он будет один на план РК? И если второе, то дедуп будет глобальный для этого плана или каждый эплаинс будет дедупить только те данные, что он через себя пропускает?
ErmolaevD Автор
1) Самый большой архив который видел в заявках клиентов был чуть больше 30 ТБ. Проблем с ним не было, просто видел его в логах. Но уверен что есть и поболее.
2) Привязка архива для ВМ идет по ID этой ВМ и ID плана. По этому в момент начала резервного копирования происходит балансировка по агентам (кому удобнее и проще), а потом агент продолжает созданный ранее архив. К агенту тут архив не привязывается.
3) Дедуп в данном случае будет в рамках последней цепочки (полная копия и ее дифы + инкременты).
Latsitus
>Привязка архива для ВМ идет по ID этой ВМ и ID плана. По этому в момент начала резервного копирования происходит балансировка по агентам (кому удобнее и проще), а потом агент продолжает созданный ранее архив. К агенту тут архив не привязывается.
То есть на план РК один архив? и агенты друг с другом и узлом хранения хешами обмениваются?
ErmolaevD Автор
В плане резервного копирования, для каждой ВМ архив один. Верно.
Все хеши и мета хранятся в самом архиве. По этому агентам не нужно ничем обмениваться. Агент просто начинает резервное копирование и из самого архива берет все необходимое.