Как стать автором
Обновить

Тонкое резервирование файловых систем Linux. Как создавать рабочие копии трехтерабайтной СУБД MySQL за 20 секунд

Время на прочтение10 мин
Количество просмотров16K
Всего голосов 34: ↑34 и ↓0+34
Комментарии55

Комментарии 55

Если (когда?) вы дадите разработчикам возможность создавать шард под себя и писать/тестить на нём какие-то фичи, что весьма удобно, когда хватает места, то столкнётесь с небольшой проблемой: разработчик показывает бизнесу новые фичи, бизнес говорит «отлично, внедряем!» и не понимает, что хоть шард прода и прод почти одинаковы — нельзя взять и запушить все изменения напрямую.

почему нельзя?

Потому что пуши даже от 3 разработчиков, которые создали свои шарды и что-то поменяли на прод, могут сломать большую часть прода: нужно хотя бы собрать все изменения и оттестить их — функциональное, интеграционное, регресс-тестирование.
К примеру, 1 добавляет новый функционал, который стартует при вставке в таблицу по ттриггеру on after insert. И второй разработчик сделает что-то с этим триггером — в результате могут быть чудные баги и гонка обновлений: какой alter trigger придёт позже — тот и будет работать, со всеми сопутствующими фичами.
Хотя, всё зависит от ценности системы и стоимости downtime: знаю компанию, которая свежее UI выкатывает сразу в прод, там же и тестит.
Запросы тестировщиков на получение тестового контура упираются в «а вам зачем?»
Разные изменения от двух разработчиков могут сломать друг друга почти всегда. От наличия копии базы с прода это не зависит — и других способов много.

>Запросы тестировщиков на получение тестового контура упираются в «а вам зачем?»
Не, ну вопрос-то вполне резонный. Скажем, наш тестовый контур, чтобы полностью реализовать сценарий (лишь один из множества других), имеющий место в проме, должен включать минимум два оракла и хадуп, и это не считая остальных «мелочей». Понятно что это денег стоит — за железки и за работу, и на этом пытаются экономить (обычно за счет надежности, конечно же).
Значит, для вашей компании упавший пром (+время его даунтайма) выходит дешевле, чем несколько серверов на тестовый контур + оракловые лицензии.
Или руководители не считали, сколько будет стоить такое падение + простой + недополученная прибыль.
Или надеются на авось и вообще, «выжпрофессионалы, почему всё упало?!»
> упавший пром
Все-таки, пониженная надежность не синоним нулевой надежности. С какого это он вдруг непременно будет падать?

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

Ну так это вопрос пересечения изменений по коду, какая база особо нет разницы. Ну и реально кажется редким случаем — два разработчика одновременно пилят один и тот же кусок кода и не знают об этом. У нас продуктовые команды, где люди общаются, ну и есть лид. Если и случилось такое, то мерж конфликт с мастером уже намекает перепроверить результат. Ну и функциональные тесты как вишенка. Т.е. все стандартно и не вижу, что может поменяться от наличия/ отсутствия снепшотов базы

На свежих linux ядрах можно использовать новую фичу — reflinks. На хабре были небольшие заметки, можно поискать.
Схема останется примерно той же, только упростится (в случае с lvm) — вместо шаманства со снапшотами и всем этим адовым LVM-зоопарком, после остановки реплики делаем
cp -a --reflink=always /var/lib/mysql /var/lib/mysql-snapshot1/
и всё — имеем рабочую copy-on-write копию. Помимо упрощения процесса — такой метод не требует наличия отдельно зарезервированного места в lvm пуле для хранения изменений относительно снапшота, которое непонятно как заранее определить.


Я по такой схеме делаю бэкапы мускуля, постгреса, монги: имею кучу снапшотов, снятых через интервал 10-30 минут за последние несколько суток, и раз в сутки утягиваю актуальный снапшот в холодное хранилище (там уже рефлинки "разломаются", конечно, тк ФС меняется).
Вотъ. Имею сказать — весьма неплохо работает. Базы от 10 до 350 гигов.


А вообще, zfs рулит, конечно =)

новую фичу — reflinks

На ext4?

xfs, как я понимаю?

Да, XFS.
Как дела у ext не знаю, давно не слежу за ними и не использовал.

Да, у нас основная production fs это ext4, не поддерживающия COW, да и основное LTS ядро у нас пока без поддержки reflinks. Интересно было бы посмотреть не просто холодные снапшоты а именно под нагрузкой в 2-3 активных снапшота на одном сервере — возможно cо временем проведем такие эксперименты на xfs на свежем ядре.

вангую, что у вас основная ос — дебиан или убунту. Так ?

Ubuntu
А может знаете способ как можно в MySQL быстро скопировать базу в другую (с другим именем) на этом же сервере? Все очевидные варианты (типа создать пустую базу, скопировать в неё файлы) перепробовал — не работает. Percona xtrabackup аналогично не позволяет такое провернуть. Единственное что работает — дамп и заливка, но это дико долго.
Раздел в xfs, созданый с опцией reflink. Или раздел с btrfs. Копирование в пределах одной ФС, через cp --reflink=auto, займёт секунды.

mongodb на 400 гигов, SSD, reflink копирование занимает 2 — 2:30 минуты.

А сколько файлов копируется?

Imho, здесь важно не количество файлов, а их размер, тк для reflink нужно прописать дополнительные данные для каждого блока.
Но я всё же проверил вашу гипотезу. До этого было ~ 600 файлов, тк на реплике были включены диагностики, которые плодили лишние файлы. Отключил диагностику, почистил, теперь осталось 60 файлов.
Время reflink копирования не изменилось.

Файловая система какая: xfs, btrfs или APFS?
И сколько по времени занимает обычное копирование?

Я подозреваю, что у вас XFS. Что касается BTRFS — в ней эта операция c аналогичным объёмом данных на HDD занимает около 10 секунд.

Для XFS для reflink нужно создавать раздел заново со специальными ключами, может в этом дело.

XFS. Конечно, ФС была создана с фичей reflink.
На BTRFS делать подобное смысла мало, там есть нормальные снапшоты. Но в проде я btr использовать боюсь.

Но в проде я btr использовать боюсь.

Synology в своих NAS не боится (смотри ниже ссылку). В конце-концов, опасения верные, но тогда и Убунту пользоваться стремно — у вас же наверняка не куплена поддержка от вендора ?

Ну у синолоджи свои данные и мнение, а у меня свое. Такое бывает.
Я вполне представляю себе расклад по фс, с их + и — , нет смысла стращать меня громкими именами :) Тем паче, что ковырял я синолоджи изнутри, неонки там нет.
Убунту на серверах я не использую, хотя попытки были. На десктопе — в целом норм, терпимо.

Тут дело не в скорости копирования даже — MySQL вот так напрямую не позволяет скопировать базу (для innodb по крайней мере), потому как кроме копирования файлов в директории базы нужно ещё модифицировать ibdata

так реплика же

Не понял причём тут реплика. Мне нужно быстро скопировать базу в пределах одного сервера MySQL.

Ну как, реплика позволяет корректно и без простоя потушить инстанс СУБД, сделать снапшот и вернуть реплику в работу. По идее журнарлирование БД должно позволять снимать снапшот прямо с рабочего процесса, и в случае восстановления сделать необходимый откат незавершенных транзакций… Но через реплику как-то спокойнее. =) Ибо были серьезные баги у того же постгреса с вызовом sync, плюс, даже если мы получили ответ, что sync прошел это еще не гарантия того, что данные в самом деле легли на пластины/записались в ячейки. Слишком много там слоёв стало.

Копирование в пределах одной ФС, через cp --reflink=auto, займёт секунды.

В случае btrfs можно же снимок тома делать — это даже не секунды, а мгновенно.

Процесс БД, как я понимаю, не остонавливали,
Останавливали — это указано в статье — иначе получаем длительный check на старте MySQL на снапшоте из-за некорректного завершения.

Разве это допустимо в продакшне?

Нет — но это и не продакшн — в статье описана stage-среда основанная на реплике от мастер продакшн базы, но которая (реплика) не участвует в бизнес процессах. Поэтому тут важнее не сама остановка, а скорость при остановке и запуске для того чтобы реплика как можно быстрее восстанавливала отставание от мастера.

Имеем на проде несколько баз PostgreSQL на ZFS. Основная весит более 20Тб. Используется для бэкапов. Да и сами БД на SSD под zfs работают здорово.
Есть немного рекоммендаций по тюнингу ZFS:


  1. Сжатие лучше использовать LZ4 т.к. gzip в разы медленнее. Возможно даже гна порядок медленнее. Под LZ4 база так же жмётся с коэффициентом около 2, а оверхеда на сжатие по сравнению с записью без сжатия вообще не удалось заметить. Т.к. у zfs скорость сжатия на одно ядро подходит к 1Гб/сек.
  2. Размер блока оптимальный по производительности оказался 128кб, хотя у Постгре блоки в базе по 8кб это оказалось лучше для arc-кэша.Так же более крупные блоки лучше жмутся, опять же, снижая нагрузку на диски.
  3. Удивило создание вами l2arc на рамдиске. Это намного хуже, чем отдать эту память тому же arc-кэшу. Более того, если у вас вся база уже лежит на ссд от l2arc нет пользы т.к. это нужно для гибридных решений, где есть небольшой, шустрый ссд под кэш, а памяти уже не хватает. У вас же происходит по сути дубляж одних и тех же данных в arc и l2arc.
  4. Zil slog можно не делать, достаточно прописать для датасета zfs асинхроную запись всегда и режим throughput. Это позволит возвращаться из прерывания записи не дожидаясь фактической записи данных на диск. При внезапном отключении питания потеряются только данные в памяти, на целостность ФС это не влияет.
  5. Чисто постгресовая вещь, не знаю, есть ли аналог в MySQL — можно отключить full page writes в xlog БД т.к ZFS гарантирует целостность и атомарность записанных блоков.

В п.1 опечатался. Имел в виду, что у LZ4 скорость упаковки/распаковки под 1Гб на ядро. С телефона писал, извините! )

Размер блока оптимальный по производительности оказался 128кб,

зависит от данных в бд, стоит тестить


Zil slog можно не делать, достаточно прописать для датасета zfs асинхроную запись всегда и режим throughput.

Только если готовы потерять последние секунды записи, на кластерах может быть больно.


Добавлю ещё, что на линуксе, если вам не нужна 100%-ная совместимость пула с другими ОС, стоит выставлять xattr=sa, будет экономия нескольких iops на каждое изменение и чтение метаданных файлов.

Это реплика же. То что потеряется это несколько секунд обычно, дореплицируется заново, накатив логи с мастера. На мастере это было бы критично, конечно в службе такси, у нас же первичная инфа хранится в логах и мы можем повторно залить хоть всю базу, но это очень больно на 20 Тб будет )
Про xattr согласен, тоже устанавливаем. Но на бд профита не заметил.

Про 128кб блок, не совсем от данных в бд зависит. Больше от устройства ZFS. На каждый блок в кэше arc и l2arc идёт оверхед на хранение метаданных. Плюс сексканы и вакуумы делаются дольше собирая блоки по 8кб из рандомных мест.
Но конечно тестов под конкретный профиль использовпния БД никто не отменял. Я когда замерял, остановился на 128. На 8кб был огромный оверхед в l2arc в гибридных ssd + hdd инстансах.

Вы правы про оверхед ZFS на каждый блок, но я имел в виду тесты на данных именно про оверхед чтения всех 128к для получения 8-16к из них, и аналогично read-modify-write такого блока. Если запись-чтение происходит очень малыми блоками и не последовательно, то этот оверхед может быть больше, чем вы сэкономили в zfs на большом блоке.
Спасибо за подробный экспертный комментарий!
п.1 однозначно попробуем
п.2-3 делали по рекомендациям Perconа из вот этой статьи — при замере l2arc в shm особого прироста или регресса не заметил, но решили оставить исходя из рекомендаций.
п.4 попробуем

L2arc — выгрузка редко используемого кеша l1arc (в озу) на диск.


Slog — запись zil (журнала синхронной записи до формирования txg) на отдельный быстрый носитель. Если он вам не нужен и вы готовы потерять синхронную запись за последние секунды — просто поставьте sync=disabled на датасет.


В обоих случаях выгружать их в рамдиск бессмысленно. Странная статья, признаться, в этой части.

В статье использовали gzip для сжатия. Возможно более мелкий блок позволил лучше распараллелить сжатие и в целом жать меньше при мелких записях/чтении. LZ4 же не является бутылочным горлышком даже при рандомных чтениях по 128кб. Да еще в последних версиях ZFS по дефолту вкючено сжатие и в кэше arc. Если там тот же gzip будет, как у датасета, то это вообще грустно будет по скорости.

Но предполагаем, что проблема сохраняется, поэтому я не стал бы рекомендовать эту файловую систему для каких-либо файловых хранилищ.

То-то внутри коммерческих хранилок ZFS внутри. Ну, или btrfs.

В каких?

Во всех на базе zfs и btrfs.


А по серьёзному — zfs для больших хранилок и делался. Nexenta, nutanix files, oracle zfssa, это только из головы.


Не скажу за опыты автора, но с большим количеством файлов она справляется лучше других фс. Для примера на тестах zfs хранит мету о файлах минимум в 2 раза эффективнее по месту, чем ext4.

Ну большие серьезные коммерческие хранилки это все же netapp, emc, а там вроде как свои решения, покруче zfs.
zfs это для бедных, хотя лучше ничего нет, это да. С ext сравнивать смешно :)

Synology рассматриваем? или это так — поиграться?
Ну, у них btrfs, о чем они радостно рассказывают — https://www.synology.com/ru-ru/dsm/Btrfs

А как получить то же самое, но с анонимизацией некоторых данных (данных клиентов) в БД?

При небольшом объеме подобных данных можно делать сразу после старта реплики на снапшоте обфускацию приватных данных скриптом — но это пока только в планах, и реализация конечная пока не продумана, возможно есть лучше решения.

Разве FLUSH TABLES WITH READ LOCK; в mysql не хватает для консистентных снапшотов, зачем его полностью тушить?

Пробовали, но к сожалению нет — все равно при старте прогоняет recheck всех данных. (Percona 5.7)
Давно не лазил в эту часть мускуля, но думал, что он только вычитывает бинлоги. У перконы есть возможность читать только первый и последний бинлог если включить одну настройку. Вы же про бинлоги?
Цитируя O'Reilly High Performance MySQL:
InnoDB’s background threads continue to work even if you’ve locked all tables, so it
is probably still writing to its files even as you take the snapshot. Also, because InnoDB
hasn’t performed its shutdown sequence, the snapshot’s InnoDB files will look the way
these files would have looked if the server had lost power unexpectedly.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий