Вопрос или проблема
Я пытаюсь настроить MD RAID1 (используя mdadm) с параметром --write-mostly
, чтобы сетевой (EBS) том и локальный диск были зеркалами друг друга (идея заключается в том, что локальный диск является эпhemeral для моего экземпляра, но имеет лучшую производительность).
Чтобы оценить эту идею, я получаю базовую оценку производительности своего диска, используя следующие два скрипта.
fio -name=RandWrite -group_reporting -allow_file_create=0 \
-direct=1 -iodepth=128 -rw=randwrite -ioengine=io_uring -bs=32k \
-time_based=1 -ramp_time=10 -runtime 10 -numjobs=8 \
-randrepeat=0 -norandommap=1 -filename=$BENCHMARK_TARGET
# Производительность чтения
fio -name=RandRead -group_reporting -allow_file_create=0 \
-direct=1 -iodepth=128 -rw=randread -ioengine=io_uring -bs=32k \
-time_based=1 -ramp_time=10 -runtime 10 -numjobs=8 \
-randrepeat=0 -norandommap=1 -filename=$BENCHMARK_TARGET
Результаты:
- Сетевой диск: 117 MiB/s запись, 117 MiB/s чтение
- Локальный диск: 862 MiB/s запись, 665 MiB/s чтение
Проблема возникает, когда я ввожу mdadm. Даже при использовании тривиального “RAID1” без зеркалирования производительность записи значительно ухудшается при использовании сетевого диска.
mdadm --build /dev/md0 --verbose --level=1 --force --raid-devices=1 "$TARGET"
# mdadm --detail /dev/md0
/dev/md0:
Версия :
Время создания : Пн Сент 30 14:22:41 2024
Уровень RAID : raid1
Размер массива : 10485760 (10.00 GiB 10.74 GB)
Используемый размер устройства : 10485760 (10.00 GiB 10.74 GB)
Устройства RAID : 1
Всего устройств : 1
Состояние : чистое
Активные устройства : 1
Рабочие устройства : 1
Неисправные устройства : 0
Резервные устройства : 0
Политика согласованности : повторная синхронизация
Номер Основной Вторичный Устройство RAID Состояние
0 8 16 0 активная синхронизация /dev/sdb
- 0-зеркало RAID1, поддерживаемый сетевым диском: 69.9 MiB/s запись, 118 MiB/s чтение
- 0-зеркало RAID1, поддерживаемый локальным диском: 868 MiB/s запись, 665 MiB/s чтение
Как мы видим, производительность записи практически не изменилась для локального диска (MD-raid против сырого доступа), но она значительно ухудшена при использовании сетевого диска через MD-raid. Почему это происходит?
Не зная точную реализацию mdadm, я напишу свою обоснованную догадку по этому поводу.
Я думаю, что в настройке RAID 1 подсистема RAID ждет, когда оба диска подтвердят операции записи, прежде чем обрабатывать следующие файловые события. И тогда могут быть дополнительные задержки, вызванные несоответствием производительности между дисками, что в дальнейшем будет способствовать скорости записи 69.9 MiB/s против 117 MiB/s.
Я не думаю, что целесообразно создавать RAID-массивы с устройствами, у которых скорость доступа сильно различается. RAID не был разработан для этого случая использования.
Вам может быть полезно рассмотреть кластерную файловую систему, такую как GFS2 или OCFS2; они могут быть лучше подходящими для вашего случая использования.
Насколько я могу судить, это режим отказа, вызванный перегрузкой модуля ядра MD IOPS.
Когда я изменил свои скрипты, чтобы использовать iodepth=64 numjobs=1, я не наблюдал потерь в производительности на сырых дисках, и влияние на производительность записи RAID1 исчезло.
Вот финальные скрипты:
fio -name=RandWrite -group_reporting -allow_file_create=0 \
-iodepth=128 -numjobs=8 \
-direct=1 -rw=randwrite -ioengine=io_uring -bs=16k \
-time_based=1 -ramp_time=10 -runtime 10 \
-randrepeat=0 -norandommap=1 -filename=$1
fio -name=RandRead -group_reporting -allow_file_create=0 \
-iodepth=$IODEPTH -numjobs=$NUMJOBS \
-direct=1 -rw=randread -ioengine=io_uring -bs=16k \
-time_based=1 -ramp_time=10 -runtime 10 -randrepeat=0 \
-norandommap=1 -filename=$1
А вот итоговые результаты:
Метрика | iodepth=128 numjobs=8 |
iodepth=64 numjobs=1 |
---|---|---|
Локальный диск, запись | 629 | 766 |
Локальный диск, чтение | 754 | 877 |
Облачный диск, запись | 117 | 117 |
Облачный диск, чтение | 118 | 117 |
RAID1, локальный, запись | 526 | 775 |
RAID1, локальный, чтение | 751 | 853 |
RAID1, облачный, запись | 59 | 117 |
RAID1, облачный, чтение | 115 | 117 |
RAID1, оба, запись | 61 | 117 |
RAID1, оба, чтение | 755 | 879 |
Я предполагаю, что слишком большое количество IOPS в сочетании с более медленным диском приводит к чрезмерной длине очереди, что затем приводит к какому-то виду конфликтов блокировки в модуле ядра. Но я не знаю достаточно деталей, чтобы быть уверенным. Что я узнал, так это то, что мне понадобится более точный бенчмарк, чтобы правильно оценить, подходит ли этот подход для моего случая использования.
Ответ или решение
MD RAID1 значительно медленнее, чем работа с сырым сетевым диском, по нескольким причинам, связанным с особенностями реализации управления дисками и архитектурой RAID.
Причины медленной записи в MD RAID1
-
Синхронизация записи:
В формате RAID1 данные, записываемые на один диск, должны быть дублированы на второй. Это означает, что система ждет подтверждения записи с обоих дисков, прежде чем переходить к следующему блокированию операций. Когда один из дисков представляет собой сетевое хранилище (например, EBS), которое, как правило, медленнее, чем локальный диск, это создает узкое место, поскольку операции записи задерживаются до тех пор, пока оба диска не подтвердят выполнение операции. -
Различие в производительности дисков:
Использование RAID-структуры с дисками, обладающими значительно различающейся производительностью, может привести к проблемам. Как вы правильно заметили, MD RAID1 была изначально спроектирована для использования с дисками с аналогичной производительностью. Ваша сеть может иметь определенные задержки и пропускную способность, которые вниз по лесенке могут уменьшить общую производительность массива. -
Задержки от сетевых операций:
Работа с сетевым диском добавляет дополнительные задержки, связанные с сетью, которые не наблюдаются при локальных операциях. Особенно это заметно в сценариях с высокой IOPS, где сетевые диски могут не справляться с нагрузкой, создавая дополнительные задержки. -
Нагрузка и IOPS:
Как вы уже подметили, при увеличении глубины очереди (iodepth) и количества заданий (numjobs) вы можете столкнуться с перегрузкой системы, что в свою очередь приводит к увеличению задержек и блокировок на уровне ядра. Это может вызывать контенцию и снижать общую доступную пропускную способность системы.
Рекомендации для улучшения производительности
-
Оптимизация конфигурации тестирования:
Лучше всего проводить тесты с большим количеством небольших операций записи, чтобы лучше понять, как система справляется с нагрузкой. Вы уже сделали шаг в правильном направлении, уменьшив iodepth и numjobs, что позитивно сказалось на производительности. -
Использование файловой системы кластера:
Рассмотрите возможность использования файловых систем, таких как GFS2 или OCFS2, которые могут быть оптимизированы для работы в сетевых средах, предоставляя лучшую поддержку параллельных операций записи и чтения. -
Настройка RAID1:
По возможности следует использовать RAID с устройствами, обладающими близкой производительностью, чтобы избежать описанных задержек и узких мест.
Общий вывод: Для достижения стабильной и высокой производительности следует внимательно подходить к выбору и конфигурации дисковых массивов RAID, учитывая характер нагрузки и производительность используемых устройств.