ZFS SMB: Виправлення проблеми «Копіювання у Windows повільне»

Було корисно?

Windows Explorer показує «Копіювання… 112 MB/s» протягом трьох секунд, потім швидкість падає до 0 B/s і зависає, ніби роздумує про сенс життя. Користувачі звинувачують «мережу». Мережа звинувачує «зберігання». Зберігання звинувачує «Windows». Усі помиляються по-своєму.

Якщо ви працюєте з SMB на базі ZFS (зазвичай Samba на Linux або інколи пристрій зберігання), ви можете зробити копіювання з Windows стабільно швидким. Але не через хаотичне крутіння налаштувань. Потрібно виявити, де з’являється затримка, а потім виправити ту частину, яка «бреше».

Що насправді означає «повільне копіювання» (і чого це не стосується)

«Windows копіювання повільне» — це не одна проблема. Це видима користувачу ознака для конвеєра, який включає: поведінку клієнта Windows, семантику протоколу SMB, деталі реалізації Samba, групи транзакцій ZFS та шляхи запису, і фізичну латентність носіїв. Ваше завдання — знайти етап, де пропускна здатність перетворюється на очікування.

Три шаблони копіювання, які треба розрізняти

  • Великі послідовні копії (наприклад, ISO, VHDX): мають йти ближче до лінійної швидкості, поки сервер може комітити записи достатньо швидко.
  • Багато дрібних файлів (наприклад, дерева вихідного коду): домінують операції з метаданими (створення, setattr, close, rename), а не пропускна здатність.
  • Змішані навантаження (домашні шари + ВМ + сканери): «повільно» часто означає head-of-line blocking — один поганий шаблон псує чергу для всіх.

Чого це зазвичай не стосується

Зазвичай це не «SMB повільний». SMB3 може бути дуже швидким. Зазвичай це не «ZFS повільний». ZFS може наситити серйозні мережі. Зазвичай це спайки затримки від sync-записів, дрібних випадкових I/O, посилення метаданих або поганого вирівнювання кешування, які проявляються в клієнті, що показує оптимістичні сплески швидкості.

Ще одне переналаштування: Windows Explorer — не бенчмарк, а візуалізатор тривоги. Той графік — швидше емоційний індикатор, ніж осцилограф.

Цікаві факти та історичний контекст (щоб поведінка стала зрозумілішою)

  1. SMB1 vs SMB2/3 змінило все. SMB2 (ера Vista/2008) зменшила балакучість, збільшила розміри читань/записів і додала конвеєрування. Багато історій «SMB повільний» насправді — «ви застрягли на SMB1».
  2. Samba починалася як проект з реверс-інженерії. Вона виросла з «змушує UNIX говорити з Windows» до рівня enterprise SMB-сервера. Деякі значення за замовчуванням консервативні, бо Samba має витримувати дивні клієнти.
  3. ZFS групує записи. ZFS комітить дані в transaction group (TXG). Це робить пропускну здатність чудовою, але створює помітний «пульс», якщо фаза коміту затягується.
  4. Sync-записи — це зобов’язання, а не відчуття. Коли SMB-клієнт просить забезпечити надійність, ZFS має безпечно закомітити. Якщо ваш пул не вміє робити low-latency fsync, ви отримаєте класичний графік «швидко, потім нуль».
  5. SMB durable handles і leases змінили поведінку close/open. Сучасний Windows агресивно кешує. Це добре, поки додаток не вимагає семантики durable і не перетворює кешування на синхронний біль.
  6. Recordsize важливіший для файлових шарів, ніж багато кому здається. recordsize ZFS формує I/O-амліфікацію. Неправильний recordsize не лише марнує місце — він додає зайві IOPS при дрібному випадковому доступі.
  7. Стиснення часто допомагає SMB, навіть на швидких CPU. Багато офісних файлів добре стиснюються, знижуючи навантаження на диск і мережу. Перемога часто в латентності, а не в пропускній здатності.
  8. SMB signing став поширенішим з міркувань безпеки. Увімкнення підпису — це податок на CPU. Налаштування «secure» інколи перетворюється на «securely slow», коли серверний CPU слабкий або обмежений одним потоком.

Швидкий план діагностики

Це порядок дій, який швидко знаходить вузьке місце, не впадаючи в пастку «налаштуй усе підряд».

По-перше: класифікуйте навантаження

  • Один великий файл? Багато дрібних файлів? Додаток пише з вимогами до збереження (durability)?
  • Швидкість падає через фіксовані інтервали (кожні кілька секунд)? Це пахне TXG commit latency.
  • Трапляється лише на певних шарах (shares)? Це пахне властивостями dataset або опціями SMB share.

По-друге: вирішіть, чи це мережа, CPU чи латентність зберігання

  • Мережа: помилки інтерфейсу, повторні передачі, неправильний MTU, погане хешування LACP, Wi‑Fi клієнти, які поводяться як сервери.
  • CPU: один ядро завантажене в smbd, наклад від signing/encryption, переривання, насичення softirq.
  • Шлях зберігання: високий await на vdev, блокування шляху ZFS sync, відсутній/повільний SLOG, пул майже заповнений або фрагментований.

По-третє: перевірте поведінку sync (зазвичай це винуватець)

  • Перевірте властивість dataset sync та налаштування Samba, які примушують sync (наприклад, strict sync).
  • Виміряйте fsync-латентність з самого хоста SMB, а не з вашого ноутбука.
  • Якщо потрібна семантика sync, забезпечте правильний SLOG-пристрій (з захистом від втрати живлення) або прийміть обмеження продуктивності ваших основних vdev.

По-четверте: ізолюйте випадок «багато дрібних файлів»

  • Метадані — це навантаження. Перевірте atime, поведінку xattr та продуктивність дрібних блоків.
  • Переконайтеся, що розташування пулу відповідає очікуванням по IOPS для метаданих (компроміс між mirror та RAIDZ).

По-п’яте: налаштовуйте лише те, що показали вимірювання

Якщо ви не можете показати before/after у латентності I/O, завантаженні CPU або повторних передачах, ви не налаштовуєте — ви декоруєте.

Припиніть здогадки: вимірюйте, куди йде час

SMB-копії — це переговори між клієнтом, який буферизує, і сервером, який комітить. Explorer показує «швидкість» на основі того, як швидко дані приймаються в буфери, а не того, наскільки швидко вони надійно записані. Тоді як ZFS може швидко прийняти дані в ARC і «грязні» буфери, а потім призупинитись під час коміту TXG. Саме ця пауза викликає нуль на графіку.

Ваш план вимірювань має відповісти на три питання:

  1. Чи клієнт чекає на сервер (латентність), чи він просто не надсилає (обмеження клієнта)?
  2. Чи сервер чекає на скидання на диск (sync-путь), чи на CPU (signing/encryption), чи на мережу?
  3. Чи ZFS підсилює навантаження (несумісний recordsize, фрагментація, тиск на метадані)?

Інженерія надійності має просте правило: вимірюйте систему, яка у вас є, а не ту, якою ви хотіли б її бачити.

Парафраз (Gene Kim): «Покращення потоку означає знаходження та усунення обмеження». Ось у чому справа.

Реалії ZFS, які ускладнюють роботу з SMB

TXG і шаблон «швидко, потім нуль»

ZFS накопичує «брудні» дані в пам’яті і періодично комітить їх на диск як transaction group. Якщо фаза коміту затягується, система пригальмовує записувачів. Очима клієнта: швидкий сплеск, потім пауза. Повторюється. Це не «мережева нестабільність». Це збереження надійності зберігання.

Sync-записи: податок на надійність

Коли навантаження виконує синхронні записи (або сервер їх трактує як такі), ZFS має гарантувати, що дані на стабільному носії перед підтвердженням. На пулах без швидкого intent log (SLOG) sync-записи лягають на основні vdev. Якщо це RAIDZ на HDD, результат передбачуваний: біль з часовими відмітками.

Recordsize, ashift та I/O-ампліфікація

recordsize ZFS керує максимальною роздільною здатністю блоків для даних файлу. SMB-шерінги часто містять змішані розміри файлів; занадто великий recordsize не завжди шкодить послідовним читанням, але може нашкодити випадковим записам і частковим перезаписам. Занадто малий — збільшує накладні витрати на метадані і погіршує ефективність стиснення.

Метадані не «безкоштовні»

Копії дрібних файлів навантажують метадані: записи в директоріях, ACL, xattr, timestamps. ZFS може це обробити, але тільки якщо макет пулу і кешування розумні. Якщо ви побудували широкий RAIDZ для ємності і потім використовуєте його для метаданих важкого SMB-шару, ви фактично купили автобус і заявили його на мотогонку.

Заповненість пулу та фрагментація

Коли пул заповнюється, розміщення блоків ускладнюється, фрагментація зростає, і латентність зростає. Користувачі SMB відчують це як «все працювало минулого місяця». ZFS не забуває, як писати; йому просто виснажуються легкі місця для розміщення блоків.

Реалії SMB, які ускладнюють роботу з ZFS

Семантика копіювання Windows: буферизація, close і надійність

Windows може буферизувати записи й вимагати надійності лише при закритті файлу, залежно від прапорів додатка та конфігурації сервера. Деякі додатки (і деякі засоби безпеки) вимагають write-through семантики. Це миттєво перетворює навантаження з «переважно async» на «сильно sync».

Signing і шифрування: безпека має ціну CPU

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

SMB3 Multichannel: чудово, коли працює, неважливо, коли ні

Multichannel може використовувати кілька NIC і черг RSS. При неправильному конфігу ви отримаєте єдиний TCP-потік, застряглий на одній черзі. Тоді хтось скаже «але у нас подвійний 10GbE», ніби сервер зобов’язаний зацікавитися.

Opportunistic locks, leases і антивірус

Кешування на клієнті (oplocks/leases) зменшує чати. Але засоби безпеки на кінцевих точках люблять відкривати файли, змушувати оновлювати атрибути і загалом ламати поведінку кешування. Це може перетворити копію «багато дрібних файлів» в шаленство системних викликів.

Жарт №1: Трасування проблем SMB схоже на офісну політику — кожен наполягає, що він вузьке місце, і всі вони якимось чином праві.

Практичні завдання: команди, виводи, рішення

Нижче — реальні завдання, які ви можете виконати на SMB/ZFS сервері. Кожне містить, що означає вивід і яке рішення потрібно прийняти далі. Приклади орієнтовані на Linux + Samba + OpenZFS, бо саме там більшість тикетів «Windows копіювання повільне» живе.

Завдання 1: Підтвердіть стан пулу (бо продуктивність часто — симптом помираючого диска)

cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 04:12:19 with 0 errors on Tue Dec 10 03:20:01 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_A   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_B   ONLINE       0     0     0

errors: No known data errors

Значення: «ONLINE» і чистий scrub означають, що ви не боретесь із прихованими ретраями чи навантаженням resilver. Якщо ви бачите DEGRADED, resilvering або checksum errors, припиніть тонке налаштування продуктивності і спочатку виправте апаратні проблеми.

Рішення: Якщо будь-який vdev показує помилки або триває resilver, заплануйте усунення та перевірте продуктивність після стабілізації.

Завдання 2: Перевірте заповненість пулу (майже повні пули повільні в передбачуваний спосіб)

cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint tank
NAME   USED  AVAIL  REFER  MOUNTPOINT
tank   38.2T 2.1T   96K    /tank

Значення: ~95% заповнений (38.2T used, 2.1T avail) — це зона ризику для багатьох навантажень. Розміщення ускладнюється; фрагментація зростає.

Рішення: Якщо використання понад ~80–85% і продуктивність важлива, плануйте звільнення місця або розширення. Жоден параметр Samba не переможе фізику.

Завдання 3: Визначте dataset, який використовує SMB share, і виведіть ключові властивості

cr0x@server:~$ sudo zfs get -H -o property,value recordsize,compression,atime,sync,xattr,acltype,primarycache,logbias tank/shares/engineering
recordsize	1M
compression	lz4
atime	on
sync	standard
xattr	sa
acltype	posixacl
primarycache	all
logbias	latency

Значення: У вас recordsize 1M (добре для великих послідовних файлів, ризиковано для часткових перезаписів), atime увімкнено (додаткові записи метаданих), sync standard (sync шанується), xattr у SA (часто добре), logbias latency (віддає перевагу SLOG якщо є).

Рішення: Якщо шар — «багато дрібних файлів», розгляньте recordsize=128K і atime=off. Якщо це образи ВМ, інша стратегія потрібна (ймовірно не через SMB).

Завдання 4: Виміряйте I/O-латентність пулу під час копіювання (істина в iostat)

cr0x@server:~$ sudo zpool iostat -v tank 1 5
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        38.2T  2.1T     12   2400   3.1M   210M
  mirror-0                  38.2T  2.1T     12   2400   3.1M   210M
    ata-SAMSUNG_SSD_1TB_A      -      -      6   1250   1.6M   108M
    ata-SAMSUNG_SSD_1TB_B      -      -      6   1150   1.5M   102M
--------------------------  -----  -----  -----  -----  -----  -----

Значення: Висока кількість операцій запису (2400/s) з помірною пропускною спроможністю вказує на дрібні записи або sync-важке навантаження. Якщо пропускна здатність низька, але ops високі, ви обмежені IOPS або flush-путтям.

Рішення: Якщо записи дрібні й часті, дослідіть синхронні семантики, навантаження на метадані та невідповідність recordsize. Якщо ops низькі і пропускна здатність низька — підозрюйте мережу або обмеження SMB.

Завдання 5: Спостерігайте латентність по vdev через iostat (await — як сигнал тривоги)

cr0x@server:~$ sudo iostat -x 1 3
Linux 6.6.15 (server) 	12/25/2025 	_x86_64_	(16 CPU)

Device            r/s     w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await  r_await  w_await  svctm  %util
nvme0n1           2.0   950.0    64.0 118000.0   248.0     3.20    3.4     1.2      3.4    0.6   58.0
nvme1n1           1.0   910.0    32.0 112000.0   246.0     3.05    3.3     1.1      3.3    0.6   55.0

Значення: ~3.3ms write await — це нормально для NVMe. Якщо під час копій ви бачите десятки/сотні ms, зберігання обмежує вашу пропускну здатність.

Рішення: Високий await + низький CPU + чиста мережа = проблема шляху зберігання (sync-записи, заповнений пул, повільні vdev або проблеми з SLOG).

Завдання 6: Перевірте, чи взагалі є у вас SLOG (і чи він щось робить)

cr0x@server:~$ sudo zpool status tank | sed -n '1,120p'
  pool: tank
 state: ONLINE
config:

        NAME                         STATE     READ WRITE CKSUM
        tank                         ONLINE       0     0     0
          mirror-0                   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_A    ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_B    ONLINE       0     0     0
        logs
          nvme-SLOG_INTEL_OPTANE     ONLINE       0     0     0

Значення: Є окремий лог-пристрій. Добре. Але наявність не означає продуктивність; пристрій має бути швидким і захищеним від втрати живлення.

Рішення: Якщо існують sync-важкі навантаження і SLOG відсутній, вирішіть, чи потрібна вам семантика sync. Якщо так — додайте відповідний SLOG. Якщо ні — не підмінюйте це sync=disabled, якщо ви не готові втрачати підтверджені дані при відключенні живлення.

Завдання 7: Спостерігайте TXG-тротлінг і поведінку «брудних» даних

cr0x@server:~$ sudo arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c  avail
12:10:01   320    12      4     1    0    11    3     0    0   84.2G  96.0G  21.4G
12:10:02   410    16      3     2    0    14    3     0    0   84.2G  96.0G  21.4G
12:10:03   390    10      2     1    0     9    2     0    0   84.2G  96.0G  21.4G

Значення: ARC не має суттєвих промахів; кешування не є вашим поточним обмеженням. Якщо ARC малий відносно пам’яті або промахи стрімко зростають, можливо ви обмежені пам’яттю або маєте неправильні налаштування.

Рішення: Якщо під час читань промахи ARC високі, налаштуйте розмір пам’яті/ARC або набір робочих даних (або прийміть, що навантаження не кешується добре).

Завдання 8: Підтвердіть версію Samba і чи погоджується SMB3

cr0x@server:~$ smbd -V
Version 4.19.5-Debian

cr0x@server:~$ sudo smbstatus -b | sed -n '1,60p'
Samba version 4.19.5-Debian
PID     Username     Group        Machine                                   Protocol Version  Encryption           Signing
-------------------------------------------------------------------------------------------------------------------------
23144   user1        domain users  10.10.20.55 (ipv4:10.10.20.55:53122)     SMB3_11           -                    partial

Значення: SMB3_11 погоджено, це добре. Signing показано «partial» (залежить від конфігурації і клієнта). Якщо ви бачите SMB1 — у вас проблеми більші, ніж налаштування.

Рішення: Якщо виявлено SMB1, вимкніть його і усуньте сумісність клієнтів усвідомлено. Не тримайте SMB1 «через один старий сканер». Замініть сканер або ізолюйте його.

Завдання 9: Перевірте конфіг Samba на наявність «вбивць» sync (strict sync, sync always)

cr0x@server:~$ sudo testparm -sv | sed -n '/^\[engineering\]/,/^\[/{p}'
[engineering]
	path = /tank/shares/engineering
	read only = No
	vfs objects = acl_xattr
	strict sync = Yes
	sync always = No

Значення: strict sync = Yes змушує Samba виконувати більше flush-ів. Це класичне налаштування «ми ввімкнули його для безпеки», яке може знищити пропускну здатність.

Рішення: Якщо у вас немає суворої вимоги відповідності, виставте strict sync = No і перевірте коректність додатків. Якщо потреба є — інвестуйте в SLOG і низьколатентне зберігання.

Завдання 10: Перевірте, чи увімкнено SMB signing/encryption і чи є CPU-обмеження

cr0x@server:~$ sudo smbstatus -b | awk 'NR==1 || NR==2 || $0 ~ /SMB3/'
Samba version 4.19.5-Debian
PID     Username     Group        Machine                                   Protocol Version  Encryption           Signing
23144   user1        domain users  10.10.20.55 (ipv4:10.10.20.55:53122)     SMB3_11           AES-128-GCM          mandatory

cr0x@server:~$ top -b -n 1 | sed -n '1,20p'
top - 12:12:41 up 34 days,  3:01,  2 users,  load average: 9.12, 8.40, 7.95
Tasks: 291 total,   2 running, 289 sleeping,   0 stopped,   0 zombie
%Cpu(s): 12.1 us,  2.0 sy,  0.0 ni, 78.0 id,  0.0 wa,  0.0 hi,  7.9 si,  0.0 st
MiB Mem :  256000.0 total,  21000.0 free,  95000.0 used, 140000.0 buff/cache

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

Рішення: Якщо encryption/signing обов’язкові і CPU гарячий — оновіть CPU, використовуйте системи з AES-NI, налаштуйте RSS і multiqueue, або звузьте шифрування до конкретних чутливих шарів.

Завдання 11: Перевірте лінк NIC, дуплекс та лічильники помилок (дешеві перевірки, дорогі наслідки)

cr0x@server:~$ ip -s link show dev bond0
2: bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 9c:dc:71:aa:bb:cc brd ff:ff:ff:ff:ff:ff
    RX:  bytes packets errors dropped  missed   mcast
    1223344556677 1023344556      0       0       0  120034
    TX:  bytes packets errors dropped carrier collsns
    1334455667788 1124455667      0       0       0       0

cr0x@server:~$ ethtool bond0 | sed -n '1,25p'
Settings for bond0:
	Supported ports: [ ]
	Supported link modes:   Not reported
	Speed: 20000Mb/s
	Duplex: Full
	Auto-negotiation: off

Значення: Немає помилок, повний дуплекс, очікувана швидкість. Якщо ви бачите помилки або дропи — виправляйте мережу перш ніж чіпати ZFS.

Рішення: Якщо є помилки: перевірте кабелі, порти комутатора, узгодженість MTU та налаштування offload. Налаштування продуктивності поверх втрат пакетів — це театр.

Завдання 12: Перевірте повторні передачі TCP та тиск на сокети (SMB над хворою мережею — ілюзія)

cr0x@server:~$ ss -s
Total: 884
TCP:   211 (estab 104, closed 72, orphaned 0, timewait 72)

Transport Total     IP        IPv6
RAW	  0         0         0
UDP	  11        8         3
TCP	  139       113       26
INET	  150       121       29
FRAG	  0         0         0

cr0x@server:~$ netstat -s | sed -n '1,80p'
Tcp:
    154239 active connection openings
    149802 passive connection openings
    1124 failed connection attempts
    1821 connection resets received
    0 connections established
    224159 segments received
    231008 segments sent out
    214 segments retransmitted

Значення: Повторні передачі є, але не у величезній кількості. Якщо під час копій retransmits зростають, ви побачите паузи, що не пов’язані зі зберіганням. SMB чутливий до стрибків латентності.

Рішення: Високі retransmits: перевірте буфери комутатора, невідповідність MTU, драйвер/прошивку NIC або перевантажений шлях через фаєрвол.

Завдання 13: Визначте, чи навантаження sync-важке (серверний тест fsync)

cr0x@server:~$ sync; sudo bash -c 'time dd if=/dev/zero of=/tank/shares/engineering/.fsync-test bs=1M count=256 conv=fdatasync status=none'
real	0m1.92s
user	0m0.00s
sys	0m0.28s

cr0x@server:~$ sudo rm -f /tank/shares/engineering/.fsync-test

Значення: Це вимірює «запис, а потім примусове забезпечення надійності». Якщо це повільно (наприклад, 10–60s), ваш пул не може швидко комітити sync-записи для SMB-навантажень, які їх вимагають.

Рішення: Повільний fsync: додайте/перевірте SLOG, зменшіть кількість примусових sync у Samba, якщо це прийнятно, або переробіть зберігання для низьколатентних записів.

Завдання 14: Переконайтеся, що dataset випадково не змушує sync вимкненим (або увімкненим) там, де ви не планували

cr0x@server:~$ sudo zfs get -H -o name,property,value sync tank/shares/engineering tank/shares/finance
tank/shares/engineering	sync	standard
tank/shares/finance	sync	always

Значення: Finance share має примусово встановлене sync=always. Це може бути свідомо (додатки потребують надійності) або помилкова конфігурація, що робить його повільним.

Рішення: Якщо знайдено sync=always, уточніть у власників додатків причини. Якщо ніхто не може обґрунтувати — поверніть на standard і протестуйте.

Завдання 15: Перевірте стиснення ZFS і реальне співвідношення (бо «ми увімкнули стиснення» ≠ «воно працює»)

cr0x@server:~$ zfs get -H -o name,property,value compression,compressratio tank/shares/engineering
tank/shares/engineering	compression	lz4
tank/shares/engineering	compressratio	1.62x

Значення: 1.62x означає, що ви економите I/O і місце. Якщо ratio ~1.00x, стиснення мало допомагає, але звичайно LZ4 не шкодить.

Рішення: Тримайте LZ4 за замовчуванням. Відключайте лише якщо виміряли насичення CPU і дані майже не піддаються стисненню.

Завдання 16: Пошукайте патологічну фрагментацію (особливо якщо пул старий і майже повний)

cr0x@server:~$ sudo zdb -bbbs tank | sed -n '1,40p'
Block Size Histogram:
 512: 0
 1K : 0
 2K : 1048576
 4K : 2097152
 8K : 1048576
 16K: 524288
 32K: 262144
 64K: 131072
 128K: 65536
 256K: 32768
 512K: 16384
 1M : 8192

Значення: Це грубий огляд; на практиці ви звʼяжете фрагментацію з поведінкою розміщення і латентністю. Велике різноманіття дрібних блоків у dataset, призначеному для великих послідовних записів, може бути підказкою.

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

Три міні-історії з корпоративної практики

Міні-історія 1: Інцидент через хибне припущення

У них був новий ZFS-файловий сервер і два uplink по 10GbE. Розгортання виглядало добре перший тиждень, переважно тому, що тест був «скопіювати 20GB ISO один раз», і всі пішли додому задоволені.

Потім настав кінець кварталу. Фінанси завантажили тисячі дрібних PDF і таблиць у шар з Windows-додатку, який вимагав write-through. Користувачі повідомили, що копії «зависають кожні кілька секунд». Мережа не бачила насичення, тому її визнали вільною від вини. Команда зберігання бачила багато вільної RAM і гадала, що ARC все вирівняє. Але ні.

Хибне припущення було тонким: «Якщо пул може робити 1GB/s послідовних записів, він може робити офісні копії». Це різні види навантаження. Послідовна пропускна спроможність — це парадний заїзд; sync-важкі метадані — це смуга перешкод.

Коли хтось запустив простий тест dd ... conv=fdatasync на dataset, стало очевидно. Латентність коміту sync була вузьким місцем. Пул був RAIDZ на HDD. Чудово для ємності, жахливо для низьколатентних записів.

Виправлення теж було делікатним: вони не вимикали sync. Додали якісний SLOG з захистом від втрати живлення і прибрали strict sync з шарів, які цього не вимагали. Фінанси зберегли свої гарантії, інженери повернули швидкість. Тікети служби підтримки припинилися — це єдина KPI, що справді має значення, коли ти на чергуванні.

Міні-історія 2: Оптимізація, що відкотилася

Інша компанія мала повільні копії домашніх директорій. Хтось прочитав форум і вирішив «більший recordsize — значить швидше». Тому вони виставили recordsize=1M для всіх SMB dataset, включно з домашніми та проектними деревами.

Великі файли трохи прискорилися. Потім скарги стали дивнішими: збереження дрібних документів загальмувало, доступ до Outlook PST став ривкоподібним, і деякі додатки почали «не відповідати» при збереженні. Сервер SMB не впав; він просто виконував зайву роботу.

Чому? Часткові перезаписи великих блоків можуть створити write amplification. Невелика зміна в файлі може викликати read-modify-write великого блоку, особливо коли навантаження випадкове і додаток робить багато дрібних оновлень. ZFS — copy-on-write, тож і так веде детальний облік; додаткова ампліфікація — це як просити його жонглювати на біговій доріжці.

Невдала «оптимізація» також збільшила навантаження на метадані, бо профілі користувачів генерують купу дрібних файлів і атрибутних оновлень. Більший recordsize не допоміг у шляху метаданих; він лише зробив шлях даних менш дружнім.

Відкат був дисциплінований: вони розділили dataset за робочим навантаженням. Домашні директорії отримали 128K recordsize, atime off. Великі архіви залишилися на 1M. Продуктивність стабілізувалась. Урок закарбувався: налаштування — не шведський стіл, де можна все навантажити.

Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію

Команда, що керувала ZFS + Samba кластером, мала одну непримітну звичку: щотижневі звіти scrub і щомісячні базові знімки продуктивності. Не панелі для керівництва. Просто текстовий файл з zpool status, zpool iostat під навантаженням і базові лічильники помилок NIC.

Одного вівторка користувачі повідомили про «стрибкоподібні» копії. Інженер на чергуванні не гадала. Вони порівняли базовий знімок з поточними числами. Велика зміна: латентність запису на одній нозі mirror трохи піднялася, і з’явилися виправні помилки — достатньо, щоб викликати ретраї, але не достатньо, щоб диск вийшов з ладу.

Оскільки були історичні дані, вони не витратили півдня на суперечки про прапори Samba. Вони замінили диск у вікні технічного обслуговування, зробили resilver, і затримки копій зникли.

Нічого героїчного. Жодних магічних налаштувань. Просто помічати, що «регрес продуктивності» часто означає «апарат старіє повільно». Ось як виглядає нудна компетентність у продакшені.

Рішення з налаштування, які справді дають ефект

1) Визначте свою позицію щодо sync явно (не дозволяйте цьому статися випадково)

SMB-навантаження можуть бути sync-важкими, особливо з певними додатками і політиками. У вас є три варіанти:

  • Шанувати sync і платити за це: тримайте sync=standard, уникайте налаштувань Samba, які примушують додаткові flush, і розгорніть реальний SLOG, якщо потрібен.
  • Примусово sync завжди: sync=always для шарів з вимогами відповідності. Очікуйте нижчу пропускну спроможність; проектуйте зберігання відповідно.
  • Вимкнути sync: sync=disabled — бізнес-рішення, щоб ризикувати втратою підтверджених записів при відключенні живлення або збої. Це може бути прийнятно для тимчасових шарів, але не видавайте це за «безкоштовну продуктивність». Це інша угода щодо надійності.

2) Розділіть dataset за навантаженням (один шар — одна поведінка)

Один dataset для всього — найшвидший спосіб переконатися, що нічого не буде добре. Розділіть:

  • Домашні директорії (метадані-важкі, дрібні файли)
  • Інженерні проектні дерева (багато дрібних файлів, переважно для читання)
  • Медіа-архіви (великі послідовні файли)
  • Зони доставки додатків (можуть вимагати суворої надійності)

Потім задайте властивості на dataset: recordsize, atime, sync, стиснення, поведінка ACL.

3) Підібрати recordsize «достатньо правильно»

  • Загальні SMB-шари: почніть з recordsize=128K.
  • Архіви великих файлів: розгляньте recordsize=1M, якщо більшість файлів великі і послідовні.
  • Бази даних/образи ВМ поверх SMB: уникайте цього, якщо можете; якщо ні — використовуйте спеціальні налаштування і ретельно тестуйте. SMB-файлообслуговування і datastore для ВМ — не випадкове поєднання.

4) Вимкніть atime для SMB-шарів (якщо немає реальної потреби)

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

5) Тримайте LZ4 стиснення за замовчуванням

LZ4 — одне з небагатьох «дефолтних» налаштувань, яке я захищаю в продакшені. Воно часто підвищує ефективну пропускну здатність і зменшує I/O. Не ускладнюйте до доказу з насичення CPU.

6) Використовуйте реальний SLOG, коли він потрібен (і не економте)

SLOG-пристрій — це не «будь-який SSD». Він має мати низьку латентність під sync-навантаженням і захист від втрати живлення. Інакше ви побудували дорогий генератор латентності.

7) Samba: уникайте «strict sync», якщо не можете його обґрунтувати

strict sync може знищити пропускну спроможність для навантажень, що генерують багато fsync-пунктів (включно з певною поведінкою Windows при закритті файлів). Якщо вам потрібна сувора семантика — зробіть зберігання здатним її підтримувати. Якщо ні — не платіть за це.

8) SMB signing/encryption: сфокусуйте застосування

Команди безпеки люблять загальні політики. Продукційні системи люблять бюджети. Якщо підпис/шифрування обов’язкові, переконайтеся, що хост SMB має запас CPU і сучасне апаратне прискорення криптооперацій. Якщо тільки певні шари містять чутливі дані — обмежуйте політики на рівні шару або трафіку.

Жарт №2: Нічого не робить файловий сервер швидшим так, як політичне засідання, що закінчилося словами «ми нічого не змінювали».

Типові помилки: симптом → корінь проблеми → фікс

1) Симптом: Копія починається швидко, потім падає до 0 B/s повторно

Корінь проблеми: TXG commit stalls через sync-записи або повільну латентність flush (немає SLOG, повільні vdev, пул занадто заповнений).

Виправлення: Виміряйте fsync (dd ... conv=fdatasync), перевірте налаштування Samba щодо sync, додайте якісний SLOG або переробіть пул для низької латентності, звільніть місце.

2) Симптом: Великі файли копіюються нормально; багато дрібних файлів повзають

Корінь проблеми: Навантаження, що залежить від метаданих (ACL, xattr, timestamps) плюс обмеження дрібних випадкових I/O.

Виправлення: atime=off, переконайтеся у відповідних властивостях dataset, розгляньте зеркала для пулів з високими вимогами метаданих, перевірте, чи VFS-модулі Samba не додають накладних витрат; прийміть, що це IOPS, а не bandwidth.

3) Симптом: Швидкість обмежується приблизно ~110 MB/s на «10GbE»

Корінь проблеми: Клієнт/сервер погодили 1GbE, неправильне хешування LACP або один TCP-потік без multichannel.

Виправлення: Перевірте швидкість лінку через ethtool, перевірте конфіг switch, протестуйте SMB multichannel і переконайтеся, що клієнт не знаходиться в сегменті 1GbE.

4) Симптом: Продуктивність гірша після увімкнення SMB signing або encryption

Корінь проблеми: CPU-обмеження в крипто/підписі, одномодульні «гарячі» місця, недостатні RSS-черги.

Виправлення: Виміряйте завантаження CPU по ядрах під час передачі, увімкніть multiqueue/RSS, оновіть CPU, звужуйте зону застосування signing/encryption або використайте обладнання з прискоренням.

5) Симптом: Копії час від часу зависають «саме на кілька секунд»

Корінь проблеми: Повторні передачі в мережі, bufferbloat або конгестія комутатора; іноді часи TXG збігаються з паузами.

Виправлення: Перегляньте retransmits (netstat -s), дропи інтерфейсу і лічильники комутатора. Якщо чисто — поверніться до перевірки латентності зберігання та sync.

6) Симптом: Один шар повільний; інший на тому ж сервері ок

Корінь проблеми: Різниця властивостей dataset (sync=always, дивний recordsize, atime on), відмінності в конфігурації Samba (strict sync, VFS-модулі) або квоти/резервування, що впливають на розміщення.

Виправлення: Порівняйте виходи zfs get і блоки testparm -sv для обох шарів. Нормалізуйте усвідомлено.

7) Симптом: «Windows каже, що потрібно 2 години», але сервер виглядає простою

Корінь проблеми: Сканування на стороні клієнта (антивірус, індексація), накладні витрати на дрібні файли або клієнт чекає на кожну операцію метаданих.

Виправлення: Відтворіть на чистому клієнті, протестуйте robocopy з опціями і перевірте метрики сервера під час операції. Не налаштовуйте сервери, щоб компенсувати проблемні кінцеві точки.

Контрольні списки / покроковий план

Покроково: виправлення «швидко, потім нуль» SMB-копій на ZFS

  1. Підтвердіть стан пулу: zpool status -v. Якщо degraded або помилки — зупиніться і виправте диски.
  2. Перевірте заповненість пулу: zfs list. Якщо >85% використано — плануйте очищення/розширення.
  3. Визначте dataset і властивості: zfs get recordsize,atime,sync,compression.
  4. Перегляньте конфіг Samba: testparm -sv на предмет strict sync, aio та VFS-модулів.
  5. Виміряйте sync-латентність: серверний dd ... conv=fdatasync. Якщо повільно — це головний підозрюваний.
  6. Перевірте наявність/продуктивність SLOG: zpool status для логів і впевніться, що клас пристрою відповідний.
  7. Спостерігайте латентність дисків під навантаженням: iostat -x і zpool iostat під час відтворення.
  8. Перевірте здоровʼя мережі: ip -s link, retransmits (netstat -s) і швидкість лінку (ethtool).
  9. Застосовуйте по одній зміні: наприклад, відключіть strict sync на тестовому шарі або додайте SLOG; потім повторіть ту саму передачу і порівняйте.
  10. Запишіть результат: зніміть латентність, пропускну здатність і чи зникли паузи. Памʼять тьмяніє; тикети — ні.

Базовий контрольний список (нудні речі, за які ви подякуєте собі)

  • Щотижневий scrub запланований; звіти scrub переглядаються.
  • Щомісячний знімок: zpool status, ключові властивості zfs get, ip -s link і повторюваний тест throughput + fsync.
  • Макет dataset документований за категорією навантаження.
  • Ясна політика щодо sync: які шари вимагають гарантій надійності.
  • Контроль змін для конфігурації Samba; без «однорядкових фіксів» у продакшені о 2-й ночі.

ЧаПи

1) Чому Windows Explorer показує швидку швидкість, а потім 0 B/s?

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

2) Чи robocopy швидший за Explorer?

Іноді. Велика перевага в тому, що robocopy передбачуваніший і скриптуємий, та показує повторні спроби і поведінку по файлах. Він не вирішить синхронну латентність на сервері.

3) Чи варто ставити sync=disabled, щоб прискорити?

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

4) Чи потрібен мені SLOG для SMB?

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

5) Який recordsize слід використовувати для SMB-шарів?

Починайте з 128K для загального призначення. Використовуйте 1M для великих послідовних архівів. Уникайте глобальних змін; розділяйте dataset за навантаженням.

6) Чи ввімкнення LZ4 сповільнить роботу?

Зазвичай ні, і часто воно пришвидшує роботу, зменшуючи I/O. Якщо CPU вже завантажений (шифрування/підпис, важке навантаження), виміряйте перед прийняттям рішення.

7) Чи RAIDZ поганий для SMB?

Не «поганий», але RAIDZ менш дружній до дрібних випадкових записів і метаданих-важких навантажень, ніж mirror. Якщо ваш SMB-випадок — багато дрібних файлів і sync-поведінка, mirrored vdev часто виграють по латентності.

8) Чому один SMB-шар повільний, а інші — ок?

Різні властивості dataset або опції Samba. Шукайте sync=always, atime=on, дивний recordsize або strict sync лише на одному шарі.

9) Чи SMB Multichannel вирішує все?

Ні. Воно може підвищити пропускну здатність і стійкість, але не виправить латентність зберігання або sync-паузи. Також вимагає коректних NIC, драйверів і підтримки на клієнті.

10) Як зрозуміти, що проблема в CPU?

Під час передачі одне або кілька ядер будуть постійно завантажені, часто в smbd або ядровому networking/crypto. Тим часом диски і NIC не будуть насичені. Це ваш знак.

Наступні кроки на цей тиждень

Виконайте ці кроки у порядку. Кожен крок робить рішення очевиднішим, і жоден не вимагає віри.

  1. Виберіть один відтворюваний тест трансфер (один великий файл і одна папка «багато дрібних файлів») і тримайте його постійним.
  2. Запустіть швидкий план діагностики і збережіть виводи: zpool iostat, iostat -x, ip -s link, netstat -s, smbstatus.
  3. Доведіть або виключіть синхронну латентність за допомогою серверного тесту dd ... conv=fdatasync на dataset.
  4. Розділіть dataset за навантаженням, якщо ще не зроблено. Встановіть atime=off і розумні recordsize для кожної категорії.
  5. Виправте реальне вузьке місце: додайте якісний SLOG для sync-важких шарів, звільніть місце якщо пул занадто повний, або розвʼяжіть CPU/мережеві проблеми якщо саме вони — джерело.
  6. Напишіть односторінковий ранбуk з базовими командами і «нормальними» виводами. Майбутнє ви купить каву минулому вам.

Мета не в ідеальному графіку. Мета — передбачувана продуктивність в межах контракту на надійність, який ви справді хочете надавати. Коли ви свідомо обираєте цей контракт, ZFS і SMB перестають бути містичними і стають… просто вимогливими.

← Попередня
Docker: резервні копії, які ви ніколи не перевіряли — як правильно провести репетицію відновлення
Наступна →
MySQL vs PostgreSQL: JSON-навантаження — швидкий шлях чи довгостроковий біль

Залишити коментар