Архив метки: zfs

ZFS. Почему заканчивается место в пуле? Подводные камни ZVOL на raidz.

Файловая система ZFS — достаточно продвинутая и многофункциональная. Тут вам и дедупликация, и сжатие, и контрольные суммы, продвинутое кэширование и т.д. Одно из хороших применений ZFS — создание ZVOL на ее основе и дальнейшее расшаривание их по iSCSI для любых целей. Плюсы достаточно очевидны: надежность хранения как на любом RAID, отсутствие дорогих аппаратных RAID-контроллеров, быстрое восстановление массива в случае замены диска (ZFS не перестраивает весь массив, как классические RAID — перестраивается только реально необходимое место). Но потом всплывают малоизвестные минусы…

Итак, при создании ZVOL с параметрами по умолчанию (а именно volblocksize=8k) на raidz и заполнении всего раздела данными мы можем внезапно обнаружить очень немаленький оверхэд по реальному размеру, занимаемому этим разделом в массиве. Причем речь идет не о 10%, которые можно было бы простить «на служебные нужды». Речь легко может идти о 60-70% оверхэда. Да-да, при размере ZVOL в 1 ТБ, он вполне может занять 1.7 ТБ в вашем массиве. И произойдет это ровно в тот момент, когда вы этого ожидаете меньше всего — массив заполнен полезными данными, а найти такое количество места, чтобы быстро сбросить туда всё — нереально.

К сожалению, никаких «магических» способов исправить такую ситуацию, когда она уже случилась — нет. Более того, скорее всего вам придется уничтожить весь zpool для того, чтобы вернуть его к жизни — так как даже при удалении всех zvol в массиве вы не сможете создать такое же количество новых zvol с тем же размером. Т.е. только zfs destroy/zpool destroy/zpool create/zfs create.

А теперь немного цифр. Я провел тесты для определения потерь места на массиве raidz из 8 HDD с разными volblocksize. Ниже в таблице представлены результаты тестов. Методика такая: создаем ZVOL на 5 ГБ с размерами блоков 4k, 8k, 16k, 32k, 64k и 128k. После этого при помощи dd с параметром bs=8k записываем данные на раздел пока dd не скажет, что место закончилось. Далее при помощи команды zfs get all zpool/zvol1 смотрим на параметр used — он-то и расскажет о реально занятом месте.

Размер блока 4k 8k 16k 32k 64k 128k
Занятое место 8,52 ГБ 8,48 ГБ 6,34 ГБ 5,28 ГБ 5,27 ГБ 5,01 ГБ
% 170,4 169,6 126,8 105,6 105,4 100,2

Для моих целей прекрасно подошел размер блока 128к, т.к. мелкие файлы на нем не хранятся и потери в таком случае будут минимальны. Следует учитывать, что эти сведения актуальны для массива raidz из 8 дисков. Если у вас raidz2 или другое количество дисков — данные будут другими. Как вариант, вы можете использовать комбинации stripe и mirror — они лишены этой неприятной особенности.

Горячие бэкапы mysql при помощи снэпшотов ZFS в FreeBSD

Давным-давно, на заре времен, когда сервера были большими, а базы данных маленькими, все нормальные люди бэкапили их просто при помощи mysqldump. Получался в результате сего действия вполне себе хороший бэкап, который можно восстановить где угодно. Шло время, объемы баз росли… В какой-то момент придумали mysqlhotcopy для того, чтобы не тратить ресурсы на полное вычитывание базы (с блокировкой таблиц на это время). Он прекрасно справлялся с таблицами myisam, но с innodb ничего поделать не мог. Долгое время «горячий» бэкап innodb-таблиц был возможен только при помощи платного софта, который не все могли себе позволить. Потом добрая Percona выпустила свой бесплатный xtrabackup, который снимал горячие копии InnoDB, XtraDB и MyISAM таблиц. Вроде бы все было хорошо, но… Если ваш сервер не относится к high-end, но очень старается работать также (с минимальными перерывами в обслуживании), то даже бэкап с помощью xtrabackup на продакшене может вызвать небольшой даунтайм — если вы копируете базы размером в 5-10 Гб, а запросы к ним идут хотя бы пару раз в секунду. Конечно, можно сказать, что мир неидеален и надо ставить второй сервер, настраивать репилкацию и снимать копии со слэйва. Но не всегда на это выделяется должное финансирование.

Всю ситуацию может спасти сервер с FreeBSD на ZFS. В FreeBSD поддержка ZFS сделана уже довольно давно и работает она в ней стабильно, хоть и намного медленнее, чем в Solaris. Именно в ZFS есть модный нынче «механизм» снэпшотов (снимков) файловой системы. Причем сделано все так, что наличие большого количества снэпшотов никак не влияет на производительность сервера (кроме, конечно, поедания дискового пространства). Именно при помощи снэпшотов можно делать самые быстрые горячие бэкапы mysql. Но тут всплывает один нюанс: InnoDB сбрасывает «грязные» страницы на диск не сразу, да и мы можем сделать снэпшот как раз в момент записи данных (и чем больше пишем, тем больше шансов это сделать). Т.е. наша база в бэкапе может оказаться с битыми таблицами. Приятного мало.

Можно, конечно, набросать простенький скрипт, который будет делать «flush tables with read lock», потом снэпшот, потом «unlock tables», но лучше воспользоваться уже готовым вариантом. В FreeBSD портировали прекрасную софтинку (или даже скрипт) для автоматического создания снэпшотов — zfstools (искать тут: /usr/ports/sysutils/zfstools).  Ей необходимо передавать всего 2 параметра: название серии снэпшотов и количество снэпшотов, которые необходимо в этой серии хранить. Запускается она так:

/usr/local/sbin/zfs-auto-snapshot hourly 72

Объяснить ей что надо снэпшотить, а что нет, очень просто: необходимо выставить свойство com.sun:auto-snapshot = true для конкретной ФС в zpool (причем этот параметр наследуется всеми «дочерними» ФС). При запуске она просматривает все файловые системы в zpool и снэпшотит те из них, в которых свойство  com.sun:auto-snapshot установлено не в false. В случае снэпшота файловой системы, в которой лежат базы данных (вы же создали под них отдельную ФС, верно?) вместо true необходимо написать mysql. Скрипт автоматически выполнит команду «flush tables with read lock», сделает снэпшот и разблокирует таблицы. Таким образом, скорость выполнения будет напрямую зависеть от количества данных, которые необходимо сбросить на диск при снятии снимка.

Но опытные пользователи админы понимают: снэпшот — не замена бэкапа. Если умрет сервер — умрут и все снэпшоты. Для простого доступа к файлам снэпшотов, в FreeBSD реализован замечательный «скрытый» путь. Если мы сделали снэпшот /var/db/mysql при помощи zfs-auto-snapshot 1 марта 2015 года в 11:00, то получить к нему доступ сможем по пути: /var/db/mysql/.zfs/snapshot/zfs-auto-snap_hourly-2015-03-01-11h00. Таким образом, сразу после снятие снэпшота, его можно скопировать куда угодно каким угодно способом. А для того, чтобы не создавать лишнюю нагрузку на диски, лучше всего копировать оттуда данные при помощи rsync — после первого копирования мы будем перемещать только измененные таблицы, что чаще всего значительно уменьшает время, необходимое на копирование и неплохо снижает нагрузку на диск. И уже после этого, в удаленном месте (это может быть даже виртуалка на обычном PC) снимаем бэкапы.