«Воно каже 1 000 000 FPS.» Зазвичай так починається історія. Слайд, таблиця закупівлі, менеджер, якому просто треба закрити задачу, і система зберігання, яка — дивним чином — не може тримати базу даних менше ніж 30 мс під піком навантаження.
«Маркетингові FPS» (називайте це IOPS, FPS, транзакціями, «ops» або «до») — це число, яке постачальники використовують, коли хочуть, щоб ви припинили ставити питання. У продакшені це не має значення. У продакшені важливі латентність під навантаженням, хвостова поведінка, співвідношення читань/записів, робочий набір і те, що відбувається після охолодження кешу та коли система помірно нещасна.
Що насправді означають «маркетингові FPS» (і що вони приховують)
Коли постачальник каже «1M IOPS» (або їхній ребрендинг «FPS»), потрібно розуміти приховані умови:
- Розмір блока: майже завжди 4K (малі блоки роздувають кількість операцій).
- Шаблон: випадкове читання (читання простіше за запис; випадкове навантаження ховає обмеження послідовної пропускної здатності).
- Глибина черги: висока (глибокі черги накачують IOPS, поки латентність потайки зростає).
- Кеш: прогрітий, і інколи фактично не лягає на носій.
- Набір даних: вміщується в кеш або в SLC-буфер запису — дуже зручно.
- Тривалість: достатньо коротка, щоб уникнути поведінки в рівновазі (особливо для NAND і збору сміття).
- Диски: «топовий» бін-модель, а не те, що вам поставлять після квартальних змін у постачанні.
- Хост: сервер для бенчмарку, натюнений як гоночний болід, а не як ваш ферм VM.
Маркетингові числа не завжди брехня. Часто вони правдиві для вузького, підготовленого сценарію. Проблема в тому, що люди з закупівель трактують їх як гарантію для вашого робочого навантаження.
Ось реальність: IOPS — це не метрика ємності. Це точка на кривій. Змініть одну змінну — розмір блока, співвідношення читань/записів, глибину черги, локальність даних — і ви опинитесь на іншій кривій.
Швидка перевірка здорового глузду: якщо пристрій обіцяє величезні IOPS, але не може перемістити багато пропускної здатності, швидше за все це заголовок для 4K. Приклад: 1 000 000 IOPS при 4K — це близько 4 GB/s. Це реально, але тільки якщо все інше співпрацює і ви можете його «годувати».
Жарт №1: «До 1M IOPS» — як «до 200 миль/год» у прокатній машині: технічно можливо, соціально не схвально й без гарантії.
Прості правила, які вбережуть вас від проблем
Правило 1: Якщо у вас немає перцентилів латентності — у вас нема претензії по продуктивності
Просіть P50, P95, P99 latency при заявлених IOPS. Середня латентність — казка на ніч; хвостова латентність — справжній сюжет. Якщо постачальник не надає перцентилі при тих самих умовах, вважайте число IOPS декоративним.
Правило 2: Ставтеся до глибини черги як до ручки, яка міняє латентність заради заголовкових IOPS
Глибокі черги збільшують IOPS і роблять користувачів сумними. Ваш додаток зазвичай не працює при QD=128 на пристрій. Бази даних, пошук і сервіси запит/відповідь часто мають обмежену конкурентність і дбають про низьку латентність при помірній QD, а не про «максимальну пропускну здатність будь-якою ціною».
Правило 3: Розділяйте «сплеск» і «стійкий режим»
NVMe-диски, масиви й хмарні томи можуть виглядати героїчно 10–60 секунд. Потім вони падають до сталого стану. Вимагайте принаймні 30 хвилин тестування для записової навантаженості і переконайтесь, що пристрій у сталому стані (далі про це).
Правило 4: Якщо набір даних вміщується в кеш — ви тестуєте кеш
Кеш — це добре. Купувати сховище, щоб воно було кешем — теж добре, якщо це те, що ви планували. Але не тестуйте 20 GB на системі з 512 GB RAM і не називайте це «дисковою продуктивністю». Це «продуктивність RAM з додатковими кроками».
Правило 5: Вимагайте повний рецепт тесту (розмір блоку, rw mix, QD, потоки, час виконання, пре-кондиціювання)
Одне число без рецепту — це не бенчмарк; це слоган. Вимагаючи відтворюваний fio job file або еквівалент, ви отримуєте інструмент для інженерних рішень. Якщо вони не можуть дати такий файл — їхнє число непридатне для технічних висновків.
Правило 6: Використовуйте «латентність при потрібній пропускній здатності» як ціль для розрахунку
Ви не купуєте «максимальні IOPS». Ви купуєте здатність залишатися, скажімо, менше 5 ms P99 при піковому змішаному навантаженні. Почніть із ваших SLO і працюйте назад.
Правило 7: Слідкуйте за write amplification і garbage collection
Системи на флеш-пам’яті можуть деградувати при тривалих випадкових записах, особливо при високій заповненості. Попередньо кондиціонуйтe диски. Тестуйте при реалістичних рівнях заповнення. Питайте постачальника, що відбувається при 70% заповнення, а не при 7%.
Правило 8: Якщо заява ігнорує хост — вона неповна
Драйвери, multipathing, CPU, NUMA, обробка переривань, файлові системи й шифрування можуть стати вузьким місцем задовго до носія. Заява про сховище, яка не вказує обладнання й ПЗ хоста — лише половина твердження.
Правило 9: «IOPS» без співвідношення читань/записів — марна штука
70/30 чит/зап поводиться зовсім інакше, ніж 100% чит. Так само і 30/70. Якщо ваше навантаження змішане — бенчмарк має бути змішаним і критерії приймання теж.
Правило 10: Завжди тестуйте режим відмови, якого уникнути не вдасться
Ребілди трапляються. Фоновий scrub трапляється. Одна дорога відмирає. Один контролер перезавантажується. Якщо ви тестуєте тільки «сонячний день» — продакшен обов’язково запланує грозу.
Цікаві факти та контекст (маркетинг сховищ має історію)
- Факт 1: «IOPS» стали популярними, бо ранні дискові масиви могли приховувати поганий час пошуку за допомогою кешування і паралельних шпинделів — тож постачальникам потрібне було одне, підраховуване число для випадкового доступу.
- Факт 2: Індустрія стандартизувала заголовкове 4K випадкове читання частково тому, що воно добре лягає на розміри сторінок баз даних і дає більше операцій у порівнянні з 8K/16K.
- Факт 3: Бенчмарки сховищ суперечливі ще з часів SPEC і TPC; постачальники часто налаштовували конфігурації, щоб виграти прогін бенчмарку, а не відтворити типовий розгорт.
- Факт 4: Багато SSD використовують SLC write cache (навіть коли NAND — TLC/QLC). Це дає приголомшливі короткі сплески, які зникають у сталому стані.
- Факт 5: NAND flash вимагає erase-before-write на рівні блока; garbage collection і wear leveling — причина того, чому стійкий випадковий запис часто значно повільніший, ніж «з коробки».
- Факт 6: Глибина черги стала маркетинговим важелем, коли NVMe зробив глибоку паралельність дешевою; велика QD може тримати пристрій зайнятим, але також ховає сплески латентності, допоки ваш додаток не впаде.
- Факт 7: В еру HDD «15K RPM» диск міг давати приблизно 175–210 випадкових IOPS; масиви діставали десятки тисяч за рахунок страйпінгу по багатьом шпинделям і агресивного кешування.
- Факт 8: Хмарні томи часто мають явні burst credits або обмеження пропускної спроможності; продуктивність може бути контрактною, але обмеженою за часом, і короткі бенчмарки вводять в оману.
- Факт 9: Ранні RAID-контролери з батарейним кешем запису робили записи швидкими до моменту скидання кешу; «неочікуваний крах латентності» старший за багатьох сьогоднішніх SRE-команд.
Єдині метрики, які важливі в реальних системах
1) Перцентилі латентності (P50/P95/P99) у часі
Вам потрібний часовий ряд, а не одне зведення. Якщо P99 під час прогону йде вгору, ви бачите виснаження кешу, теплове тротлінг, garbage collection або фонову роботу.
2) IOPS і пропускна здатність разом
IOPS без MB/s — як система, що гарно виглядає на папері, але не може робити бекапи. Пропускна здатність без IOPS — як система, що чудово стрімить, але зависає на метаданих.
3) Глибина черги та конкурентність
Заміряйте ту IO-чергу, яку ви фактично використовуєте. Якщо додаток має лише 16 відкритих IO на вузол, бенчмарк при QD=256 не має значення.
4) Співвідношення чит/запис і локальність
Випадкове проти послідовного — не бінарна різниця. Багато навантажень «переважно послідовні з дратівливими випадковими метаданими», тому вони відчуваються нормальними допоки не стають такими.
5) Стійкий стан і рівень заповнення
Тестуйте при реалістичній заповненості і після пре-кондиціювання. Продуктивність флешу сильно залежить від того, наскільки він повний і «брудний».
6) Хвіст під конкуренцією
У продакшені є сусіди: фонові компакти, снапшоти, ребілди, scrubs, антивірус, лог-шейпінг, інші орендарі і ваші вікна патчування. Потрібні числа під невеликим болем, а не тільки під відсутністю болю.
Одна перефразована ідея, бо вона занадто правдива, щоб її ігнорувати: перефразована ідея
— Gene Kranz (директор польотів NASA) часто асоціюється з «failure is not an option», що в експлуатації перекладається як «тестуйте потворний шлях зараз, а не пізніше».
Практичні завдання: команди, виводи та рішення
Ось перевірки, які можна виконати на Linux-хості, щоб не бути загипнотизованим одним числом IOPS. Кожне завдання включає: команду, що означає типовий вивід, і рішення, яке ви приймаєте.
Завдання 1: Визначте пристрій зберігання та його модель (не тестуйте не те)
cr0x@server:~$ lsblk -o NAME,MODEL,SIZE,ROTA,TYPE,MOUNTPOINT,FSTYPE
NAME MODEL SIZE ROTA TYPE MOUNTPOINT FSTYPE
nvme0n1 Samsung SSD 990 PRO 1.8T 0 disk
├─nvme0n1p1 512M 0 part /boot ext4
└─nvme0n1p2 1.8T 0 part /data xfs
Що це означає: Ви на NVMe (ROTA=0), модель видна, і ви бачите, куди змонтовано.
Рішення: Бенчмаркуйте сирий пристрій або виділений тестовий файл на правильній файловій системі. Якщо модель не та, що ви очікували — зупиніться й виправляйте припущення закупівель/зборки хоста.
Завдання 2: Підтвердіть, що ядро бачить NVMe на очікуваній швидкості лінка та ширині
cr0x@server:~$ sudo nvme id-ctrl /dev/nvme0 | egrep -i 'mn|fr|mdts'
mn : Samsung SSD 990 PRO 2TB
fr : 5B2QJXD7
mdts : 9
Що це означає: Правильна модель/прошивка; MDTS підказує максимальний розмір трансферу. Це не повна перевірка лінка, але базова перевірка ідентичності.
Рішення: Якщо ідентифікація пристрою несподівана — не продовжуйте. Неправильна прошивка також може означати відоме тротлінг/помилкову поведінку; узгодьте з вашою платформною базою.
Завдання 3: Перевірте, чи диск не тротлить через нагрів (класичне «бенчмарк швидкий, закінчується сумно»)
cr0x@server:~$ sudo nvme smart-log /dev/nvme0 | egrep -i 'temperature|warning|critical'
temperature : 71 C
warning_temp_time : 12
critical_comp_time : 0
Що це означає: Диск досяг попереджувальної температури протягом 12 хвилин. Це великий червоний прапорець, що вказує на тротлінг.
Рішення: Виправте охолодження/повітряний потік/розташування у слоті перед тим, як вірити будь-якому «стійкому» тесту продуктивності.
Завдання 4: Перевірте опції монтування файлової системи (ви можете випадково тестувати журналювання або барʼєри)
cr0x@server:~$ mount | grep ' /data '
/dev/nvme0n1p2 on /data type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Що це означає: XFS з більш-менш типовими опціями; нічого явно неправильного.
Рішення: Якщо ви бачите несподівані опції (наприклад, sync або екзотичні зміни барʼєрів), вирівняйте з конфігурацією продакшену перед тестуванням.
Завдання 5: Подивіться, чи ви вже обмежені IO (висока завантаженість) до запуску fio
cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0 (server) 01/21/2026 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
12.1 0.0 4.2 8.7 0.0 75.0
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
nvme0n1 9.0 320.0 0.0 0.0 1.2 35.6 220.0 8200.0 6.9 1.8 92.4
Що це означає: %util близько 92% вказує, що пристрій майже насичений. w_await — 6.9 ms, а iowait — немалий.
Рішення: Якщо це продакшен-хост, ви вже можете бути на межі — тестування зараз примножить шум робочого навантаження в результатах. Для усунення проблем: зосередьтесь, хто виконує IO, і чи збігається латентність з вашим SLO.
Завдання 6: Знайдіть процеси, які генерують IO (не звинувачуйте сховище через баг у додатку)
cr0x@server:~$ sudo iotop -o -b -n 3
Total DISK READ: 0.00 B/s | Total DISK WRITE: 62.31 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
14221 be/4 postgres 0.00 B/s 41.72 M/s 0.00 % 65.12 % postgres: checkpointer
18802 be/4 root 0.00 B/s 18.49 M/s 0.00 % 22.30 % /usr/bin/rsync -a /var/lib/app/ /backup/
Що це означає: Postgres checkpointer і rsync роблять більшість записів. Це пояснювано, а не містично.
Рішення: Вирішіть питання планування/координації (перенести бекап, налаштувати чекпойнтинг) перед тим, як витрачати кошти на сховище.
Завдання 7: Виміряйте латентність напряму за допомогою fio (і зафіксуйте перцентилі)
cr0x@server:~$ sudo fio --name=randread4k --filename=/data/fio.test --size=40G --direct=1 --rw=randread --bs=4k --iodepth=16 --numjobs=4 --runtime=120 --time_based --group_reporting --ioengine=libaio --percentile_list=50:95:99:99.9
randread4k: (groupid=0, jobs=4): err= 0: pid=21401: Tue Jan 21 11:10:10 2026
read: IOPS=185k, BW=723MiB/s (758MB/s)(84.7GiB/120001msec)
clat (usec): min=62, max=4210, avg=334.18, stdev=91.22
lat (usec): min=64, max=4215, avg=336.49, stdev=91.30
clat percentiles (usec):
| 50.000000th=[ 331], 95.000000th=[ 470], 99.000000th=[ 620], 99.900000th=[ 980]
Що це означає: Гарні IOPS, і головне — P99 дорівнює 620 µs при цьому навантаженні. Це реальне інженерне число.
Рішення: Якщо ваш додаток потребує <2 ms — це підходить. Якщо потрібно <200 µs — зменшіть глибину черги, змініть архітектуру або використайте швидше медіа/топологію.
Завдання 8: Показати, як глибина черги роздуває IOPS, а латентність погіршується
cr0x@server:~$ sudo fio --name=randread4k_qd128 --filename=/data/fio.test --size=40G --direct=1 --rw=randread --bs=4k --iodepth=128 --numjobs=4 --runtime=120 --time_based --group_reporting --ioengine=libaio --percentile_list=50:95:99
randread4k_qd128: (groupid=0, jobs=4): err= 0: pid=21455: Tue Jan 21 11:13:01 2026
read: IOPS=420k, BW=1641MiB/s (1721MB/s)(192GiB/120001msec)
clat (usec): min=85, max=25000, avg=1188.74, stdev=655.10
clat percentiles (usec):
| 50.000000th=[ 1056], 95.000000th=[ 2200], 99.000000th=[ 3900]
Що це означає: IOPS більше ніж подвоїлися, але медіана латентності тепер ~1 ms, а P99 — 3.9 ms. Це пастка «маркетингових FPS» в одному екрані.
Рішення: Виберіть QD, що відповідає вашому навантаженню. Для латентнісно-чутливих сервісів приймайте менші IOPS, щоб утримати хвостову латентність в межах SLO.
Завдання 9: Тестуйте змішане навантаження (70/30), бо так виглядає реальне життя
cr0x@server:~$ sudo fio --name=mix70_30 --filename=/data/fio.test --size=80G --direct=1 --rw=randrw --rwmixread=70 --bs=8k --iodepth=32 --numjobs=8 --runtime=300 --time_based --group_reporting --ioengine=libaio --percentile_list=50:95:99
mix70_30: (groupid=0, jobs=8): err= 0: pid=21510: Tue Jan 21 11:20:01 2026
read: IOPS=110k, BW=859MiB/s (901MB/s)
clat percentiles (usec):
| 50.000000th=[ 540], 95.000000th=[ 1500], 99.000000th=[ 2800]
write: IOPS=47.1k, BW=368MiB/s (386MB/s)
clat percentiles (usec):
| 50.000000th=[ 810], 95.000000th=[ 2600], 99.000000th=[ 5200]
Що це означає: Записи повільніші й мають гірший хвіст латентності. Це нормально — і саме тому «100% read IOPS» не підходить для розрахунку бази даних.
Рішення: Якщо write P99 занадто високий, зменшіть write amplification (пакетування, розміщення WAL), додайте пристроїв або перейдіть на систему, оптимізовану для консистентних записів.
Завдання 10: Попередньо кондиціонуйте SSD перед довірою стійким записовим тестам
cr0x@server:~$ sudo fio --name=precond --filename=/dev/nvme0n1 --direct=1 --rw=write --bs=1M --iodepth=32 --numjobs=1 --runtime=1800 --time_based --ioengine=libaio --group_reporting
precond: (groupid=0, jobs=1): err= 0: pid=21602: Tue Jan 21 12:00:01 2026
write: IOPS=2900, BW=2900MiB/s (3041MB/s)(5100GiB/1800000msec)
Що це означає: Ви записали ~5 TB за 30 хвилин; ви штовхнули диск у більш реалістичний стан для наступних тестів випадкових записів.
Рішення: Якщо ви не можете попередньо кондиціонувати (бо це спільний продакшен), чесно стверджувати «стійку» продуктивність запису після короткого бенчмарку — неможливо.
Завдання 11: Виявити читання з допомогою read-ahead або сторінкового кешу (ненавмисно або навмисно)
cr0x@server:~$ sudo fio --name=cached-read --filename=/data/fio.test --size=4G --rw=read --bs=1M --iodepth=1 --numjobs=1 --runtime=30 --time_based --group_reporting
cached-read: (groupid=0, jobs=1): err= 0: pid=21688: Tue Jan 21 12:10:01 2026
read: IOPS=9200, BW=9200MiB/s (9647MB/s)(270GiB/30001msec)
Що це означає: 9.2 GiB/s з одного NVMe у типовому сервері — підозріло. Ви читаєте з кешу сторінок (page cache), бо не використовувалось direct IO і набір даних малий.
Рішення: Додайте --direct=1, збільште набір даних понад RAM і перезапустіть. Не використовуйте цей результат для планування сховища.
Завдання 12: Перевірити, чи є вузьке місце в пристрої чи CPU
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server) 01/21/2026 _x86_64_ (32 CPU)
11:25:01 AM CPU %usr %nice %sys %iowait %irq %soft %steal %idle
11:25:02 AM all 38.2 0.0 18.9 0.7 0.0 2.1 0.0 40.1
11:25:02 AM 7 92.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0
Що це означає: Одна CPU-схема завантажена під зав’язку. Це може бути прив’язка переривань, один запущений fio job під пінінгом або вузьке місце в драйвері.
Рішення: Якщо CPU насичений, «швидше сховище» не допоможе. Виправте pinning CPU, розподіл IRQ або підвищте паралелізм належним чином.
Завдання 13: Шукайте налаштування планувальника IO і черг (дрібні ручки, великі наслідки)
cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber bfq
Що це означає: NVMe використовує none (часто правильно). Інші планувальники можуть змінити розподіл латентності.
Рішення: Не повторюйте механічно. Якщо у вас проблеми з хвостовою латентністю під змішаним навантаженням — протестуйте mq-deadline/kyber з вашим реальним профілем і виміряйте перцентилі.
Завдання 14: Перевірити, чи TRIM/discard не саботує вас (або що він є, коли потрібен)
cr0x@server:~$ lsblk -D -o NAME,DISC-GRAN,DISC-MAX,DISC-ZERO
NAME DISC-GRAN DISC-MAX DISC-ZERO
nvme0n1 512B 2T 0
Що це означає: Discard підтримується. Добре — тепер ви можете обрати, як його використовувати (періодичний fstrim проти безперервного discard).
Рішення: Якщо у вас є деградація стійкого запису, розгляньте запланований fstrim у неробочий час і підтвердіть, що він не конфліктує з критичними вікнами IO.
Завдання 15: Спостерігайте за латентністю по пристрою в реальному часі під час інциденту
cr0x@server:~$ sudo pidstat -d 1 3
Linux 6.5.0 (server) 01/21/2026 _x86_64_ (32 CPU)
11:40:01 AM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
11:40:02 AM 999 14221 0.00 48200.00 0.00 postgres
11:40:02 AM 0 18802 0.00 20600.00 0.00 rsync
Що це означає: Ви можете корелювати IO-сплески з активністю процесів, що звужує «сховище повільне» до «ці два процеси конфліктують».
Рішення: Впровадьте планування IO, cgroups або вікна обслуговування. Не починайте з міграції сховища, доки не доведете насичення носія.
Завдання 16: Перевірте md RAID ребілд або фоні задачі (невидимий податок на продуктивність)
cr0x@server:~$ cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sdb1[0] sdc1[1]
976630336 blocks super 1.2 [2/2] [UU]
[======>..............] resync = 34.1% (333333333/976630336) finish=120.2min speed=89000K/sec
Що це означає: Іде ресинхронізація. Ваша «нормальна» продуктивність зараз недоступна.
Рішення: Налаштуйте обмеження швидкості ребілда, відтермінуйте важкі задачі або тимчасово прийміть деградований SLO. Також: включіть тестування ребілда в передпридбні бенчмарки.
Швидкий план діагностики: знайти вузьке місце швидко
Це чекліст, який ви використовуєте, коли хтось пише «сховище повільне» і у вас є 10 хвилин, перш ніж канал інциденту перетвориться на інтерпретативний танець.
Перше: підтвердіть, що це латентність сховища, а не час додатка
- Перевірте розподіли латентності запитів (метрики додатка), якщо вони доступні.
- На хості перевірте
iostat -xz 1на предмет await, aqu-sz і %util. - Якщо %iowait високий, але %util низький, підозрюйте щось вгору по ланцюгу (мережевий шлях до сховища, тротлінг або обмеження по cgroup).
Друге: визначте клас обмеження (пристрій, шлях, CPU або політика)
- Обмеження пристрою: %util ~100%, await зростає з навантаженням, fio відтворює це на тому ж LUN/пристрої.
- Обмеження шляху: проблеми multipath, помилки лінка, затори; сплески латентності без локального %util на максимумі.
- Обмеження CPU: один ядро завантажене (переривання, шифрування, контрольні суми), сховище недовантажене.
- Політика: ліміти IOPS в хмарі, SAN QoS, «гучний сусід» зіткнення.
Третє: доведіть це одним цільовим тестом
- Запустіть короткий fio read тест з
--direct=1на ураженому томі, підбираючи розмір блоку і глибину черги, які нагадують робоче навантаження. - Порівняйте з базовими числами, яким ви довіряєте (з ваших власних runbook, не з слайду постачальника).
- Якщо fio виглядає нормально, а додаток повільний — вузьке місце, ймовірно, у додатку, метаданих файлової системи, конкуренції за блокування або в мережевому шляху.
Четверте: вирішіть найшвидше безпечне пом’якшення
- Зменшіть конкурентний IO (припиніть пакетні завдання, уповільніть ребілд, перемістіть бекапи).
- Зменшіть write amplification (налаштування чекпойнтів, пакування, регулювання швидкості компактацій).
- Масштабуйте читання (репліки) або шардуйте «гарячі» партиції.
- Лише потім: масштабування або міграція сховища.
Жарт №2: Якщо бенчмарк постачальника каже «нуль латентності», вони випадково виміряли емпатію відділу продажів.
Поширені помилки: симптом → корінна причина → виправлення
1) «Ми досягли заявлених IOPS, але додаток повільніший»
Симптом: fio при QD=256 показує величезні IOPS; додаток все одно таймаутить або P99 вибухає.
Корінна причина: Додаток працює з малою конкурентністю; бенчмарки з глибокими чергами обміняли латентність на IOPS.
Виправлення: Бенчмарк на реалістичній QD (часто 1–32), і розраховуйте під P99 латентність при цій QD. Якщо потрібні і низька латентність, і велика пропускна здатність — масштабуйте горизонтально або використайте кілька пристроїв/шляхів.
2) «Вчора було швидко; сьогодні — вдвічі повільніше»
Симптом: Продуктивність випадкових записів падає після деякого часу або при вищому рівні заповнення.
Корінна причина: Різниця між «з коробки» і сталим станом SSD, garbage collection, виснаження SLC-кешу або тиск у тонкошарованому пулі.
Виправлення: Попередньо кондиціюйте, тестуйте довше, тестуйте при реалістичній заповненості і забезпечте адекватне overprovisioning. Розгляньте періодичну TRIM-стратегію і уникайте роботи пулів на межі.
3) «Читання в порядку; записи іноді зависають на секунди»
Симптом: Здебільшого все нормально, потім періодичні багатосекундні сплески латентності на записах.
Корінна причина: Події скидання кешу запису, підтвердження журналу, destage контролера або тиск метаданих файлової системи.
Виправлення: Перевірте налаштування writeback, політику кешу контролера, розміри журналу файлової системи і чи не співпадають фонові задачі (снапшоти, scrub) з затримками.
4) «Додав оптимізацію — стало гірше»
Симптом: Після налаштувань «для швидкості» хвостова латентність погіршилась або пропускна здатність впала.
Корінна причина: Неправильно застосовані опції монтування, невірний планувальник IO, надмірний readahead або накладні витрати від стиснення/шифрування на гарячих шляхах.
Виправлення: Відкотіть, а потім тестуйте зміни по одній з перцентилями. Розглядайте тюнінг як експеримент, а не як істину.
5) «SAN повільний, але на панелі масиву все зелене»
Симптом: На хості високе await; масив показує низьку завантаженість.
Корінна причина: Проблеми шляху (multipath misconfig), затори, повторні передачі, обмеження черг HBA або політики QoS на ініціатора.
Виправлення: Перевірте стан multipath, черги, шукати помилки лінку і підтвердіть, що ніякі політики QoS вас не обмежують.
6) «Бенчмарки хмарного тому хороші 30 секунд, потім колапс»
Симптом: Перші хвилини приголомшливі; потім ви нарветеся на стіну.
Корінна причина: Burst credits або базові обмеження.
Виправлення: Бенчмарк достатньо довго, щоб витратити кредити. Розраховуйте за базою, а не за сплеском. Якщо сплеск — частина дизайну, протестуйте поведінку поповнення кредитів при вашому циклі роботи.
Три корпоративні міні-історії (анонімізовано, правдоподібно та технічно корректно)
Міні-історія 1: Інцидент, спричинений неправильним припущенням
Вони замінили гуркітну групу старих дисків на блискучий масив, що «робив 800k ops». План проєкту мав один пункт продуктивності: «нове сховище швидше за старе». Це була вся acceptance-критерія. Воно пройшло тижневий тест. Усі пішли додому.
Через два тижні почалася місячна звітність. База даних не була забита CPU і не була заблокована. Вона була просто… повільною. Пакетні роботи накопичилися. Латентності API повільно піднімались, доки канал підтримки клієнтів не почав робити власний моніторинг: «Система впала?»
Масив давав обіцяні операції, але при глибині черги, яку додаток ніколи не продукував. Кешування масиву робило читання блискучими; записи при змішаному навантаженні з синхронними підтвердженнями були звужені політикою, яку команда не помічала: підтвердження запису було прив’язане до консервативного режиму захисту, і малі випадкові записи серіалізувалися вузьким внутрішнім шляхом.
Хибне припущення було не в тому, що «постачальники брешуть». Воно було тоншим: команда вважала, що одне число IOPS означає «швидше у всьому» і що політики захисту не мають власного впливу на продуктивність.
Виправлення не потребувало героїзму. Вони зібрали перцентилі при реалістичній конкурентності, змінили налаштування захисту для конкретного класу томів і відокремили WAL/лог IO на шар з нижчою латентністю. Місячні обробки перестали бути ритуальними жертвоприношеннями.
Міні-історія 2: Оптимізація, що відбилася бумерангом
Платформна команда вирішила «відкрити продуктивність», підвищивши глибини черг скрізь. Вони збільшили налаштування NVMe-черг, підкоригували параметри multipath і заохочували команди запускати більш велику кількість одночасних IO. Бенчмарки покращились. Слайд-дек був прекрасний.
Потім продакшен трафік змінив форму. Невелика кількість орендарів почала генерувати сплески випадкових читів і записів одночасно з фоновим обслуговуванням: снапшотами, компактаціями і ребілдом на одному вузлі. Пропускна здатність виглядала нормально, але хвостова латентність стала кошмарною антологією. Таймаути запитів зросли, бо сервіси мали строгі дедлайни і не могли чекати за довгими чергами пристроїв.
Відбій був передбачуваний: вони оптимізували під агрегований IOPS, а не під latency SLO. Глибокі черги ховали біль, тримаючи пристрої зайнятими, але сервіси, що взаємодіють з користувачем, потребують коротких черг і швидких відповідей. Пристрій на 100% завантаження — не «ефективний», якщо він перетворює ваш 99-й перцентиль на вираз викупу.
Виправлення полягало в тому, щоб трактувати глибину черги як налаштування для кожного робочого навантаження. Латентнісно-чутливі сервіси отримали меншу QD і сильнішу ізоляцію. Пакетні навантаження могли користуватися глибокими чергами, коли платформа мала резерви. Також ввели IO cgroup-контроль, щоб «корисні» фонові завдання не їли обід інтерактивного трафіку.
Найсмішніше — кінцевий графік виглядав нудно. Хвостова латентність вирівнялась; пікові IOPS впали. Усіх перестали будити о 2 ночі, і це єдиний KPI, що справді має значення.
Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію
Інша компанія мала правило: кожна платформа зберігання мала короткий версіонований рецепт бенчмарка. Ті самі fio job-и, той самий runtime, ті самі кроки пре-кондиціювання, ті самі цільові рівні заповнення. Без виключень. Інженери тихо нарікали, бо послідовність — не захопливо.
Одної п’ятниці через заміну постачання прийшла нова партія «еквівалентних» SSD. Система піднялась, навантаження мігрували, і за кілька годин вони побачили трохи вищу P99 для записів. Не катастрофа — просто дивно. Он-колл витягнув стандартні результати бенчмарків з внутрішньої бази та прогнав ту саму суїту на одному вузлі в ізоляції.
Різниця була очевидна: стійка випадкова записова продуктивність деградувала швидше і хвіст став товщим. Диски не були зламані; вони були іншими. Прошивка, тип NAND, поведінка кешування — щось змінилось.
Тому що у них були нудні базові дані, не було суперечок про відчуття. Нову партію помістили в карантин на менш чутливий до латентності шар, оновили вимоги procurement і вимагали кваліфікаційного прогона для майбутніх замін. Нема інциденту, нема впливу на клієнтів, нема втраченого уїк-енду.
Ось як виглядає «операційна досконалість»: графік, який ніхто ніколи не презентує, і безшумний пейджер.
Контрольні списки / покроковий план
Чекліст для закупівель (перед підписанням)
- Вимагайте рецепт бенчмарка: розмір блоку, rw mix, QD, потоки, runtime, пре-кондиціювання, розмір набору даних.
- Вимагайте перцентилі латентності: принаймні P50/P95/P99 при заявленому навантаженні.
- Вимагайте поведінки в сталому стані: 30+ хвилин для сцен зі значними записами; додавайте графіки, якщо можливо.
- Тестуйте при реалістичній заповненості: принаймні 60–80% для флеш-пулів, якщо ви плануєте так їх використовувати.
- Уточніть продуктивність у режимі відмови: вплив ребілда/скрабів/відмови контролера і час відновлення.
- Вкажіть вимоги до хоста: CPU, покоління PCIe, HBA, версії драйверів, налаштування multipath.
- Проясніть burst vs baseline: особливо для хмарних томів і кешованих масивів.
План виконання бенчмарка (відтворювано й захисно)
- Забронюйте чистий хост: відключіть непотрібні cron, бекапи і галасливі агенти на вікно тесту.
- Перевірте ідентичність і стан: модель/прошивка, SMART, поведінка температури.
- Фіксуйте змінні: однакова версія fio, однакове ядро, ті самі опції монтування, політика NUMA де можливо.
- Прекондиціонування, де релевантно: особливо для стійких записових тестів.
- Запустіть кілька профілів: принаймні 4K randread, 4K randwrite, 70/30 mix і послідовний тест пропускної здатності.
- Фіксуйте перцентилі і часові ряди: не лише підсумковий вивід; повторюйте прогони.
- Порівнюйте з вашим SLO: приймайте чи відхиляйте на основі латентності при потрібній пропускній здатності, а не пікових IOPS.
Чекліст приймання в продакшен (після розгортання)
- Встановіть базові значення: знімки iostat/fio при відомо хороших умовах.
- Інструментуйте латентність: збирайте P95/P99 на рівні хоста і додатка.
- Протестуйте один режим відмови: відключіть шлях, ініціюйте контрольоване фейловер або симулюйте вікно ребілда.
- Підтвердіть ізоляцію: упевніться, що пакетні роботи не зможуть виснажити інтерактивні навантаження.
Питання й відповіді
П1: Чи марний IOPS?
Ні. Він просто неповний. IOPS корисний у парі з розміром блоку, глибиною черги, співвідношенням чит/запис та перцентилями латентності. Інакше це число, що допомагає комусь виграти зустріч.
П2: Яка розумна глибина черги для бенчмарка?
Бенчмарк робіть при глибині черги, яку породжує ваше навантаження. Якщо не знаєте — виміряйте її непрямо через спостережувані відкриті IO і поведінку латентності. Для багатьох латентнісно-чутливих сервісів QD у діапазоні 1–32 на пристрій більш репрезентативний, ніж 128+.
П3: Чому постачальники завжди використовують 4K випадкове читання?
Бо це дає велике, вражаюче число операцій, і це легітимний шаблон для деяких навантажень. Проте це не універсальний проксі для «швидкого сховища».
П4: Скільки часу потрібно тримати fio?
Достатньо, щоб побачити стійкий стан і хвостову поведінку. Для читань кілька хвилин може бути достатньо, якщо набір даних перевищує кеш. Для стійких записів 30 хвилин — краще початкове значення, і довше часто виправдано.
П5: Чи тестувати на сирих блочних пристроях чи файлах?
Якщо хочете знати здатність пристрою — використовуйте raw. Якщо хочете знати «що отримає мій додаток» — тестуйте через ту саму стеку файлової системи, яка буде в продакшені. Обидва варіанти валідні; змішувати їх без вказівки — причина довгих суперечок.
П6: Чому продуктивність падає, коли диск заповнюється?
Флеш-таблиці трансляції потребують вільних блоків для ефективного запису. Коли вільного місця менше, зростає вартість garbage collection, і write amplification підвищується. Багато систем виглядають добре при 5–10% заповнення і зовсім інакше при 70–90%.
П7: А що з «FPS» від прикладного бенчмарка замість fio?
Прикладні бенчмарки кращі для енд-ту-енд планування — якщо вони відображають ваш патерн доступу і конкурентність. Але їх теж можна «приламати» кешами, нереалістичними наборами даних або відключеними налаштуваннями надійності. Ставтесь до них з тією ж часткою скептицизму: вимагаєте рецепт і перцентилі.
П8: Як порівнювати локальний NVMe, SAN і хмарний блочний storage?
Порівнюйте перцентилі латентності при потрібній пропускній здатності і включайте поведінку при відмовах. SAN і хмара часто додають шляхову латентність і варіативність. Локальний NVMe зазвичай має нижчу латентність, але менш розподілений і має інші операційні ризики (заміна, дзеркалювання, відмова вузла).
П9: Чи можна довіряти бенчмарку всередині VM?
Можна, якщо розумієте шар віртуалізації: спільні черги хоста, політики тротлінгу і «гучні сусіди» можуть домінувати в результатах. Для планування ємності тестуйте в тому ж середовищі, де працюватимете. Для кваліфікації пристрою — тестуйте на bare metal або в строгій ізоляції.
П10: Який найпростіший критерій приймання, який не тупий?
Виберіть репрезентативний профіль навантаження і вимагайте P99 latency нижче X ms при Y IOPS/MB/s протягом принаймні Z хвилин, з набором даних більшим за кеш і з налаштуваннями надійності, що відповідають продакшену.
Висновок: практичні наступні кроки
Якщо запам’ятати лише три кроки — робіть ці:
- Відмовтесь від одночисельних претензій з продуктивності. Просіть повний рецепт та перцентилі латентності.
- Бенчмарк так, як ви експлуатуєте. Реалістична глибина черги, реалістичний мікс, реалістичний розмір набору даних, реалістична тривалість.
- Розраховуйте під ваші SLO, а не під заголовок. Купуйте «P99 під навантаженням», а не «до» чогось.
А далі зробіть нудну, але корисну річ, яка збереже вам повагу пізніше: запишіть файли ваших бенчмарків, зберігайте базові виводи і перезапускайте їх після змін. Коли наступного разу пролунає «але брошура каже…», у вас будуть дані, а не думки.