Изучаем ZFS


David Chisnall
Перевод: Виктор Черкасов

NetSago

2 октября 2007 г
Оригинал: ZFS Uncovered
Все замечания и исправления к переводу принимаются по адресу n0xi0uzz@gmail.com.

Каждые несколько лет, кто-то делает прогноз о том, сколько компьютерных ресурсов, скорее всего, понадобится в будущем. Позже, все смеются над наивностью этих прогнозов. В проектировании ZFS, Sun попыталась избежать этой ошибки.

Пока весь мир переключается на 64-битные файловые системы, Sun выкатила 128-битную. Понадобится ли нам когда-нибудь столько пространства? Не сразу. Масса Земли около 6?1024 килограмм. Если бы мы взяли такую массу водорода, мы получили бы 3,6?1048 атомов. 128-битная файловая система может индексировать 2128, или 1038 единичных блоков. Если вы создадите хранилище, в котором каждый атом будет хранится как одиночный бит водорода (не считая пространства, которое вам понадобится для управляющей логики), вы сможете создать около 300 000 таких устройств, превышающих массу земли, если каждый из них будет иметь 128-битную файловую систему с 4 Кб единичных блоков. Чтобы преодолеть ограничения дискового пространства ZFS, нам придется создавать жесткие диски, размером с континенты.

Так есть ли какое-то преимущество у 128-битных файловых систем? Не совсем. Тем не менее, если текущие тенденции будут продолжаться, мы начнем превосходить ограничения 64-битных файловых систем в следующие 5-10 лет. 80-битной файловой системы возможно будет достаточно для непредвиденных выходов за границы ограничений, но большинство компьютеров работают с 80-битными числами сложнее, чем со 128-битными. Вот почему Sun выпустила 128-битную систему.

Конечная независимость.

При записи данных на диск (или в сеть), вы должны быть осторожны с порядком байтов. Если вы загружаете и храните данные только на одном компьютере, вы можете выполнять контрольное считывание содержимого регистров компьютера, в независимости от их представления. Проблема возникает, когда вы начинаете распространять информацию. Все в порядке, если вы оперируете с объемами меньше байта (до тех пор, пока вы не используете VAX), но большие объемы нуждаются в наличии четко определенного порядка байтов.

Два наиболее распространенных порядка расположения байтов названы в честь поедающих яйца философов из книги Джонатана Свифта "Приключения Гулливера". "Тупоконечная" нотация располагает байты в виде 1234 (big-endian, обратный порядок байтов, при котором старший байт передается сначала, - примеч. переводчика), в то время как "остроконечные" компьютеры хранят их в порядке 4321 (little-endian, прямой порядок байтов, при котором сначала передается младший (наименее значимый) байт, - примеч. переводчика). Некоторые компьютеры используют что-то вроде 1324, но в основном, люди стараются избежать использование подобного порядка.

Большинство файловых систем спроектированы для работы на определенной архитектуре. Не смотря на то, что она может быть портирована на другие архитектуры позже, каждая файловая система имеет тенденцию к хранению метаданных в том порядке расположения байтов, что использовался на оригинальной архитектуре. HFS+ от Apple является хорошим примером подобной практики. С тех пор, как HFS+, возникшая на Power PC, данные в файловой системе хранятся в формате big-endian. На маках с процессором Intel, вам приходится переворачивать порядок байтов при каждой операции загрузки или сохранения на диске. Инструкция BSWAP на чипах x86 позволяет быстрый переворот, но, в любом случае не является решением высокой эффективности.

Sun заняла интересную позицию в порядке расположения байтов, когда начала продажи и поддержку Solaris на архитектурах SPARC64 и x86-64. На SPARC64 используется big-endian, а на x86-64 little-endian; таким образом, Sun выбрала сделать одну из своих файловых систем медленнее, чем на другой поддерживаемой Sun архитектуре.

Решение Sun? Не выбирать. Каждая структура данных в ZFS записана в том порядке расположения байтов, в каком компьютер её записал и сопровождается индикатором используемого порядка расположения байтов. Раздел ZFS на Opteron будет little-endian, а контролируемый UltraSPARC - big-endian. Если вы разделите дисковое пространство между двумя компьютерами, все по-прежнему будет работать; и чем больше операций записи выполняется, тем больше он становится оптимизирован для чтения.

Ужасное нарушение иерархии.

ZFS была описана в LKML как "ужасное нарушение иерархии". Это не совсем точно, ZFS не является файловой системой в традиционном понимании UNIX, но, несмотря на это, набор хорошо определенных слоев дает расширенный набор обычной файловой системы. Поэтому любые администраторы VMS могут самодовольно пробормотать: "UNIX наконец-то получил настоящую файловую систему. В конечном счете, он может быть готов для использования предприятиями".

Три слоя ZFS называются: слой интерфейса, слой работы с объектами и слой хранения пулов. Проходя вниз по стеку, разметка слоев файловой системы делает запросы на транзакции объектов, транзакции на виртуальное устройство и, наконец, превращение виртуальных операций в реальные.

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

Менеджер разделов.

Внизу стека ZFS находится слой хранения пулов.
Этот слой выполняет простую роль менеджера разделов на текущей системе. Он берет несколько физических устройств и комбинирует их в виртуальные.

Каждое виртуальное устройство (vdev), созданное из скомбинированных устройств, используя либо зеркалирование, либо RAID-Z. Однажды создав vdev-ы, вы скомбинируете их в пул хранения. Этот подход обеспечивает некоторую гибкость. Если у вас есть некоторые данные, доступ к которым должен быть быстрым и которые должны надежно храниться, вы можете создать в большей степени зеркалируемый пул и пул RAID-Z, а также создать файловые системы из какого-либо лучшего набора. Учтите, что файловые системы не должны быть размещены рядом на vdev; пока они могут казаться близкими блоками хранящегося пространства на высоких слоях, они могут не быть близкими вообще.

Одна из ключевых идей проектирования ZFS заключалась в том, что создание раздела должно быть таким же простым, как создание директории. Например, это дает возможность реализовать квоты в ZFS, дав каждому пользователю собственный раздел для домашней директории, который будет расти динамически в пуле хранения.

В отличии от других менеджеров разделов, ZFS дает возможность точно определять планирование I/O. Каждая транзакция имеет определенный приоритет и срок окончания работы с обрабатываемым расписанием слоем vdev системы.

Объектный слой.

Средним слоем ZFS является слой работы с объектами. Основой этого слоя является Модуль Менеджмента Данных (DMU) и на многих диаграммах блоков ZFS DMU это все, что вы увидите от этого слоя. DMU ставит объекты на верхний слой и разрешает выполнение элементарных операций.

Если у вас когда-либо был сбой напряжения во время записи файла, возможно вы запускали fsck, scandisk или какую-нибудь подобную утилиту. В конце концов, вы, вероятно, восстановите несколько поврежденных файлов. Если они были текстовыми, то вам может быть повезло, повреждение может быть ликвидировано легко. Если файлы имели комплексную структуру, вы могли потерять эти файлы. Приложения, работающие с базами данных решают такую проблему использованием механизма транзакций, - они записывают что-то на диск, говоря "Я собираюсь это сделать", и делают это. Затем они пишут "Я это сделал" в лог. Если что-то пойдет не так где-то на середине, такое приложение может просто откатиться назад, к состоянию перед стартом.

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

ZFS использует модель транзакций. Вы можете начать транзакцию, выдавая число записей, и они либо все завершатся успешно, либо все не завершатся. Это возможно за счет использования механизма копирование-на-записи. Каждый раз, записывая некоторые данные, ZFS записывает эти данные в запасное место диска. Затем, она обновляет метаданные, говоря "Это новая версия". Если процесс записи не пройдет стадию обновления метаданных, никаких записей поверх старых данных производиться не будет.

Одна из сторон эффекта от использования копирование-на-записи заключается в том, что это позволяет постоянно по времени создавать снапшоты. Некоторые файловые системы, такие, как UFS2 на FreeBSD и XFS на IRIX, уже поддерживают снапшоты, так что это не новая концепция. Стандартная технология создает партиции для снапшотов. Один раз сделав снапшот, каждая операция записи заменяется в соответствии с копированием оригинала на партицию со снапшотом и только потом осуществляет запись. Лишним будет говорить, что этот подход довольно-таки дорогой.

С ZFS, все, что вам нужно для создания снапшота - это увеличить счетчик ссылок партиции. Каждая операция записи уже недеструктивна, и единственное, что может произойти - это то, что операция обновления метаданных не удалит ссылки на старое местоположение. Другая сторона эффекта от использования этого механизма заключается в том, что снапшоты являются файловыми системами первого класса со своими собственными правами. Вы можете делать запись на снапшот точно также, как и на любой другой раздел. Например, вы можете создать снапшот файловой системы для каждого пользователя и разрешить им делать все, что они захотят, без помех для других пользователей. Эта возможность имеет пользу на практире в совместном использовании с Solaris Zones.

Претендуя на то, чтобы быть файловой системой.

Все это прекрасно, иметь базирующуюся на объектах, транзакционную систему хранения данных, но кто собирается это использовать? Все мои приложения хотят использовать что-то, что похоже на файловую систему UNIX. И тут в дело вступает ZPL, POSIX слой в ZFS. ZPL предоставляет соответствие между файловыми операциями POSIX (read, write и т.д.) и операциями DMU. Это дает возможность управления структурой директорий и позволяет использование прав доступа.

Вдобавок к ZPL, в ZFS есть другой модуль в слое интерфейса, известный как ZVOL. Этот слой дает более простое соответствие; вместо того чтобы создавать видимость POSIX-совместимой файловой системы, он кажется необработанным блочным устройством, которое полезно для реализации существующих файловых систем, поддерживаемых пулами хранения ZFS. Порт FreeBSD изначально использует существующую файловую систему UFS2 поверх устройства с ZVOL. Я думаю, что порт от Apple будет использовать HFS+ поверх ZVOL для того, чтобы дать Apple поддержку метаданных HFS+.

Некоторые интригующие возможности доступны для будущей работы в этом слое. Поскольку ZFS уже поддерживает транзакции, возможно, что SQL или похожий интерфейс может быть использован в этом слое. Исходя из низкой стоимости создания файловых систем, каждый пользователь может создать базы данных на лету и получить гораздо более гибкий интерфейс, чем предоставляемый слоем POSIX. Проблема WinFS от Microsoft в том, что она слишком сложна для того, чтобы обеспечить всем поддержку реализаций, которые не основаны на файлах и не будет там применяться, поскольку это приведет к увеличению средств, вместо замены текущей файловой системы (тут бред получился - примеч. переводчика).

Что она не делает?

В настоящее время, наибольшим недостатком ZFS является недостаток шифрования.
В NTFS шифруется каждый файл, и у большинства менеджеров разделов имеются механизмы шифрования на уровне блока. К счастью, выход был найден и ZFS может использовать такой же механизм, который уже реализован, для поддержки компрессии.

Хорошо разделенные квоты также не поддерживают. Вы можете создавать разделенные разделы с максимальным размером, но мы не можете установить максимальное число файлов, которое пользователь может создать в разделе.

Последнее слово в RAID?

Одно из самых волнующих возможностей ZFS - это RAID-Z. Это массив, состоящий из блоков фиксированного размера, с которого может происходить чтение или запись. С тех пор, как RAID обычно реализуется близко к блочному слою (часто на уровне аппаратного обеспечения, открыто к операционной системе), устройства RAID также предоставляют этот интерфейс. В массиве RAID-5 с тремя дисками, запись блока вызывает сохранение блока на диск 1, а результат XOR-а блока, соответственно, один из дисков 2 или 3. Это вызывает две взаимосвязанных проблемы:
Если вы счастливчик, вы можете гарантировать выполнение простейших операций записи на один диск, но почти невозможно получить возможность простейших записей на группу дисков. Если что-то нарушится между записью первого блока и контрольной суммой, система будет содержать невозможный для этого блока индекс на всех дисках. Современные RAID-контроллеры обходят эту проблему путем хранения записей в энергонезависимой RAM, до тех пор, пока они не получать подтверждение от диска о том, что данные были сохраненны.

Вышеупомянутый сценарий, записывание одного блока на диск 1 требует, чтобы вы затем считали блок с диска 2 и сохранили контрольную сумму на диск 3. Эта дополнительная операция чтения в середине каждой записи может быть дорогой.

Так что же RAID-Z делает по-другому? Во-первых, массив RAID-Z не настолько туп, как массив RAID; у него есть некоторая осведомленность о том, что в нем хранится. Ключевая составляющая - категория - переменной ширины. С существующими реализациями RAID, она составляет либо 1 байт (например, каждый нечетный байт будет записан на диск 1, каждый четный - на диск 2, а каждый сравнимый по модулю - на диск 3), либо величину, равную длине блока. В ZFS этот размер категории определяется размером записи. Каждый раз когда вы производите запись на диск, вы полностью записываете категорию.

Такое строение решает обе проблемы, указанных выше. С тех пор, как ZFS транзакционна, категория либо записывается корректно и метаданные обновляются, либо нет. Проще говоря, поскольку категория содержит только данные, состоящие на записи, вам никогда не понадобится считывать что-то с диска для осуществления записи.

RAID-Z стал возможен только за счет новой структуры слоев ZFS. Вы можете восстановить раздел RAID-5, когда диск сломается, получив "XOR всех битов на индексе 0 на каждом диске в сумме дает 0, так что должен содержать наш пропавший диск?". С RAID-Z это невозможно. Вместо этого, вам надо будет прослеживать метаданные файловой системы. Контроллер RAID, который является блочным устройством не будет иметь возможности это сделать. Один из добавленных бонусов это то, что аппаратный контроллер RAID при запросе на восстановление, должен воссоздать диск, даже те блоки, которые не использовались, в то время, как RAID-Z нужно восстановить только использовавшиеся блоки.

Не являясь частью RAID-Z, ZFS включает в себя ещё одну возможность, которая помогает решить проблемы потери данных: так как каждый блок содержит хеш SHA256, поврежденный сектор на диске будет отображаться, как содержащий ошибки, даже если котроллер диска этого не замечает. Это превосходство над существующими реализациями RAID. Используя RAID-5, например, вы можете восстановить раздел, но если одиночный сектор на диске поврежден, весь диск может сообщить о существующей ошибке. Раздел RAID-Z может сообщить вам, какой диск содержит ошибку (тот, чей блок не соответствует хешу) и восстановить данные с другого. Он также может сообщать заранее о том, какой диск может быть поврежден.

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

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

Как я могу это получить?

Будет ли ZFS доступна для вашей операционной системы? Для пользователей [Open]Solaris ответ будет "да", для остальных - "может быть". Если вы используете Windows, то возможно нет. Для Linux ситуация не намного лучше. Реализация OpenSolaris выпускается под лицензией CDDL, с которой не совместима GPL. Существует две возможности поддержки этой файловой системы на Linux. Первая: сделать полностью собственную реализацию, что потребует огромных усилий и поэтому вряд ли возможно в ближайшее время. Другая заключается в том, чтобы портировать её в FUSE и запускать, как пользовательский процесс. Эта работа находится в процессе реализации, но похоже, что результат будет значительно медленнее версии, реализованная на уровне ядра и невозможен к использованию на загрузочных разделах. Пользователи Ubuntu, желающие поддержки ZFS, могут переключиться на Nexenta, в которой используется ядро OpenSolaris и пользовательское окружение GNU.

CDDL - однофайловая лицензия, она не влияет на общую лицензию проекта, что позволяет использовать её в больших количествах проектов, у которых нет лицензии, указывающей, что "все компоненты этого проекта должны быть лицензированы под лицензией, приветствующей эти утверждения". Эти требования позволяют FreeBSD и DragonFlyBSD разрабатывать порты ZFS, и MacOS X - где также ожидается поддержка ZFS.

Обновлено: 12.03.2015