Вопрос или проблема
Многие ресурсы в интернете содержат противоречивую информацию относительно логики чтения/записи для RAID-чанков.
Этот ответ содержит следующие (на первый взгляд противоречивые) утверждения:
Размер чанка 512 КБ не требует от системы записи, например, 512 КБ для каждой записи на 4 КБ или чтения 512 КБ с поверхности устройства для чтения 4 КБ приложением.
[При чтении 16-КиБ блока из RAID с размером чанка 64-КиБ] RAID выполнит операцию чтения/изменения/записи при записи этого файла на 4 КБ/16-КиБ блока, потому что наименьшая единица хранения RAID составляет 64-КиБ.
С другой стороны, этот ресурс содержит следующие данные:
Например, если у вас есть текстовый файл размером 10 КБ, и размер чанка составляет 256 КБ, то эти 10 КБ данных хранятся в блоке размером 256 КБ, при этом остальная часть блока остается пустой. В свою очередь, с чанками по 16 КБ будет гораздо меньше неиспользуемого пространства при хранении этого файла на 10 КБ.
В частности, у меня есть следующие вопросы:
- При чтении/записи некоторой единицы данных меньшего размера, чем размер чанка RAID, с использованием схемы без четности, требуется ли это чтение/изменение/запись для всего чанка или только для той части чанка, которая изменяется?
- При использовании схемы RAID с четностью, изменится ли что-либо в ответе на вопрос 1?
- Как упоминалось во втором источнике, оставляет ли запись единицы данных меньшего размера, чем чанк RAID, каким-то образом остальную часть чанка RAID пустой? Это кажется мне неправильным, но я хотел уточнить, так как этот ресурс неоднозначно утверждает это.
- Меняются ли какие-либо из этих ответов в зависимости от реализации RAID (ядро Linux, аппаратный RAID и т.д.)?
Если возможно, было бы замечательно предоставить какую-либо авторитетную ссылку (какая-либо спецификация RAID, исходный код и т.д.).
Спасибо заранее!
Размер чанка в первую очередь определяет, как данные распределяются по устройствам (на какое физическое устройство и смещение нужно смотреть, если вы хотите прочитать байт 1234567890 на вашем RAID-устройстве).
Это не напрямую влияет на алгоритм RAID, который в случае RAID 5 является простой операцией XOR, также известной как побитовый XOR. Математически это работает на битах и, следовательно, не зависит от байтов, секторов или чанков. RAID 6 немного более сложен, но все равно в достаточной степени похож.
Таким образом, нет необходимости обрабатывать весь чанк.
Для RAID на основе Linux mdadm вы можете попробовать проверить это экспериментально:
Создайте несколько виртуальных дисков (используя разреженные файлы):
# truncate -s 1G {1..8}.img
# for img in {1..8}.img; do losetup --find --show "$img"; done
/dev/loop{1..8}
Создайте mdadm RAID 6 поверх (используя --assume-clean
, чтобы ничего не писать, кроме метаданных):
# mdadm --create --assume-clean --level=6 --raid-devices=8 --data-offset=2048 /dev/md42 /dev/loop{1..8}
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md42 started.
Небольшая запись в случайное смещение:
# blockdev --getsize64 /dev/md42
6429868032
# echo $((SRANDOM % 6429868032))
2931013558
# echo -n TEST | dd bs=1 seek=2931013558 of=/dev/md42
# sync
# echo 3 > /proc/sys/vm/drop_caches
Результат:
# filefrag {1..8}.img
1.img: 1 extent found
2.img: 1 extent found
3.img: 2 extents found
4.img: 1 extent found
5.img: 2 extents found
6.img: 2 extents found
7.img: 1 extent found
8.img: 1 extent found
Все изображения имеют 1 экстент (для метаданных mdadm), поэтому вы можете его игнорировать. Только у 3 изображений 2 экстента (данные, четность 1, четность 2). Следовательно, только они были записаны.
# filefrag -v -e 3.img 5.img 6.img
File size of 3.img is 1073741824 (262144 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 1.. 1: 301057.. 301057: 1: 1: merged
1: 119739.. 119739: 318395.. 318395: 1: 420795: last,merged
3.img: 2 extents found
Как вы можете видеть, экстент — это один сектор, а не чанк.
Сырые данные выглядят так:
# hexdump -C 3.img
*
1d3bb7b0 00 00 00 00 00 00 54 45 53 54 00 00 00 00 00 00 |......TEST......|
1d3bb7c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
# hexdump -C 5.img
*
1d3bb7b0 00 00 00 00 00 00 54 45 53 54 00 00 00 00 00 00 |......TEST......|
1d3bb7c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
# hexdump -C 6.img
*
1d3bb7b0 00 00 00 00 00 00 29 24 59 29 00 00 00 00 00 00 |......)$Y)......|
1d3bb7c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
Поскольку все данные равны нулю, четность RAID 5 для TEST
по-прежнему равна TEST
. Для четности RAID 6 TEST
трансформировался в )$Y)
.
Вы можете расширить этот эксперимент, заполнив массив случайными данными, затем записывая только {4,16,512,4096,16384} байт нуля в/около целевого смещения только для одного или нескольких из этих 3 устройств, а затем повторить эксперимент.
Таким образом, вы сможете определить, что mdadm не работает на уровне единиц байтов (но все же не выходит за пределы секторов, не говоря уже о целых чанках).
Вы также можете заметить, что он записывает неправильную четность, если четность уже была неправильной перед записью (четность обновляется с использованием четности, а не пересчитывается из данных).
Большое спасибо пользователю https://unix.stackexchange.com/users/30851/frostschutz, который рассказал, как просто поиграть с RAID, не покупая много контроллеров и дисков, в первую очередь 🙂
Чтобы ответить на конкретные вопросы:
-
Пожалуйста, различайте операции чтения-изменения-записи, требуемые для работы RAID, и операции чтения-изменения-записи, требуемые файловой системой. Последние могут происходить, когда системный вызов
write()
записывает данные, которые начинаются или заканчиваются посередине сектора диска, и этот сектор отсутствует в памяти, выделенной под кеш диска. Такие события редки, однако: большинство нормальных приложений записывают только в конец файлов, и файловый кеш Linux использует высокий приоритет для секторов, наполовину заполненных, находящихся в конце файлов, которые открыты для записи. Большинство баз данных действительно записывают в середине файлов, но обычно выполняя операцию чтения-изменения-записи в пользовательском пространстве. Секторы, которые только что былиread()
, обычно все еще находятся на момент, когда база данных выдает соответствующийwrite()
, чтобы обновить набор данных или запись индекса.Размер секторов, которые файловая система читает или записывает, не меняется RAID между файловой системой и диском. Все чтения и записи по-прежнему происходят на секторах, а не на чанках или полосах!
-
В RAID без четности ни чтение секторов, ни запись не требуют дополнительных циклов чтения-изменения-записи. Все, что необходимо, — это сопоставить каждый логический номер сектора из RAID с фактическим физическим диском и номерами секторов этих дисков. Для RAID0 это сопоставление 1 : 1, поэтому каждое
read()
илиwrite()
сектора из/в RAID0 становитсяread()
сектора из/в одного из дисков в RAID0. Для RAID1 и RAID10 это сопоставление 1 : N, где N — это параллелизм RAID. Дляread()
система сопоставляет это с одним из дисков в RAID1/10. Она может применять некоторые методы повышения производительности, чтобы выбрать оптимальный диск, например, тот, который уже имеет ожидающие запросы к физическим секторам, близким к запрашиваемому сейчас, или, в противном случае, к диску с низким количеством ожидающих запросов. Дляwrite()
все сопоставленные сектора будут записаны, чтобы сохранить избыточность.Но снова, нет необходимости читать или записывать данные из остальной части полосы, чтобы прочитать или обновить некоторые сектора внутри полосы.
-
В RAID с четностью, в частности RAID5 и RAID6 (никто не должен использовать RAID4 больше), все логические чтения из RAID снова напрямую сопоставляются с конкретным сектором на физическом диске, и только этот сектор будет записан. В (редком) случае, если чтение попадает на вышедший из строя диск, все соответствующие сектора на невыставленных дисках и хотя бы один диск четности (или оба диска четности в случае двух вышедших из строя дисков на RAID6) должны быть восстановлены.
При логических записях в RAID5/6 система должна записать фактический сектор на тот диск, с которым он сопоставлен, но также обновить четность на одном (RAID5) или двух (RAID6) дисках, которые несут четность для этого конкретного сектора. Существуют два способа обновления четности: либо система может прочитать соответствующие сектора на всех остальных дисках, которые сопоставляются с той же четностью, а затем пересчитать четность после загрузки всех данных. Либо она может прочитать старые данные сектора, который обновляется, перед его перезаписью, и вычислить обновление четности (как операция XOR), полученное в результате. Затем она может прочитать старые данные четности с диска четности, применить к ним обновление четности и затем снова записать их. Конечно, каждое из этих чтений в этих операциях чтения-изменения-записи может быть пропущено, если старые данные уже присутствуют в кеше памяти.
-
Файловая система организует данные в секторах в качестве наименьшей единицы. Подлежащая RAID полоса не меняет этого. Никакое пространство не будет потеряно, если размер полосы больше, чем размер сектора. Обратите внимание, что общая пропускная способность может быть немного выше, если типичные записи соответствуют ровно одной полосе на границе полосы. Поэтому, если RAID, например, используется напрямую с базой данных (без файловой системы между), может быть целесообразно сопоставить размер полосы и размер блока базы данных. Для файловых систем ext4 параметр “extsize” должен быть установлен на размер полосы RAID, что снова предпочтительно для размещения, выровненного с полосами RAID. Тем не менее, ни один из этих мер не ведет к потере пространства.
-
Мои ответы относятся к программному RAID Linux. Все приличные аппаратные RAID также будут в основном одинаковыми. Дополнительной особенностью большинства аппаратных RAID являются большие кэш-памяти, которые хранят данные для записи. Часто они содержат резервные батареи, чтобы сохранить данные в кеше в случае внезапного отключения питания.
Ответ или решение
RAID (Redundant Array of Independent Disks) — это технология, которая объединяет несколько жестких дисков в одно логическое устройство для повышения производительности, надежности или обоих этих параметров. Отвечая на ваши вопросы о том, читается ли и записывается ли всегда целый блок в RAID, начнем с основ.
-
Чтение/запись данных меньшего размера, чем размер блока RAID: В RAID без четности (например, RAID 0, RAID 1) операция чтения и записи действительно стремится работать на уровне секторов, а не целых блоков RAID. Это означает, что если вы запрашиваете операции записи или чтения данных меньшего размера, чем размер блока, то RAID отвечает на эти запросы, затрагивая только нужные сектора. Не требуется выполнять операции «чтение-модификация-запись» для всего блока RAID, а достаточно обновить соответственно только тот сектор, где находятся данные.
-
С RAID с четностью: При этом, когда используется RAID с четностью (например, RAID 5 или RAID 6), ситуация немного изменяется. Хотя RAID будет снова работать на уровне секторов, записывая или читая только нужные сектора, при записи данных, обновление четности требует выполнения операции «чтение-модификация-запись» на уровнях четности. То есть, чтобы обновить четность, традиционно RAID должен сначала прочитать нужные данные из других дисков (которые будут использоваться для пересчета новой четности), что приводит к дополнительной операции чтения перед записью. Тем не менее, если данные уже кэшируются в памяти, этот этап может быть минимизирован, что позволяет избежать ненужных чтений.
-
Пустое пространство в блоке RAID: Действительно, если вы запишите данные, меньшие по размеру, чем размер блока RAID, то оставшееся пространство не используется и, как результат, кажется «пустым». Однако это не означает, что данные «потеряны» — просто свободное пространство не может быть использовано для хранения других данных в рамках текущей записи. Это не считается потерей пространства в контексте RAID, поскольку данные не записываются неэффективно, это просто диспозиция оставшегося пространства.
-
Реализация RAID (Linux, аппаратный RAID и т.д.): Хотя основные принципы RAID применимы ко всем реализациям (как программным, так и аппаратным), конкретные механизмы могут варьироваться. Например, программный RAID, такой как mdadm в Linux, имеет информацию, которая иллюстрирует позже описанные принципы, в то время как аппаратные RAID контроллеры могут использовать свои собственные алгоритмы и кэширование, чтобы оптимизировать операции чтения и записи. Однако все они стремятся снизить нагрузку и выполнить операции по мере возможности на уровне секторов, а не блоков RAID.
В заключение, можно сказать, что RAID не всегда читает или записывает целый блок. Операции на уровне секторов позволяют значительно улучшить производительность. Однако, когда работа с четностью необходима, дополнительные операции чтения и записи могут потребоваться для корректного обновления информации.