У меня есть аппаратная система RAID-6 размером 30 ТБ (LSI 9280-8e) из 10 твердотельных накопителей Intel DC-S4500, которая используется для баз данных. ОС Debian 7.11 с ядром 3.2. Файловая система смонтирована в XFS без опций барьера.
Увидев несколько медленную по сравнению с моими ожиданиями производительность при случайном вводе-выводе, я начал исследовать, что происходит, запустив тесты fio. И, к моему удивлению, когда я просто использовал fio для файла размером 1 ТБ в настройках случайного чтения с (iodepth = 32 и ioengine = libaio), я получил ~ 3000 операций ввода-вывода в секунду, что намного ниже, чем я ожидал.
random-read: (groupid=0, jobs=1): err= 0: pid=128531
read : io=233364KB, bw=19149KB/s, iops=4787 , runt= 12187msec
...
cpu : usr=1.94%, sys=5.81%, ctx=58484, majf=0, minf=53
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=99.9%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued : total=r=58341/w=0/d=0, short=r=0/w=0/d=0
Однако, если я использую параметр direct = 1 (то есть в обход буферного кеша Linux), я получаю ~ 40000 IOPS, что я бы хотел видеть.
random-read: (groupid=0, jobs=1): err= 0: pid=130252
read : io=2063.7MB, bw=182028KB/s, iops=45507 , runt= 11609msec
....
cpu : usr=6.93%, sys=23.29%, ctx=56503, majf=0, minf=54
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued : total=r=528291/w=0/d=0, short=r=0/w=0/d=0
Кажется, у меня есть все правильные настройки для раздела SSD в виде планировщика, упреждающего чтения и настройки вращения.
root@XX:~# cat /sys/block/sdd/queue/scheduler
[noop] deadline cfq
root@XX:~# cat /sys/block/sdd/queue/rotational
0
root@XX:~# blockdev --getra /dev/sdd
0
Мне все еще не хватает чего-то, что сильно снижает производительность буферизации? Или ожидается увидеть такую разницу между DIRECT и buffered?
Я также посмотрел на вывод iostat во время двух прогонов. Это когда использовалось direct = 1:
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdd 0.00 0.00 48110.00 0.00 192544.00 0.00 8.00 27.83 0.58 0.58 0.00 0.02 99.60
Это буферный прогон
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdd 0.00 0.00 4863.00 0.00 19780.00 0.00 8.13 0.89 0.18 0.18 0.00 0.18 85.60
Таким образом, похоже, что ключевым отличием является размер очереди (avgqu-sz), который невелик при использовании буферизованного ввода-вывода. Я нахожу это странным, учитывая, что nr_requests и queue_depth все высоки:
root@XX:~# cat /sys/block/sdd/queue/nr_requests
128
root@XX:~# cat /sys/block/sda/device/queue_depth
256
Есть здесь какие-нибудь советы?
Debian 7.11 с ядром 3.2
Обновите, если возможно. Вы не только получаете улучшения ядра, но и Wheezy - это конец жизни.
Да, вы видите более высокую загрузку и глубину очереди, когда direct = 1. В руководстве по fio этот случай особо упоминается (выделено мной):
iodepth = int
Количество модулей ввода-вывода, которые нужно держать в движении для файла. Обратите внимание, что увеличение iodepth выше 1 не повлияет на синхронные ioengine (за исключением малых степеней, когда используется verify_async). Даже асинхронные механизмы могут налагать ограничения ОС, в результате чего желаемая глубина не может быть достигнута. Это может произойти в Linux при использовании libaio без установки direct = 1, поскольку буферизованный ввод-вывод не является асинхронным в этой ОС. Следите за распределением глубины ввода / вывода в выводе fio, чтобы убедиться, что достигнутая глубина соответствует ожиданиям.
Итак, libaio требует O_DIRECT для асинхронной работы, что необходимо знать о важной детали реализации. Кто-то спросил, не было ли хорошей идеей напрямую с libaio:
Допустимо ли установить direct = 0 при использовании libaio?
Вы можете это сделать, но я бы не рекомендовал это. С сегодняшними ядрами Linux отправка libaio, скорее всего, станет блокирующей (и, следовательно, больше не будет асинхронной) без O_DIRECT, который может ограничить количество достигаемого параллельного ввода-вывода. Есть веский аргумент в пользу того, что примеры fio НЕ должны поощрять такую комбинацию вариантов ...
что означает поведение "в очереди" в man doc?
Если вы имеете в виду предложение «Обратите внимание, что Linux может поддерживать поведение в очереди только с небуферизованным вводом-выводом» (см. http://fio.readthedocs.io/en/latest/fio_doc.html#i-o-engine ) Думаю, это пытается сказать:
"Вместо того, чтобы блокировать системный вызов отправки до тех пор, пока ввод-вывод не прекратится и не вернется с самого нижнего дискового устройства (поведение блокировки), при использовании direct = 1 с libaio вы можете отправить ввод-вывод и поставить его в асинхронную очередь в очередь ядро, позволяющее системному вызову отправки немедленно вернуться и открывающее вам возможность поставить в очередь другие отправления до завершения ввода-вывода ».
Также попробуйте контрольный тест с ioengine = psync и direct = 0. Даже синхронная запись в кеш может выполнять большое количество операций ввода-вывода в секунду.
Все это обходит стороной реальный вопрос: в чем заключалась проблема с рабочей нагрузкой базы данных, которую вы выполняли? Симптомы проблемы, версии программного обеспечения, конфигурация, показатели производительности (iostat). Реализация ввода-вывода СУБД может сильно отличаться от того, что вы имитировали, используемых системных вызовов, нескольких файлов и заданий, выполняющих ввод-вывод, любого количества вещей. Это заслуживает отдельного вопроса, если вы хотите продолжить расследование.