Планувальник введення-виведення: де черга завдань гальмує диски
Блоковий шар ядра приймає запити на читання й запис і складає їх у чергу запитів до диска — накопичувач фізично обробляє їх послідовно, а порядок задає планувальник. На однорідному навантаженні з великих послідовних операцій цей прошарок майже непомітний.
Проблеми починаються зі змішаним профілем: транзакції бази, журнал, вивантаження резервних копій і синхронізація файлів конкурують за один накопичувач.
При неправильному планувальнику запити втрачають порядок. Пристрій кидається між далекими адресами замість того, щоб зливати сусідні операції, і простоює між ними.
Затримка відгуку сховища зростає в рази за формально вільних ресурсів: утилізація показує половину, а застосунок чекає на відповідь на запит, що стоїть у черзі.
Так виникає вузьке місце за операціями введення-виведення, яке не видно ні в завантаженні процесора, ні в обсязі вільної пам'яті.
Різні носії потребують різної поведінки. Швидким NVMe із глибокою внутрішньою чергою перевпорядкування лише заважає — там вигідніше віддавати запити напряму.
Масивам на жорстких дисках потрібен планувальник, який укрупнює сусідні операції й не дає одному завданню зайняти чергу цілком.
Налаштування планувальника введення-виведення — це підбір компромісу між затримкою, пропускною здатністю та справедливістю розподілу під конкретний профіль навантаження.
Далі — як знайти це місце в метриках і як його закривають.
Що змінюється в роботі дисків після підбору режиму
Підбір режиму починається з розбору профілю навантаження на диск: скільки операцій у черзі одночасно, яка частка читання проти запису, чи є сплески.
Поки режим один на всі випадки, ядро вибудовує чергу за усередненим шаблоном — і на реальному потоці ця черга працює проти застосунку.
Після підбору планувальник введення-виведення узгоджується з фактичним профілем: глибина черги, пріоритети й порядок видачі операцій перестають конфліктувати з тим, як накопичувач фізично обробляє запити.
Найсильніше ефект видно на змішаному навантаженні читання й запис. Режими з розділенням черг не дають потоку читання чекати, поки накопичувач зливає та перевпорядковує записи, — операції отримують бюджет часу, а не стають у спільний хвіст.
Пропускна здатність на змішаному потоці зростає без заміни заліза, а час очікування окремої операції скорочується завдяки тому, що черга перестає бути звалищем із різнорідних запитів.
Другий ефект — рівномірність зносу накопичувача. Коли порядок видачі операцій ураховує структуру запису й не ганяє блоки марно, перезапис розподіляється рівніше, а зайві перестановки не спалюють ресурс.
Це напряму впливає на термін служби: у накопичувачів з обмеженою кількістю циклів рівний знос відсуває деградацію, а не наближає її піковими сплесками.
Третій, найпомітніший для бізнес-логіки результат — стабільність відгуку застосунків. Зникає клас відмов «диск зайнятий, застосунок чекає»: запит не зависає на піку, бо черга під нього спроєктована.
Хвостові затримки вирівнюються, розкид між швидкими й повільними операціями скорочується, і сервіс тримає рівний час відповіді під навантаженням, а не лише в простої.
Вибір планувальника під NVMe, SSD і HDD
Планувальник вирішує, у якому порядку блоковий шар ядра віддає запити накопичувачу й скільки тримає їх у черзі. На NVMe контролер сам переставляє та склеює команди, тому програмне сортування лише додає затримку. На HDD порядок визначає кількість переміщень головки, і сортування за секторами дає кратний виграш.
Вибір — це компроміс між пропускною здатністю, затримкою та справедливістю між процесами, а не пошук «найшвидшого» варіанта. У ядрі Linux доступні кілька планувальників, і перемикаються вони на живому пристрої, без перезавантаження.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
none |
NVMe і швидкі SSD із власною чергою команд | Немає сортування й пріоритетів: під змішаним навантаженням один потік захоплює пристрій |
mq-deadline |
Бази даних, віртуалізація, SATA SSD і HDD | Читання має вкластися в заданий строк; на великій кількості потоків поступається за затримкою |
bfq |
Робочі станції, відзивчивість інтерактивних завдань | З'їдає процесорний час на планування, на NVMe втрачає сенс |
kyber |
Швидкі накопичувачі з жорсткими вимогами до затримки | Обмежує довжину черги за часом, тонший у налаштуванні |
Окремо перевіряємо режим перевпорядкування запитів: на HDD і SATA SSD склеювання сусідніх блоків скорочує кількість операцій, а на NVMe воно дублює роботу контролера й додає накладні витрати.
Підсумковий варіант обираємо за вимірюваннями на реальному профілі навантаження — синтетика на порожньому диску майже завжди бреше.
Порядок упровадження: від аудиту навантаження до передавання регламенту
Планувальник введення-виведення не можна виставити «за замовчуванням»: вузол під базою, сервіс із логами та сховище образів дають різний профіль звернень до диска. Порядок робіт іде від вимірювань до рішення — спочатку аудит, потім режим, далі закріплення в конфігурації.
- Аудит навантаження на диск. Знімаємо глибину черги, співвідношення читання й запису, розмір запиту та час відгуку за кожним пристроєм — це база, з якою порівнюємо все подальше.
- Схема черг. Розмічаємо диски за призначенням і рахуємо, скільки черг припадає на пристрій і де вузьке місце: сам накопичувач чи черга до нього.
- Підбір режиму. На NVMe перевпорядкування запитів майже не дає виграшу, на SSD із паралельними чергами працює багатопотоковий режим, на HDD — із накопиченням і сортуванням запитів.
- Стенд для перевірки режиму. Розгортаємо копію контуру, повторюємо профіль з аудиту й порівнюємо затримку та пропускну здатність із базою. Режим без виграшу на стенді на бойовий вузол не їде.
- Перемикання за вузлами. Змінюємо поетапно, з відкатом за один крок, і одразу закріплюємо правило в конфігурації — інакше після перезавантаження або оновлення ядра значення повернеться до попереднього.
- Перевірка на реальному трафіку. Дивимося поведінку на піку та в години низького навантаження: час відгуку, довжину черги, регресію на сусідніх сервісах.
- Передавання регламенту обслуговування. Віддаємо документ: який режим якому класу дисків належить, як перевірити поточне значення, як відкотитися й які метрики дивитися.
Комплект документації та налаштувань на виході
Комплект збирається так, щоб стан стенда відтворювався на новому вузлі без нас — із репозиторію, а не з листування в чаті. Усе, що ми змінювали на живих системах, фіксується у вигляді файлів і коротких інструкцій, придатних для рев'ю черговою зміною.
- Файли конфігурацій планувальника введення-виведення та правил пристроїв — під контролем версій, із коментарем до кожного винятку: чому для цього тому вибрано не загальний профіль.
- Схема черг і пріоритетів: які черги обслуговують бази, журнали, резервне копіювання, яка в них вага та глибина, що відбувається при переповненні.
- Карта розподілу завдань за накопичувачами: том, тип носія, призначений планувальник і результат вимірювань, на яких засновано вибір.
- Регламент обслуговування серверів: що перевіряти після оновлення ядра або заміни диска, у який момент профіль перестає бути актуальним.
- Інструкція для чергової зміни: як перемкнути планувальник на працюючій системі, як повернути попереднє значення й за якими метриками зрозуміти, що стало гірше.
- Методика вимірювань: сценарії навантаження, кількість повторів, набір вимірюваних показників затримки та пропускної здатності — щоб спірні рішення вирішувалися цифрами.
- Інвентаризація вузлів із відхиленнями від еталона та план приведення їх до спільного стану.
Документація з налаштування дисків пишеться під інженера, який побачить сервер уперше: без посилань на наш внутрішній контекст і без кроків, що вимагають автора.
Розбір: високонавантажена база перестала впиратися в диск
Вузол поєднував базу та файлові завдання: вивантаження, приймання статики й бекапи йшли тими самими накопичувачами, що й транзакції.
Раз на кілька хвилин відгук просідав — черга запитів до диска зростала, час очікування операцій підскакував у рази, частка простою процесора на очікуванні введення-виведення сягала чверті за помірного завантаження самого процесора.
Розбір показав, що справа не у швидкості накопичувачів, а в диспетчеризації. Режим планувальника введення-виведення залишився від попередньої конфігурації з повільними дисками: він пересортовував запити й додавав затримку там, де вона не потрібна.
PostgreSQL і фонові завдання потрапляли в одну чергу без класів пріоритету, а глибина черги та розмір запитів не відповідали профілю навантаження.
Що змінили: томи з базою перевели на багатопотоковий планувальник без зайвого сортування, розвели трафік за класами пріоритету й обмежили частку смуги для бекапів, збільшили розмір запиту під послідовні читання.
Окремо рознесли журнал бази та приймання статики за різними томами, щоб фонові операції не витісняли транзакції.
Метрики до й після: час очікування дискових операцій на 99-му процентилі скоротився в 6–8 разів, частка очікування введення-виведення впала з чверті до 2–3%.
Періодичні провали за відгуком припинилися — замість сплесків раз на кілька хвилин графік став рівним, а вікно бекапу скоротилося настільки, що перестало перетинатися з піковим навантаженням. Вузол перестав впиратися в диск, і запас за навантаженням залишився на тому самому залізі.
Що робити, якщо на вузлі змішані база та файлові завдання?
Один планувальник введення-виведення на змішаному вузлі завжди програє: він налаштований під один профіль.
Увімкнете bfq заради справедливості файлових операцій — транзакції почнуть платити накладними на кожній операції; поставите простий планувальник заради мінімальної затримки — фонові завдання займуть чергу цілком. Тому змішане навантаження на вузлі розводять за пристроями, а не шукають одне універсальне правило.
Розділення дисків за завданнями дає передбачуваність: журнал і дані бази — на швидких накопичувачах із мінімальним перевпорядкуванням, а вивантаження, бекапи й репліка — на окремих томах під bfq.
Якщо накопичувач фізично один, залишаються тільки пріоритети: черга пристрою спільна, і розділення на розділи під різні профілі майже нічого не змінює.
Пріоритети операцій введення-виведення задають незалежно від пріоритету процесу: класи реального часу, best-effort та idle, а також ваги й ліміти операцій за секунду в cgroup.
Фонові завдання тримаємо в idle — такий клас отримує смугу лише за вільного пристрою й витіснити транзакції не може. Сплеск від бекапу знімають лімітом операцій, а не підвищенням пріоритету.
Перевіряємо результат вимірюванням: подаємо обидва типи навантаження одночасно й дивимося хвіст затримки — 95-й і 99-й процентиль, а не середнє, бо саме хвіст відчуває користувач. Правила фіксуємо в конфігурації, щоб вони переживали перезавантаження й оновлення ядра.
Технічні сумніви перед зміною режиму обробки черги
Інженерна команда сперечається не про саму ідею, а про ціну помилки. Зміна режиму обробки черги — рідкісний випадок, коли налаштування застосовують на працюючій системі й так само швидко скасовують: змінюється порядок і групування запитів, а не розмітка даних. Нижче — сумніви, які ми знімаємо до правки.
Потрібне перезавантаження або простій?
Ні. Режим перемикається на працюючій системі через чергу пристрою й підхоплюється одразу. Зупинка потрібна лише щоб закріпити вибір назавжди — правило udev або параметр завантажувача, і це одна пауза в узгоджене вікно.
На базі, що пише, змінюємо на паузі запису: надіслані запити завершаться, нові підуть уже через інший режим.
Чи є ризик втратити дані?
Планувальник не пише на носій — він вирішує, у якому порядку ядро віддає запити. Формат, метадані та вміст томів не зачіпаються, тому втрати даних від самої зміни режиму немає. Ризик в іншому: правка під піковим навантаженням без спостереження за затримкою та глибиною черги. Тому спочатку знімаємо вихідні метрики, потім змінюємо.
Що робити при заміні накопичувачів?
Новий диск приходить із режимом за замовчуванням — звідси «після заміни стало повільніше». Правило прив'язуємо до типу носія, а не до імені пристрою: NVMe, SATA SSD і HDD отримують свої режими автоматично. Заміна диска або додавання вузла тоді не потребує ручного налаштування.
Як відкотитися, якщо стало гірше?
Повернення значення — одна операція, застосовується без перезавантаження й простою. Знімок поточних параметрів зберігаємо до правки, щоб відкат не шукали під тиском. Перед викочуванням на весь парк проганяємо режим на одному вузлі й порівнюємо затримку з вихідною.
Обговоримо задачу й повернемося з оцінкою та планом
Щоб обговорити задачу предметно, достатньо описати контур: які вузли обслуговуємо, які носії на них стоять і що саме гальмує. Ми не починаємо із загальних питань — спочатку дивимося, як черга введення-виведення поводиться під вашим навантаженням і які параметри виставлені зараз.
Для старту надішліть:
- склад вузлів і типи носіїв — NVMe, SATA SSD, HDD та їхня роль у системі;
- профіль навантаження: база даних, черги повідомлень, файлове сховище, віртуалізація;
- поточний сценарій — який планувальник вибрано й як задано параметри черги;
- симптом із цифрами: просідання запису, зростання часу відгуку, нерівномірне завантаження ядер;
- обмеження — вікно обслуговування, вимоги до відкату та внутрішні регламенти;
- стенд або сервер, де можна відтворити поведінку до змін у робочому контурі.
Далі розбір іде за кроками: звіряємо конфігурацію з профілем навантаження, знімаємо вимірювання до й після зміни планувальника на кожному типі носія, перевіряємо поведінку під піком, а не в спокійному режимі.
За підсумком надходить оцінка та план робіт: етапи, цільові параметри черги за кожним класом носіїв, порядок викочування з точкою відкату й перелік перевірок, за якими видно результат.
Налаштування серверів Linux ведеться так, щоб зміни жили в конфігурації й переносилися на нові вузли однією командою, а не залишалися правкою на одному сервері.
Опишіть задачу — повернемося з оцінкою та планом.







