Сквозная целостность данных в ZFS

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

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

Даже если предположить, что все диски идеальны и всегда возвращают то, что было записано ранее, данные все ещё будут уязвимы при передаче: ошибки в микрокоде контроллера, ошибки четности при DMA и т.д. Мы могли бы говорить только о том, что данные были целы, когда покидали пластину диска. Если рассматривать данные как посылку, это все равно что UPS говорила бы: "Мы гарантируем, что ваша посылка не была повреждена, когда мы приняли её". Это не совсем та гарантия, которая нам нужна.

Повреждение данных при передаче не есть предмет простого научного любопытства: даже такая приземлённая вещь, как неисправный источник питания может вызвать неявное повреждение данных.

Безосновательно дорогие массивы хранения данных не могут решить эту проблему. Путь прохождения операций ввода/вывода не только остаётся таким же уязвимым, но и становится длиннее: покидая пластину диска, данные должны уцелеть, несмотря на какие бы то ни было аппаратные и программно-аппаратные ошибки, которые могут содержаться в массиве.

А если ваш массив находится в SAN, вы используете сеть, спроектированную писателями микрокода дисков. Бог в помощь.

Что же делать? Одним из вариантов является сохранение контрольной суммы каждого блока на диске. Большинство современных дисковых накопителей могут быть отформатированы с размером сектора, который немного больше стандартных 512 байт -- обычно 520 или 528. Эти дополнительные байты можно использовать для хранения контрольной суммы блока. Сказать легко, но правильно использовать контрольную сумму сложнее: эфективность контрольной суммы крайне зависит от места хранения и момента проверки.

Во многих дисковых массивах (типичный пример с прекрасным описанием данного метода можно найти в статье о Dell|EMC PowerVault) данные сравниваются с контрольной суммой внутри массива. К сожалению, это не очень помогает справиться с проблемой. Такой способ не позволяет выявить типичные ошибки в микрокоде диска, такие как, например, фантомная запись (операция записи, которая не достигла диска, но была подтверждена как выполненная), так как данные и контрольная сумма хранятся вместе -- они непротиворечивы, даже если диск возвращает устаревшие данные. Да и весь путь ввода-вывода, который должны пройти данные от момена прочтения с пластины диска до момента попадания в память сервера (и наоборот) остается незащищенным. Короче говоря, такой вариант использования контрольной суммы блока есть лишь хороший способ убедиться в том, что надёжность массива ничуть не ниже надёжности дисков, в нём содержащихся, но не более того.

Способ использования контрольной суммы блока, применяемый NetApp, выглядит похоже, но на самом деле намного мощнее. Как и во многих других массивах, NetApp форматирует диски с секторами по 520 байт. Затем они группируются в блоки по 8 секторов: 4Кб данных (размер блока файловой системы WAFL) и 64 байта контрольной суммы. Когда система WAFL читает блок, данные сравниваются с контрольной суммой, как и в случае с массивом из предыдущего примера, но с ключевым отличием: сравнение происходит после того, как данные прошли весь путь ввода-вывода, что позволяет удостовериться в том, что блок прошел путь от пластины диска до памяти без повреждения.

Это существенное улучшение, но и его недостаточно. Контрольная сумма на уровне блока только доказывает, что блок цел сам по себе; она не доказывает, что это правильный блок. Повторяя нашу аналогию с UPS: "Мы гарантируем, что посылка, которую вы получили, цела. Но мы не гарантируем, что это ваша посылка."

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

Аутентификация данных в ZFS

Сквозная целостность данных требует проверки каждого блока данных с использованием независимой контрольной суммы, после прибытия данных в память. Недостаточно знать, что каждый блок является сам собой, или что он был корректен в какой-то момент прохождения по пути ввода/вывода в прошлом. Наша цель - выявлять любые возможные формы повреждения, включая такие человеческие ошибки, как использование диска с файловой системой в качестве области подкачки, или опечатки в аргументах команды dd(1). (Не приходилось ли вам место когда-нибудь вместо "if=" ввести "of="?)

Пул дисковой памяти в ZFS - это, на самом деле, дерево блоков. ZFS обеспечивает изоляцию сбоев между данными и контрольной суммой за счет хранения контрольной суммы каждого блока в указателе, указывающем на этот блок (указателе-родителе) -- а не в самом блоке. Каждый блок дерева содержит контрольные суммы всех "детей", таким образом, весь пул оказывается самоверифицирующимся. [Вершина иерархии - убер-блок (uberblock, корень дерева) - особый случай, так как он не имеет родителя; о том, как мы обращаемся с ним, поговорим в отдельной заметке.]

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

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

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

Но и это еще не всё!

Блоки пула дисковой памяти ZFS образуют дерево Меркле, в котором каждый блок проверяет всех своих "детей". Было доказано, что дерево Меркле обеспечивает криптографически стойкую аутнтификацию как для каждого компонента дерева, так и для всего дерева целиком. ZFS использует 256-битную контрольную сумму (алгоритм SHA-256) для каждого блока (метаданных) и проддерживает алгоритмы вычисления контрольных сумм для пользовательских данных начиная с простого и быстрого алгоритма fletcher2 (используемого по умолчанию) до медленного, но безопасного SHA-256. При использовании для пользовательских данных криптографически стойкого хеша, такого как SHA-256, контрольная сумма убер-блока является постоянно обновляющимся крипто-хэшем для всех данных в пуле.

А это будет очень удобно, если вам потребуется обратиться в UPS для пересылки пула.


Теги Technorati:
Comments:

Post a Comment:
Comments are closed for this entry.
About

bonwick

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today