Основи ZFS: система зберігання та продуктивність

Основи ZFS: система зберігання та продуктивність

Цієї весни ми вже обговорили деякі вступні теми, наприклад, як перевірити швидкість ваших дисків и що таке RAID. У другій ми навіть пообіцяли продовжити вивчення продуктивності різних багатодискових топологій в ZFS. Це файлова система наступного покоління, яка зараз упроваджується всюди: від Apple до Ubuntu.

Ну що ж, сьогодні найкращий день для знайомства з ZFS, допитливі читачі. Просто знайте, що за скромною оцінкою розробника OpenZFS Метта Аренса, це дійсно складно.

Але перш ніж ми дістанемося цифр — а вони будуть, обіцяю — за всіма варіантами восьмидискової конфігурації ZFS, потрібно поговорити про те, як взагалі ZFS зберігає дані на диску.

Zpool, vdev та device

Основи ZFS: система зберігання та продуктивність
Ця діаграма повного пулу включає три допоміжні vdev'а, по одному кожного класу, і чотири для RAIDz2

Основи ZFS: система зберігання та продуктивність
Зазвичай немає причин створювати пул із невідповідних типів та розмірів vdev — але якщо хочете, ніщо не заважає вам це зробити

Щоб зрозуміти файлову систему ZFS, потрібно уважно подивитися на її фактичну структуру. По-перше, ZFS поєднує традиційні рівні управління томами та файловою системою. По-друге, вона використовує транзакційний механізм копіювання під час запису. Ці особливості означають, що система структурно відрізняється від звичайних файлових систем і RAID-масивів. Перший набір основних будівельних блоків для розуміння: це пул зберігання (zpool), віртуальний пристрій (vdev) та реальний пристрій (device).

zpool

Пул зберігання zpool – найвища структура ZFS. Кожен пул містить один або кілька віртуальних пристроїв. У свою чергу, кожен з них містить один або декілька реальних пристроїв (device). Віртуальні пули – це автономні блоки. Один фізичний комп'ютер може містити два або більше окремих пула, але кожен є повністю незалежним від інших. Пули не можуть спільно використовувати віртуальні пристрої.

Надмірність ZFS знаходиться на рівні віртуальних пристроїв, а не на рівні пулів. На рівні пулів немає абсолютно ніякої надмірності - якщо якийсь накопичувач vdev або спеціальний vdev губиться, то разом з ним губиться і весь пул.

Сучасні пули зберігання можуть пережити втрату кешу або журналу віртуального пристрою - хоча вони можуть втратити невелику кількість брудних даних, якщо втратить журнал vdev під час відключення живлення або збою системи.

Існує поширена помилка, що «смуги даних» (страйпи) ZFS записуються через весь пул. Це не вірно. Zpool - зовсім не кумедний RAID0, це скоріше кумедний JBOD зі складним мінливим механізмом розподілу.

Здебільшого записи розподіляються між доступними віртуальними пристроями відповідно до наявного вільного простору, так що теоретично всі вони будуть заповнені одночасно. У пізніших версіях ZFS враховується поточне використання (утилізацію) vdev — якщо один віртуальний пристрій значно завантаженіший за інший (наприклад, через навантаження на читання), його тимчасово пропустять для запису, незважаючи на наявність найвищого коефіцієнта вільного простору.

Механізм визначення утилізації, вбудований у сучасні методи розподілу запису ZFS, може зменшити затримку та збільшити пропускну спроможність у періоди надзвичайно високого навантаження – але це не карт Бланш на мимовільне змішування повільних HDD та швидких SSD в одному пулі. Такий нерівноцінний пул все одно працюватиме зі швидкістю найповільнішого пристрою, тобто начебто він повністю складений з таких пристроїв.

vdev

Кожен пул зберігання складається з одного або кількох віртуальних пристроїв (virtual device, vdev). У свою чергу, кожен vdev включає один або кілька реальних пристроїв. Більшість віртуальних пристроїв використовуються для простого зберігання даних, але є кілька допоміжних класів vdev, включаючи CACHE, LOG та SPECIAL. Кожен із цих типів vdev може мати одну з п'яти топологій: єдиний пристрій (single-device), RAIDz1, RAIDz2, RAIDz3 або дзеркало (mirror).

RAIDz1, RAIDz2 і RAIDz3 - це особливі різновиди того, що олди назвуть RAID подвійної (діагональної) парності. 1, 2 і 3 відносяться до того, скільки блоків парності виділено для кожної лінії даних. Замість окремих дисків для забезпечення парності віртуальні пристрої RAIDz напіврівномірно розподіляють цю парність на дисках. Масив RAIDz може втратити стільки дисків, скільки блоків парності; якщо він втратить ще один, то вийде з ладу та забере із собою пул зберігання.

У дзеркальних віртуальних пристроях (mirror vdev) кожен блок зберігається кожному пристрої в vdev. Хоча найпоширеніші подвійні дзеркала (two-wide), у дзеркалі може бути будь-яка довільна кількість пристроїв — у великих установках для підвищення продуктивності читання та стійкості до відмови часто використовуються потрійні. Дзеркало vdev може пережити будь-який збій, поки продовжує працювати хоча б один пристрій в vdev.

Поодинокі vdev за своєю суттю небезпечні. Такий віртуальний пристрій не переживе жодного збою - і якщо використовується як сховище або спеціальний vdev, то його збій призведе до знищення всього пулу. Будьте тут дуже, дуже обережні.

Віртуальні пристрої CACHE, LOG і SPECIAL можуть бути створені за будь-якою з перелічених вище топологій — але пам'ятайте, що втрата віртуального пристрою SPECIAL означає втрату пулу, тому настійно рекомендується надмірна топологія.

пристрій

Ймовірно, це найпростіший для розуміння термін ZFS — це буквально блоковий пристрій довільного доступу. Пам'ятайте, що віртуальні пристрої складаються з окремих пристроїв, а пул зроблений із віртуальних пристроїв.

Диски - магнітні або твердотільні - є найбільш поширеними блоковими пристроями, які використовуються як будівельні блоки vdev. Однак підійде будь-який девайс з дескриптором /dev - так що в якості окремих пристроїв можна використовувати цілі апаратні RAID-масиви.

Простий raw-файл є одним з найважливіших альтернативних блокових пристроїв, з яких може бути побудований vdev. Тестові пули з розріджених файлів — дуже зручний спосіб перевіряти команди пулу та дивитися, скільки місця доступно в пулі чи віртуальному пристрої даної топології.

Основи ZFS: система зберігання та продуктивність
Можете створити тестовий пул із розріджених файлів всього за кілька секунд - але не забудьте потім видалити весь пул та його компоненти

Допустимо, ви хочете поставити сервер на вісім дисків і плануєте використовувати диски по 10 ТБ (~9300 ГіБ) - але ви не впевнені, яка топологія найкраще відповідає вашим потребам. У наведеному вище прикладі ми за лічені секунди будуємо тестовий пул із розріджених файлів - і тепер знаємо, що RAIDz2 vdev з восьми дисків по 10 ТБ забезпечує 50 Тіб корисної ємності.

Ще один спеціальний клас пристроїв - SPARE (запасні). Пристрої гарячої заміни, на відміну звичайних пристроїв, належать всьому пулу, а чи не одному віртуальному пристрою. Якщо якийсь vdev у пулі виходить з ладу, а запасний пристрій підключений до пулу і доступний, то він автоматично приєднається до постраждалого vdev.

Після підключення до постраждалого vdev запасний девайс починає отримувати копії або реконструкції даних, які повинні бути на відсутньому пристрої. У традиційному RAID це називається відновленням (rebuilding), а ZFS це «відновлення надмірності» (resilvering).

Важливо, що запасні пристрої не назавжди замінюють пристрої, що вийшли з ладу. Це лише тимчасова заміна скорочення часу, протягом якого спостерігається деградація vdev. Після того, як адміністратор замінив пристрій vdev, що вийшов з ладу, то відбувається відновлення надмірності на цей постійний пристрій, а SPARE від'єднується від vdev і повертається до роботи запасним на весь пул.

Набори даних, блоки та сектори

Наступний набір будівельних блоків, які потрібно зрозуміти в нашій подорожі ZFS, відноситься не стільки до апаратного забезпечення, скільки до того, як організовані і зберігаються дані. Ми тут пропускаємо кілька рівнів, таких як metaslab, щоб не нагромаджувати деталі, зберігаючи розуміння загальної структури.

Набір даних (dataset)

Основи ZFS: система зберігання та продуктивність
Коли ми вперше створюємо набір даних, він показує весь доступний простір пулу. Потім ми встановлюємо квоту і змінюємо точку монтування. Магія!

Основи ZFS: система зберігання та продуктивність
Zvol — це переважно набір даних, позбавлений свого шару файлової системи, який ми замінюємо тут абсолютно нормальною файловою системою ext4

Набір даних ZFS приблизно аналогічний стандартній змонтованій файловій системі. Як і звичайна файлова система, на перший погляд він здається просто ще однією папкою. Але так само, як і у звичайних файлових систем, що монтуються, у кожного набору даних ZFS власний набір базових властивостей.

Насамперед, у набору даних може бути призначена квота. Якщо встановити zfs set quota=100G poolname/datasetname, то ви не зможете записати в змонтовану папку /poolname/datasetname більше, ніж 100 ГіБ.

Помітили наявність і відсутність слешів на початку кожного рядка? У кожного набору даних своє місце як ієрархії ZFS, так і ієрархії системного монтування. В ієрархії ZFS немає провідного слеша - ви починаєте з імені пула, а потім шляхи від одного набору даних до наступного. Наприклад, pool/parent/child для набору даних з ім'ям child під батьківським набором даних parent у пулі з креативною назвою pool.

За умовчанням, точка монтування набору даних буде еквівалентна його імені в ієрархії ZFS, зі слешем на початку пул з назвою pool примонтується як /pool, набір даних parent монтується в /pool/parent, а дочірній набір даних child змонтується в /pool/parent/child. Однак, можна змінити системну точку монтування набору даних.

Якщо ми вкажемо zfs set mountpoint=/lol pool/parent/child, то набір даних pool/parent/child змонтується в систему як /lol.

Крім наборів даних, ми повинні згадати томи (zvols). Тому приблизно аналогічний набору даних, за винятком того, що в ньому фактично немає файлової системи - це просто блоковий пристрій. Ви можете, наприклад, створити zvol з ім'ям mypool/myzvol, потім відформатувати його з файловою системою ext4, а потім змонтувати цю файлову систему - тепер у вас є файлова система ext4, але за допомогою всіх функцій безпеки ZFS! Це може здатися дурним на одному комп'ютері, але має набагато більше сенсу як бекенд при експортуванні пристрою iSCSI.

Блоки

Основи ZFS: система зберігання та продуктивність
Файл представлений одним чи кількома блоками. Кожен блок зберігається на одному віртуальному пристрої. Розмір блоку зазвичай дорівнює параметру recordsize, але може бути зменшено до 2^ashiftякщо містить метадані або невеликий файл.

Основи ZFS: система зберігання та продуктивність
Ми справді, дійсно не жартуємо з приводу величезної шкоди продуктивності, якщо встановити занадто маленький ashift

У пулі ZFS всі дані, включаючи метадані, зберігаються у блоках. Максимальний розмір блоку для кожного набору даних визначається властивістю recordsize (Розмір запису). Розмір запису може змінюватися, але це не змінить розмір або розташування будь-яких блоків, які вже були записані в набір даних, він діє тільки для нових блоків у міру їх запису.

Якщо не визначено інше, поточний розмір запису за замовчуванням дорівнює 128 КіБ. Це свого роду непростий компроміс, у якому продуктивність буде не ідеальною, а й не жахливою здебільшого. Recordsize можна встановити будь-яке значення від 4K до 1M (з додатковими налаштуваннями recordsize можна встановити ще більше, але це рідко буває гарною ідеєю).

Будь-який блок посилається на дані лише одного файлу - ви не можете втиснути два різні файли в один блок. Кожен файл складається з одного або кількох блоків залежно від розміру. Якщо розмір файлу менший за розмір запису, він збережеться в блоці меншого розміру — наприклад, блок із файлом 2 КіБ займе лише один сектор 4 КіБ на диску.

Якщо файл досить великий і вимагає кілька блоків, всі записи з цим файлом будуть мати розмір recordsize — включаючи останній запис, основна частина якого може виявитися невикористовуваним простором.

Томи zvol не мають властивості recordsize — натомість вони мають еквівалентну властивість volblocksize.

Сектори

Останній, найбільш базовий будівельний блок – сектор. Це найменша фізична одиниця, яка може бути записана або рахована з базового пристрою. Протягом кількох десятиліть у більшості дисків використовувалися сектори по 512 байт. Останнім часом більшість дисків налаштовано на сектори 4 КіБ, а в деяких - особливо SSD - сектори 8 КіБ або навіть більше.

Система ZFS має властивість, яка дозволяє вручну встановити розмір сектора. Ця властивість ashift. Дещо заплутано, що ashift є ступенем двійки. Наприклад, ashift=9 означає розмір сектора 2, або 9 байт.

ZFS запитує у операційної системи докладну інформацію про кожен блоковий пристрій, коли він додається в новий vdev, і теоретично автоматично встановлює ashift належним чином на основі цієї інформації. На жаль, багато дисків брешуть про розмір сектора, щоб зберегти сумісність з Windows XP (яка була нездатна зрозуміти диски з іншими розмірами секторів).

Це означає, що адміністратору ZFS рекомендується знати фактичний розмір сектора своїх пристроїв і вручну встановлювати ashift. Якщо встановлено занадто маленький ashift, астрономічно збільшується кількість операцій читання/запису. Так, запис 512-байтових "секторів" в реальний сектор 4 КіБ означає необхідність записати перший "сектор", потім прочитати сектор 4 КіБ, змінити його з другим 512-байтовим "сектором", записати його назад у новий сектор 4 КіБ і так далі для кожного запису.

У реальному світі такий штраф б'є по твердотільних накопичувачах Samsung EVO, для яких має діяти ashift=13, але ці SSD брешуть про свій розмір сектора, і тому за умовчанням встановлюється ashift=9. Якщо досвідчений системний адміністратор не змінить цей параметр, цей SSD працює повільніше звичайний магнітний HDD.

Для порівняння, за занадто великий розмір ashift немає ніякого штрафу. Реального зниження продуктивності немає, а збільшення простору, що не використовується, нескінченно мало (або дорівнює нулю при включеному стиску). Тому ми настійно рекомендуємо навіть тим дискам, які дійсно використовують 512-байтові сектори, встановити ashift=12 або навіть ashift=13впевнено дивитися в майбутнє.

властивість ashift встановлюється для кожного віртуального пристрою vdev, а не для пулу, як багато хто помилково думає - і не змінюється після установки. Якщо ви випадково збили ashift при додаванні нового vdev в пул, то ви безповоротно забруднили цей пул пристроєм з низькою продуктивністю і, як правило, немає іншого виходу, крім знищити пул і почати все спочатку. Навіть видалення vdev не врятує від збитого налаштування ashift!

Механізм копіювання під час запису

Основи ZFS: система зберігання та продуктивність
Якщо звичайній файловій системі потрібно перезаписати дані, вона змінює кожен блок там, де він знаходиться.

Основи ZFS: система зберігання та продуктивність
Файлова система з копіюванням під час запису записує нову версію блоку, а потім розблокує стару версію

Основи ZFS: система зберігання та продуктивність
В абстрактному вигляді, якщо ігнорувати реальне фізичне розташування блоків, то наша «комета даних» спрощується до «хробака даних», який переміщається зліва направо картою доступного простору

Основи ZFS: система зберігання та продуктивність
Тепер ми можемо отримати гарне уявлення, як працюють снапшоти копіювання при записі - кожен блок може належати кільком снапшотам, і збережеться доти, доки не будуть знищені всі пов'язані снапшоти

Механізм копіювання під час запису (Copy on Write, CoW) - фундаментальна основа того, що робить ZFS настільки приголомшливою системою. Основна концепція проста — якщо ви попросите традиційну файлову систему змінити файл, вона зробить те, що ви просили. Якщо ви попросите файлову систему з копіюванням під час запису зробити те саме, вона скаже «добре» — але збреше вам.

Натомість файлова система з копіюванням під час запису записує нову версію зміненого блоку, а потім оновлює метадані файлу, щоб розірвати зв'язок зі старим блоком та зв'язати з ним новий блок, який ви щойно записали.

Від'єднання старого блоку та зв'язування нового здійснюється за одну операцію, тому її не можна перервати - якщо ви скидаєте живлення після того, як це відбудеться, у вас є нова версія файлу, а якщо ви скидаєте живлення раніше, то у вас є стара версія. У будь-якому випадку у файловій системі не виникне конфліктів.

Копіювання під час запису в ZFS відбувається не лише на рівні файлової системи, а й на рівні керування дисками. Це означає, що ZFS не схильна до пробілу в записі (дірі в RAID) - Феномену, коли смуга встигла тільки частково записатися до збою системи, з пошкодженням масиву після перезавантаження. Тут смуга пишеться атомарно, vdev завжди послідовний, і Боб - твій дядько.

ZIL: журнал намірів ZFS

Основи ZFS: система зберігання та продуктивність
Система ZFS обробляє синхронні записи особливим чином – вона тимчасово, але негайно зберігає їх у ZIL, перш ніж пізніше записати їх на постійній основі разом із асинхронними записами

Основи ZFS: система зберігання та продуктивність
Зазвичай, дані, записані на ZIL, більше ніколи не зчитуються. Але це можливо після збою системи

Основи ZFS: система зберігання та продуктивність
SLOG, або вторинне LOG-пристрій, - це просто спеціальний - і, бажано, дуже швидкий - vdev, де ZIL може зберігатися окремо від основного сховища

Основи ZFS: система зберігання та продуктивність
Після збою всі брудні дані в ZIL відтворюються - в даному випадку ZIL знаходиться на SLOG, тому вони відтворюються саме звідти

Існує дві основні категорії операцій запису - синхронні (sync) та асинхронні (async). Більшість робочих навантажень переважна більшість операцій записи є асинхронними — файлова система дозволяє агрегувати їх і видавати пакетами, зменшуючи фрагментацію і значно збільшуючи пропускну спроможність.

Синхронні записи – зовсім інша справа. Коли програма запитує синхронний запис, вона говорить файловій системі: «Тобі потрібно зафіксувати це в незалежній пам'яті прямо зараз, А до того часу я більше нічого не можу зробити». Тому синхронні записи мають бути негайно зафіксовані на диску — і якщо це збільшує фрагментацію або зменшує пропускну здатність, то так і бути.

ZFS обробляє синхронні записи інакше, ніж звичайні файлові системи – замість того, щоб негайно заливати їх у звичайне сховище, ZFS фіксує їх у спеціальній області зберігання, яка називається журналом намірів ZFS – ZFS Intent Log, або ZIL. Хитрість у тому, що ці записи також залишаються в пам'яті, будучи агрегованими разом із звичайними асинхронними запитами на запис, щоб пізніше бути скинутими в сховище як нормальні TXG (групи транзакцій, Transaction Groups).

У нормальному режимі роботи ZIL записується і більше не читається. Коли через кілька хвилин записи з ZIL фіксуються в основному сховище в звичайних TXG з оперативної пам'яті, вони від'єднуються від ZIL. Єдине, коли щось зчитується із ZIL – це при імпорті пулу.

Якщо відбувається збій ZFS - збій операційної системи або відключення живлення - коли в ZIL є дані, ці дані будуть прочитані під час наступного імпорту пулу (наприклад, при перезапуску аварійної системи). Все, що знаходиться в ZIL, буде зчитано, об'єднано в групи TXG, зафіксовано в основному сховище, а потім від'єднано від ZIL у процесі імпорту.

Один із допоміжних класів vdev називається LOG або SLOG, вторинне пристрій LOG. У нього одне завдання - забезпечити пул окремим і, бажано, набагато швидшим, з дуже високою стійкістю до запису, пристроєм vdev для зберігання ZIL замість зберігання ZIL на головному сховищі vdev. Сам ZIL поводиться однаково незалежно від місця зберігання, але якщо у vdev з LOG дуже висока продуктивність запису, то синхронні записи відбуватимуться швидше.

Додавання vdev з LOG в пул ніяк не може покращити продуктивність асинхронного запису - навіть якщо ви примусово виконуєте всі записи в ZIL за допомогою zfs set sync=always, вони все одно будуть прив'язані до основного сховища в TXG так само і в тому ж темпі, що і без журналу. Єдиним прямим покращенням продуктивності є затримка синхронного запису (оскільки більша швидкість журналу прискорює виконання операцій sync).

Однак у середовищі, яке вже вимагає великої кількості синхронних записів, vdev LOG може опосередковано прискорити асинхронний запис та некешоване читання. Вивантаження записів ZIL в окремий vdev LOG означає меншу конкуренцію за IOPS у первинному сховищі, що певною мірою підвищує продуктивність усіх операцій читання та запису.

Снапшоти

Механізм копіювання під час запису також є необхідною основою для атомних моментальних знімків ZFS та інкрементальної асинхронної реплікації. В активній файловій системі є дерево покажчиків, яке помічає всі записи з поточними даними - коли ви робите снапшот, ви просто робите копію цього дерева покажчиків.

Коли в активній файловій системі перезаписується запис, ZFS спочатку записує нову версію блоку в простір, що не використовується. Потім від'єднує стару версію блоку від поточної файлової системи. Але якщо якийсь снапшот посилається на старий блок, він все одно залишається незмінним. Старий блок фактично не буде відновлений як вільний простір, доки всі снапшоти, які посилаються на цей блок, не будуть знищені!

Реплікація

Основи ZFS: система зберігання та продуктивність
Моя бібліотека Steam у 2015 році займала 158 ГіБ та включала 126 927 файлів. Це досить близько до оптимальної ситуації для rsync - реплікація ZFS по мережі була "лише" на 750% швидше.

Основи ZFS: система зберігання та продуктивність
У тій же мережі реплікація одного 40-гібібайтного файлу образу віртуальної машини Windows 7 – зовсім інша історія. Реплікація ZFS відбувається у 289 разів швидше, ніж rsync або «всього» в 161 раз швидше, якщо ви достатньо підковані, щоб викликати rsync з ключем — inplace.

Основи ZFS: система зберігання та продуктивність
Коли образ віртуальної машини масштабується, проблеми rsync масштабуються разом із ним. Розмір 1,9 ТіБ не такий великий для сучасного образу віртуальної машини - але він досить великий, щоб реплікація ZFS виявилася в 1148 разів швидше, ніж rsync, навіть з аргументом rsync inplace

Як тільки ви зрозумієте, як працюють снапшоти, буде неважко вловити суть реплікації. Оскільки снапшот - це просто дерево покажчиків на записі, це означає, що якщо ми робимо zfs send Снапшота, то ми відправляємо і це дерево, і всі пов'язані з ним записи. Коли ми передаємо цей zfs send в zfs receive на цільовий об'єкт, він записує як фактичний вміст блоку, і дерево покажчиків, посилаються на блоки, в цільової набір даних.

Все стає ще цікавіше на другому zfs send. Тепер у нас дві системи, кожна з яких містить poolname/datasetname@1, а ви знімаєте новий снапшот poolname/datasetname@2. Тому у вихідному кулі у вас datasetname@1 и datasetname@2, а в цільовому пулі поки що тільки перший снапшот datasetname@1.

Оскільки між джерелом та метою у нас є спільний снапшот datasetname@1, ми можемо зробити інкрементальний zfs send поверх нього. Коли ми говоримо системі zfs send -i poolname/datasetname@1 poolname/datasetname@2, вона порівнює два дерева покажчиків. Будь-які покажчики, які існують тільки в @2, очевидно, посилаються на нові блоки, тому нам знадобиться вміст цих блоків.

У віддаленій системі обробка інкрементального send така ж проста. Спочатку ми записуємо нові записи, включені в потік send, а потім додаємо вказівники на ці блоки. Вуаля, у нас @2 у новій системі!

Асинхронна інкрементальна реплікація ZFS - це величезне поліпшення порівняно з більш ранніми методами, не заснованими на снапшотах, таких як rsync. В обох випадках передаються лише змінені дані, але rsync повинен спочатку прочитати з диска всі дані з обох сторін, щоб перевірити суму та порівняти її. На відміну від цього, реплікація ZFS не зчитує нічого, окрім дерев покажчиків, і будь-яких блоків, які не представлені у загальному снапшоті.

Вбудований стиск

Механізм копіювання під час запису також полегшує систему вбудованого стиснення. У традиційній файловій системі стиск проблематично - як стара версія, так і нова версія змінених даних знаходяться в тому самому просторі.

Якщо розглянути фрагмент даних усередині файлу, який починає своє життя як мегабайт нулів від 0x00000000 і так далі — його дуже легко стиснути до одного сектора на диску. Але що станеться, якщо ми замінимо цей мегабайт нулів на мегабайт даних, таких як JPEG або псевдовипадковий шум? Несподівано цьому мегабайту даних потрібно не один, а 256 секторів по 4 КіБ, а тут на диску зарезервований тільки один сектор.

У ZFS немає такої проблеми, оскільки змінені записи завжди записуються в простір, що не використовується — вихідний блок займає тільки один сектор 4 КіБ, а новий запис займе 256, але це не проблема — недавно змінений фрагмент із «середини» файлу був би записаний в простір, що не використовується. незалежно від того, змінився його розмір чи ні, тому для ZFS це цілком штатна ситуація.

Вбудований стиск ZFS відключено за замовчуванням, і система пропонує алгоритми, що підключаються - зараз серед них LZ4, gzip (1-9), LZJB і ZLE.

  • LZ4 — це потоковий алгоритм, що пропонує надзвичайно швидке стиснення та декомпресію та виграш у продуктивності для більшості випадків використання — навіть на досить повільних CPU.
  • GZIP - Поважний алгоритм, який знають і люблять всі користувачі Unix-систем. Він може бути реалізований з рівнями стиснення 1-9, зі збільшенням ступеня стиснення та використання CPU у міру наближення до рівня 9. Алгоритм добре підходить для всіх текстових (або інших надзвичайно стисливих) варіантів використання, але в іншому випадку часто викликає проблеми з CPU використовуйте його з обережністю, особливо на вищих рівнях.
  • LZJB - Оригінальний алгоритм в ZFS. Він застарів і більше не повинен використовуватися, LZ4 перевершує його за всіма показниками.
  • ZLE - Кодування нульового рівня, Zero Level Encoding. Вона взагалі не торкається нормальних даних, але стискає великі послідовності нулів. Корисно для повністю стисканих наборів даних (наприклад, JPEG, MP4 або інших вже стислих форматів), оскільки він ігнорує дані, що не стискаються, але стискає невикористовуваний простір у підсумкових записах.

Ми рекомендуємо стиск LZ4 практично для всіх варіантів використання; штраф за продуктивність при зустрічі з даними, що не стискаються, дуже малий, а приріст продуктивність для типових даних значний. Копіювання образу віртуальної машини для нової інсталяції операційної системи Windows (нововстановлена ​​ОС, ніяких даних усередині ще немає) compression=lz4 пройшло на 27% швидше, ніж з compression=none, в цьому тесті 2015 року.

ARC - кеш адаптивної заміни

ZFS - це єдина відома нам сучасна файлова система, яка використовує власний механізм кешування читання, а не покладається на кеш сторінок операційної системи для зберігання копій нещодавно прочитаних блоків в оперативній пам'яті.

Хоча власний кеш не позбавлений проблем — ZFS не може реагувати на нові запити про виділення пам'яті так само швидко, як ядро, тому новий виклик malloc() на розподіл пам'яті може зазнати невдачі, якщо йому потрібна оперативна пам'ять, зайнята нині ARC. Але є вагомі причини використовувати власний кеш, принаймні зараз.

Усі відомі сучасні ОС, включаючи MacOS, Windows, Linux та BSD, для реалізації кешу сторінок використовують алгоритм LRU (Least Recently Used). Це примітивний алгоритм, який піднімає кешований блок вгору черги після кожного читання і витісняє блоки вниз черги в міру необхідності, щоб додати нові промахи кеша (блоки, які повинні були бути прочитані з диска, а не з кеша) вгору.

Зазвичай алгоритм працює нормально, але в системах з великими робочими наборами даних LRU легко призводить до трешінгу - витіснення часто необхідних блоків, щоб звільнити місце для блоків, які ніколи більше не прочитаються з кешу.

ARC набагато менш наївний алгоритм, який можна розглядати як «зважений» кеш. Після кожного зчитування кешованого блоку він стає трохи "важчим" і його стає важче витіснити - і навіть після витіснення блок відстежується протягом певного періоду часу. Блок, який був витіснений, але потім має бути рахований назад у кеш, також стане «важчим».

Кінцевим результатом цього є кеш з набагато більшим коефіцієнтом влучення (hit ratio) — співвідношенням між влученнями в кеш (читання, що виконується з кешу) і промахами (читання з диска). Це надзвичайно важлива статистика — мало того, що самі хіти кешу обслуговуються на порядки швидше, промахи кешу також можуть обслуговуватися швидше, тому що чим більше хітів кешу — тим менше паралельних запитів до диска і тим менша затримка для тих промахів, що залишилися, які повинні обслуговуватися з диска.

Висновок

Після вивчення основної семантики ZFS — як працює копіювання під час запису, а також відносин між пулами зберігання, віртуальними пристроями, блоками, секторами та файлами, ми готові обговорити реальну продуктивність із реальними числами.

У наступній частині ми розглянемо фактичну продуктивність пулів із дзеркальними vdev і RAIDz, один у порівнянні з одним, а також у порівнянні з традиційними RAID-топологіями ядра Linux, які ми досліджували раніше.

Спочатку ми хотіли розглянути лише основи – самі топології ZFS – але після такого будемо готові говорити про більш просунуте налаштування та тюнінг ZFS, включаючи використання допоміжних типів vdev, таких як L2ARC, SLOG і Special Allocation.

Джерело: habr.com

Додати коментар або відгук