«640 КБ достатньо»: цитатний міф, який не вмирає

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

Десь у вашій організації є клітинка в таблиці, яка мовчки припускає «ця межа не важлива».
Це може бути глибина черги, стандартний розмір купи JVM, кількість inode, розмір NAT-таблиці, кеш запису або «тимчасовий» том на 10 ГБ.
Ніхто не пам’ятає, чому саме таке число. Усі ставляться до нього як до фізики.

Ось чому ви опиняєтеся на інцидентному дзвінку о 03:00, сперечаючись з графіками, які здаються вигадкою.
Цитата «640 КБ достатньо» виживає, бо вона підживлює нашу найгіршу звичку: вважати сьогоднішні обмеження постійними, а завтрашній попит — перемовним.

Міф, чому він чіпкий і чому він нас чому навчає

Цитата зазвичай звучить так: «640 КБ має вистачити будь-кому.» Її зазвичай приписують Біллу Гейтсу, поміщають у ранню епоху ПК
і використовують як жарт про зарозумілість, короткозорість або про те, як швидко змінюються технології.

Проблема в тому, що немає надійних свідчень, що він це сказав. Атрибуція хитка, часові рамки неясні, і цитата часто з’являється в друку задовго після події.
І все ж історія живе, бо вона корисна. Вона стискає складну історію апаратного забезпечення, операційних систем і бізнесових компромісів в одне глузливе речення.

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

Ось що треба пам’ятати: 640 КБ не було вірою у майбутнє; це була межа, створена архітектурними рішеннями й тиском сумісності.
Сучасний еквівалент — не «хтось думав, що ОЗП не зростатиме». Це «ми не знаємо, яка межа реальна, яка — дефолт, а яка — міна».

Перший короткий жарт: цитата «640 КБ достатньо» схожа на зомбі-квиток інциденту — ніхто не знає, хто його створив, але він постійно перевідкривається.

Факти й контекст: чим насправді була межа 640 КБ

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

8 фактів, які пояснюють межу 640 КБ (і чому вона не була випадковою)

  1. Оригінальний IBM PC використовував Intel 8088, адресна модель якого й рання архітектура ПК робили 1 МБ адресного простору природною межею для тієї епохи.
    «Обмеження в 1 МБ» не було відчуттям; воно було структурним.
  2. Звичайна пам’ять була перші 640 КБ (0x00000–0x9FFFF). Вище розташовувалася зарезервована область для відеопам’яті, ROM і апаратних відображень.
    Та зарезервована область і пояснює, чому «640 КБ» виглядає як чисте число.
  3. Верхня область пам’яті (UMA) існувала не просто так: відеоадаптери, BIOS ROM і розширювальні ROM потребували адресного простору.
    Сумісність із ПК не була опцією; вона була товаром.
  4. MS-DOS працював у реальному режимі, тому він жив у світі цієї «звичайної» пам’яті.
    Можна лаяти історію, але процесор усе ще робив те, що процесор робить.
  5. Expanded memory (EMS) і extended memory (XMS) були обхідними шляхами:
    EMS підміняв банками пам’ять у фрейм сторінки; XMS використовував пам’ять вище 1 МБ за допомогою менеджера. Обидва були податком складності заради сумісності.
  6. HIMEM.SYS і EMM386.EXE були поширеними інструментами для доступу та керування пам’яттю поза звичними обмеженнями.
    Якщо ви колись «оптимізували» CONFIG.SYS і AUTOEXEC.BAT — ви виконували планування ємності текстовим редактором і молитвою.
  7. Захищений режим існував, але екосистема ПЗ відставала.
    Можливості апаратури не переписують світ миттєво; встановлена база й матриця сумісності вирішують, що можна випустити.
  8. Ця епоха була наповнена жорсткими обмеженнями, але й швидкими змінами.
    Люди не були дурні; вони будували системи, де кожен кілобайт мав своє завдання. Міф пережив, бо ми неправильно читаємо обмеження як зарозумілість.

Корисний висновок: число «640 КБ» випливало з карти адресного простору і прагматичних інженерних виборів, а не з проголошення, що користувачам ніколи не знадобиться більше.
Це різниця між «це коробка, яку ми можемо намалювати сьогодні» і «ця коробка завжди буде достатньою».

Справжній урок: обмеження — це рішення, а не дрібниця

Мені байдуже, хто що сказав у 1981 році. Мені важливо, що у 2026 команда досі випускає системи з невидимими стелями, а потім дивується, коли їх влучає.
Історія «640 КБ» — це дзеркало: вона показує те, що ми зараз махаємо рукою.

Як виглядає «640 КБ» у сучасному продакшні

  • Дефолтні квоти (тимчасове сховище Kubernetes, розміри блочних томів у хмарі, ліміти об’єктів на неймспейс), які сприймають як політику.
  • Дефолти ядра (somaxconn, nf_conntrack_max, fs.file-max), яких не чіпають бо «Linux знає краще».
  • Обмеження файлових систем (inode, поведінка при масштабуванні каталогів, накладні витрати на малі файли), які ігнорують до моменту «df каже, що місця є».
  • Припущення про кеш («більший кеш завжди швидше»), що перетворюються на тиск на пам’ять, хвилі виведення і стрибки хвостової латентності.
  • Чергування і зворотний тиск, який відсутній, бо хтось хотів «простоти».

Одна цитата заспокоює; інвентар обмежень корисний

Міф живе, бо дає вам лиходія. Лиходії прості. Обмеження — це робота.
Якщо ви експлуатуєте продакшн, ваша робота — знати межі до того, як це зроблять ваші користувачі.

Ось перефразована ідея від відомого голосу надійності, бо вона протилежна міфу про 640 КБ:
парафразована ідея — John Allspaw: надійність походить від навчання і адаптації систем, а не від звинувачень людей у наслідках.

Сприймайте «640 КБ достатньо» як діагностичний підказник: де ми покладаємося на історичний артефакт, налаштування за замовчуванням або напівпам’ятне обмеження?
Потім знайдіть це. Запишіть. Протестуйте. Поставте на нього алерт. Зробіть це нудним.

Три корпоративні міні-історії з краю «буде нормально»

Міні-історія 1: Інцидент через хибне припущення («диску не може не вистачити; у нас є моніторинг»)

Середня SaaS-компанія керувала мультиорендним кластером Postgres з логічною реплікацією в аналітичну систему.
Основна БД мала багато вільного місця, і дашборди показували «використання диску стабільне». Усі спали спокійно.

Однієї ночі записи сповільнилися, потім зупинилися. Рівень помилок у застосунку підскочив. На чергуваннях БД візуально виглядала «здоровою» за звичними перевірками:
CPU нормальний, RAM нормальний, лаг реплікації зростав, але не катастрофічно. Кластер не впав; він просто перестав просуватися вперед, ніби в патоці меду.

Корінь проблеми: том WAL заповнився. Не основний том даних. Монітор «використання диску стабільне» дивився на файлову систему даних.
Він ніколи не дивився на том WAL, бо хтось припустив «він на тому ж диску».

Гірше: процес очищення, який мав видаляти старі сегменти WAL, покладався на replication slots. Заїзджений споживач тримав слоти відкритими.
Тому WAL ріс, поки не досяг межі тому. База даних зробила саме те, що мала робити, коли не може безпечно зберегти: вона перестала приймати роботу.

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

Міні-історія 2: Оптимізація, що відкотилася проти вас («ми використаємо великі кеші; пам’ять дешева»)

Сервіс платіжів мав проблеми з латентністю під піковим трафіком. Команда оптимізувала: більше кешування в процесі, більші пули з’єднань
і агресивні read-through кеші для часто запитуваної метаданих. Латентність покращилася в стенді. Деплой пішов із впевненістю.

У продакшні хвостова латентність покращилася на кілька годин. Потім стало дивно. P99 підскочив, CPU різко зріс, а помилки стали імпульсними.
Сервіс не виглядав перевантаженим — поки ви не перевірили major page faults і активність reclaim. Ядро боролося за життя.

Оптимізація створила тиск на пам’ять і спричинила агресивне звільнення файлового кешу ядром. Це означало більше дискових зчитувань для залежностей.
Також це штовхнуло JVM (так, це був Java) у режим GC, що виглядав як зубчаста «жаль»-діаграма.
Сервіс став «швидким у середньому» і «непередбачуваним у критичні моменти», що є найгіршим видом швидкості.

Вони відкочували розміри кешів, додали явні бюджети пам’яті і перемістили частину відповідальності за кеш до окремого шару, який можна масштабувати незалежно.
Довгострокове рішення включало SLO для кожного endpoint і навантажувальні тести, що моделюють пікову кардинальність і churn кешу — не лише стабільний QPS.

Урок: «пам’ять дешева» — це не інженерний аргумент. Пам’ять — ресурс спільний, що взаємодіє з IO, GC і планувальником.
Кеші не безкоштовні; це позики, які ви віддаєте непередбачуваністю, якщо не бюджетируєте їх.

Міні-історія 3: Нудна але правильна практика, яка врятувала день (запаси ємності + тренування лімітів)

Внутрішня команда платформи підприємства керувала шлюзами об’єктного сховища перед великим бекендом.
Система обслуговувала логи, артефакти та резервні копії — все, про що ніхто не думає, поки це не зникає.

Команда мала нецікаву практику: щоквартально вони проводили «тренування лімітів».
Вони вибирали обмеження — дескриптори файлів, мережеві з’єднання, розмір кешу, пропускну здатність диску, використання inode — і перевіряли алерти, дашборди та руниби.
Вони робили це не тому, що це весело. Вони робили це, бо невідомі обмеження — це місце народження інцидентів.

Якось тиждень, команда застосунків почала завантажувати мільйони дрібних об’єктів через зміну пакувальника.
Бекенд не був повний байтами, але тиск на метадані виріс. Вузли шлюзу почали показувати підвищений IO wait і збільшену латентність.

Платформна команда виявила це рано, бо у них були алерти не лише на «відсоток заповнення диска», а й на використання inode,
глибину черги запитів та латентність по кожному пристрою. Вони обмежили шумний навантажувач, погодили виправлення пакувальника і додали політику мінімального розміру об’єкта.

Ніхто поза платформною командою цього не помітив. Ось як виглядає «врятувати день»: нічого не сталося, і вам ніхто не дякує.
Другий короткий жарт: інженерія надійності — це пишатися інцидентом, який ніколи не потрапить у слайд-дек.

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

Моя упередженість: якщо ви не можете допитати систему командою, ви не розумієте систему.
Нижче практичні завдання, які можна виконати на хості Linux. Кожне містить, що означає вивід і яке рішення з нього випливає.
Це не академічно; це ті перевірки, які ви робите, коли «щось повільно» і треба припинити здогадки.

Завдання 1: Перевірити тиск пам’яті і реальність swap

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:            31Gi        24Gi       1.2Gi       512Mi       5.8Gi       3.9Gi
Swap:          2.0Gi       1.6Gi       400Mi

Значення: «available» — головне; воно відображає відновлюваний кеш. Активне використання swap свідчить про стійкий тиск пам’яті, а не короткочасний сплеск.

Рішення: Якщо swap активно використовується і латентність погана, зменште пам’ятні вимоги (бюджети кешу, heap JVM, кількість воркерів)
або додайте пам’ять. Не сприймайте swap як «додаткову ОЗП»; це страховка латентності з дуже дорогим тарифом.

Завдання 2: Виявити найбільших споживачів пам’яті (і чи це anonymous чи файловий кеш)

cr0x@server:~$ ps -eo pid,comm,rss,vsz --sort=-rss | head
  PID COMMAND           RSS    VSZ
 4121 java           9876540 12582912
 2330 postgres       2456780  3145728
 1902 prometheus     1024000  2048000
 1187 nginx           256000   512000

Значення: RSS показує резидентну пам’ять; VSZ може вводити в оману (зарезервований адресний простір).
Один процес із бурхливим RSS — очевидна мішень.

Рішення: Якщо зростання RSS корелює зі сплесками латентності, застосуйте бюджет пам’яті: обмежте кеші, налаштуйте heap або ізолюйте навантаження.

Завдання 3: Подивитися, чи ядро агресивно звільняє пам’ять

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 1638400 120000  80000 5200000  10   25   120   300 1200 1800 20  8 60 12  0
 4  1 1639000  90000  70000 5100000  80  120   400  1500 1600 2200 18 10 45 27  0
 3  1 1639500  85000  65000 5000000  60   90   350  1200 1500 2100 15  9 50 26  0
 2  0 1640000 110000  70000 5050000  15   30   150   500 1300 1900 19  8 58 15  0
 2  0 1640000 115000  72000 5080000   5   10   100   320 1250 1850 21  7 62 10  0

Значення: Ненульові si/so (swap in/out) і високий wa (IO wait) вказують на те, що тиск на пам’ять переростає в проблеми з IO.

Рішення: Якщо під час піку відбувається свопінг, припиніть «оптимізувати» деінде. Виправте тиск пам’яті спочатку, інакше ви будете женутися за фантомними вузькими місцями.

Завдання 4: Перевірити середнє навантаження проти насичення CPU

cr0x@server:~$ uptime
 14:22:10 up 37 days,  3:11,  2 users,  load average: 18.42, 17.90, 16.77

Значення: Load average включає runnable і uninterruptible завдання (часто IO wait). Високе значення load не завжди означає, що CPU завантажений по максимуму.

Рішення: Порівняйте це з перевірками CPU і IO перед тим, як вирішити «нам потрібно більше ядер».

Завдання 5: Підтвердити, чи CPU справді є вузьким місцем

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server) 	01/21/2026 	_x86_64_	(16 CPU)

12:00:01 AM  CPU   %usr %nice %sys %iowait %irq %soft %steal %idle
12:00:02 AM  all   22.11 0.00  7.90   0.80 0.00  0.60   0.00 68.59
12:00:03 AM  all   24.01 0.00  8.10   9.50 0.00  0.70   0.00 57.69
12:00:04 AM  all   21.20 0.00  7.50  11.40 0.00  0.60   0.00 58.70

Значення: %iowait зростає; CPU не перевантажений. Система чекає на сховище/мережу.

Рішення: Не масштабувати CPU. Досліджуйте латентність IO, конкуренцію файлової системи або поведінку мережевого сховища.

Завдання 6: Швидка перевірка місця на диску (байти) і inode (метадані)

cr0x@server:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  900G  720G  180G  81% /
/dev/nvme1n1p1  200G  198G  2.0G  99% /var/lib/postgresql/wal
cr0x@server:~$ df -i
Filesystem       Inodes   IUsed    IFree IUse% Mounted on
/dev/nvme0n1p2  58982400 1048576 57933824    2% /
/dev/nvme1n1p1  13107200 13090000   17200   100% /var/lib/postgresql/wal

Значення: Файлова система може бути «не повна» по байтах, але повна по inode. Том WAL повний по обох параметрах.

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

Завдання 7: Виміряти латентність сховища і завантаженість у реальному часі

cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0 (server) 	01/21/2026 	_x86_64_	(16 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          20.15    0.00    7.30    9.42    0.00   63.13

Device            r/s     w/s   rkB/s   wkB/s  await  %util
nvme0n1         120.0   200.0  4096.0  8192.0   6.20  78.00
nvme1n1          10.0   900.0   512.0 16384.0  45.30  99.20

Значення: nvme1n1 завантажений (%util ~99) з високим await. Це вузьке місце.

Рішення: Перемістіть write-heavy навантаження (WAL, логи) з цього пристрою, збільшіть можливості пристрою або зменшіть пишуче навантаження.

Завдання 8: Знайти процеси, що зараз роблять IO

cr0x@server:~$ sudo iotop -o -b -n 3
Total DISK READ: 5.12 M/s | Total DISK WRITE: 42.33 M/s
  PID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
 2330 be/4 postgres     0.00 B/s   28.10 M/s  0.00 %  35.20 % postgres: wal writer
 4121 be/4 cr0x       1.20 M/s     4.10 M/s  0.00 %   5.10 % java -jar service.jar
 3011 be/4 root       0.00 B/s     3.20 M/s  0.00 %   2.00 % journald

Значення: WAL writer домінує в записах. Це не «таємний IO»; це ваша база даних, що виконує свою роботу.

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

Завдання 9: Перевірити опції монтування файлової системи, які можуть підставити

cr0x@server:~$ mount | grep -E ' / |wal'
/dev/nvme0n1p2 on / type ext4 (rw,relatime,errors=remount-ro)
/dev/nvme1n1p1 on /var/lib/postgresql/wal type ext4 (rw,relatime,data=ordered)

Значення: Пошукайте несподіванки: sync mounts, noatime/relatime, бар’єри, дивні опції, що змінюють патерни запису.

Рішення: Якщо знайдете sync або несподівану мережеву файлову систему під latency-чутливим шляхом — це, ймовірно, ваш «момент 640 КБ».

Завдання 10: Перевірити ліміти дескрипторів файлів (сучасний «звичний пам’яті» для сокетів)

cr0x@server:~$ ulimit -n
1024
cr0x@server:~$ cat /proc/sys/fs/file-nr
42112	0	9223372036854775807

Значення: Пер-процесний ліміт 1024 — це замало для багатьох сервісів. Системний ліміт дескрипторів у порядку.

Рішення: Якщо бачите помилки «too many open files» або часту зміну з’єднань, підніміть пер-сервісні ліміти через systemd і перевірте після рестарту.

Завдання 11: Перевірити мережевий backlog і обробку SYN (ліміти черг, що виглядають як «випадкова втрата пакетів»)

cr0x@server:~$ sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog
net.core.somaxconn = 128
net.ipv4.tcp_max_syn_backlog = 256

Значення: Ці дефолти можуть бути надто низькі для сервісів з високою конкуренцією, спричиняючи відмови з’єднань під ударами.

Рішення: Якщо бачите марноти SYN або переповнення черги accept у метриках — налаштуйте ці параметри і прогнайте навантажувальні тести. Не «додавайте просто pods» і не сподівайтесь.

Завдання 12: Перевірити використання таблиці conntrack (NAT і відстеження стану: прихована стеля)

cr0x@server:~$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 262144
cr0x@server:~$ cat /proc/sys/net/netfilter/nf_conntrack_count
261900

Значення: Ви майже на максимумі. Коли таблиця заповниться, нові з’єднання будуть відмовлені способом, що нагадує баги у застосунку.

Рішення: Збільшіть таблицю (з урахуванням пам’яті), зменште непотрібний churn з’єднань і встановіть алерти на розумні пороги.

Завдання 13: Перевірити журнали ядра на правду, якої ви не хотіли

cr0x@server:~$ dmesg -T | tail -n 8
[Mon Jan 21 13:58:11 2026] Out of memory: Killed process 4121 (java) total-vm:12582912kB, anon-rss:9876540kB, file-rss:10240kB, shmem-rss:0kB
[Mon Jan 21 13:58:11 2026] oom_reaper: reaped process 4121 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[Mon Jan 21 14:00:02 2026] EXT4-fs warning (device nvme1n1p1): ext4_dx_add_entry: Directory index full, reached max htree level

Значення: OOM kills і попередження файлової системи — не «шум». Це система каже вам, що ваші припущення помилкові.

Рішення: Якщо бачите OOM — припиніть додавати фічи і почніть підбирати пам’ять. Якщо бачите попередження індексу файлової системи — дослідіть макет каталогів і файлів.

Завдання 14: Заміряти вибух каталогів і малих файлів

cr0x@server:~$ sudo find /var/lib/postgresql/wal -type f | wc -l
12983456

Значення: Мільйони файлів означають тиск на inode, проблеми з масштабуванням каталогів і біль у бекапах/сканах.

Рішення: Перепроєктуйте структуру розміщення файлів, агресивно обертайте, або перейдіть на дизайн, що не використовує файлову систему як базу даних.

Завдання 15: Підтвердити, чи додаток обмежений cgroups (дуже 2026-річний «момент 640 КБ»)

cr0x@server:~$ cat /sys/fs/cgroup/memory.max
2147483648
cr0x@server:~$ cat /sys/fs/cgroup/memory.current
2130014208

Значення: Навантаження фактично на межі пам’яті. Ви можете налаштовувати безкінечно; стіна — буквальна.

Рішення: Збільшіть ліміт або зменшіть використання пам’яті. Також: ставте алерти на memory.current при наближенні до memory.max, а не після OOM.

План швидкої діагностики: знайти вузьке місце швидко

Коли все повільно, часу на філософію про 1980-ті немає. Потрібна дисциплінована послідовність, що сходиться.
Цей план припускає, що некоректно поводиться один хост або вузол; адаптуйте для розподілених систем, знімаючи вибірки з кількох вузлів.

Спочатку: підтвердьте режим відмови (симптоми, не теорії)

  • Чи це латентність, пропускна здатність чи помилки?
  • Чи це стабільна деградація чи шипи?
  • Чи корелює з деплоєм, трафіком, cron-джобами, пакетними вікнами?

Запустіть: швидкі перевірки load + CPU + пам’ять + IO. Не гадайте, яка підсистема винна.

По-друге: перевірте чотири звичні вузькі місця в порядку

  1. Тиск пам’яті: free -h, vmstat, cgroup-обмеження, журнали OOM.
    Якщо є свопінг або OOM — вважайте це пріоритетним, поки не спростовано.
  2. Латентність зберігання: iostat -xz, iotop, заповнення файлової системи й inode.
    Високий await або %util близько 100% — явна ознака.
  3. Насичення CPU: mpstat і CPU за процесами.
    Високі %usr/%sys з низьким iowait вказують на CPU.
  4. Мережа і черги: налаштування backlog, conntrack, ретрансляції, падіння пакетів.
    Повна таблиця conntrack може зробити інакше здоровий сервіс привидом.

По-третє: локалізуйте вплив перед тим, як «фіксити»

  • Який процес топ по CPU / RSS / IO?
  • Який том заповнюється?
  • Який пристрій має високу латентність?
  • Який ліміт близький до стелі (fds, conntrack, cgroups, диск, inode)?

По-четверте: виберіть найменш ризиковану міру пом’якшення

  • Обмежте порушника (rate limits, пауза пакетних джобів).
  • Додайте запас (зробіть том більшим, підніміть ліміти), якщо це безпечно і зворотне.
  • Перемістіть гарячі шляхи з контендованих ресурсів (розділити WAL/логи, ізолювати кеші).
  • Відкотіть останні зміни, якщо таймлайн підходить.

По-п’яте: зробіть це неможливим для повторення

  • Додайте алерт на реальну межу, яку ви влучили (не на проксі-метрику).
  • Напишіть рунибу, яка починається з «покажіть мені межу і поточне використання».
  • Заплануйте тренування лімітів. Покладіть їх у календар як патчинг. Бо це — патчинг ваших припущень.

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

Тут міф про 640 КБ відпрацьовує своє. Відмова — не «ми не передбачили майбутнє».
Відмова — «ми не ідентифікували межу і не ставили її як залежність продакшну».

1) Симптом: «Диск на 70% вільний, але записи падають»

Корінь: виснаження inode, обмеження метаданих файлової системи або інший монтувальний шлях (WAL/логи) повний.

Виправлення: перевірте df -i і точки монтування; перемістіть гарячі шляхи на окремі томи; перебудуйте файлові системи з відповідною щільністю inode за потреби.

2) Симптом: «Load average величезний; графіки CPU нормальні»

Корінь: IO wait або блоковані завдання (латентність сховища, NFS-спади).

Виправлення: запустіть iostat -xz і iotop; дослідіть await і %util пристрою; виправте вузьке місце зі зберігання перед збільшенням CPU.

3) Симптом: «Випадкові таймаути під ударами; додавання pods не допомагає»

Корінь: переповнення черги accept, низький somaxconn, виснаження SYN backlog або заповнена таблиця conntrack.

Виправлення: налаштуйте backlog-параметри, збільшіть conntrack max з урахуванням пам’яті і зменшіть churn з’єднань через keep-alive/pooling.

4) Симптом: «Латентність покращилася після кешування, потім стала гіршою ніж раніше»

Корінь: кеші спричинили тиск на пам’ять, що викликало reclaim, swap або GC-тряску.

Виправлення: встановіть бюджети кешу; моніторьте page fault і reclaim; перемістіть кеші в окремий шар; тестуйте з реалістичною кардинальністю і churn.

5) Симптом: «Перезапуски сервісу допомагають на деякий час»

Корінь: витік ресурсів (fds, пам’ять, conntrack), фрагментація або необмежені черги.

Виправлення: відстежуйте зростання з часом; встановіть жорсткі ліміти; додайте виявлення витоків; реалізуйте зворотний тиск; не приймайте «рестарт — це руниба».

6) Симптом: «База даних повільна, але CPU низький»

Корінь: латентність сховища, fsync-контенція, WAL на насиченому пристрої або сплески чекпоінтів.

Виправлення: винесіть WAL на швидке сховище, акуратно налаштуйте параметри чекпоінта, виміряйте латентність fsync і слідкуйте за write amplification.

7) Симптом: «Достатньо RAM вільно; все одно OOM-killed»

Корінь: cgroup-ліміти пам’яті, пер-контейнерні стелі або високий anonymous RSS під жорсткою межею.

Виправлення: перевірте /sys/fs/cgroup/memory.max; підвищіть ліміти; зменшіть пам’ять; переконайтеся, що алерти базуються на використанні cgroup, а не на вільній пам’яті хоста.

Чеклісти / покроковий план

Чекліст 1: Складіть «інвентар лімітів» для будь-якого важливого сервісу

  1. Перелічіть усі точки монтування, які використовує сервіс (дані, логи, WAL, tmp, кеш).
  2. Для кожного тому запишіть розмір, кількість inode, драйвери зростання і механізм очищення.
  3. Запишіть обчислювальні стелі: ліміти CPU, ліміти пам’яті, розмір heap, пули потоків.
  4. Запишіть ОС-ліміти: значення ulimit, systemd-ліміти, розмір conntrack, налаштування backlog.
  5. Запишіть upstream-ліміти: ліміти з’єднань БД, обмеження API, квоти черг.
  6. Для кожної стелі визначте поріг попередження і аварійний поріг.
  7. Створіть один дашборд, що показує «поточне використання vs ліміт» для всього переліку.

Чекліст 2: Планування ємності, що не прикидається пророцтвом

  1. Заміряйте поточний пік (не середнє) для CPU, пам’яті, IO, мережі і зростання сховища.
  2. Визначте перший ресурс, що доходить до 80% під піком; це ваша перша ціль масштабування.
  3. Визначте політику запасу (наприклад: тримати >30% вільного місця на гарячих томах; conntrack <70%).
  4. Моделюйте зростання як діапазони, не як одну лінію. Врахуйте сезонність і пакетні роботи.
  5. Тестуйте режими відмов: симулюйте повний диск, повну таблицю inode, conntrack біля максимуму, низький fd-limit.
  6. Запишіть, що означає «деградовано але прийнятно» і як ви це застосовуватимете (throttling, shedding).

Чекліст 3: Переддеплойні запобіжники (анти-640 КБ рутина)

  1. Перед відправкою «покращення продуктивності» визначте ресурсний бюджет, який воно споживатиме.
  2. Проганіть навантаження з піковою кардинальністю, а не синтетичним рівномірним трафіком.
  3. Переконайтеся, що є алерти на фактичну нову точку тиску (memory.current, iowait, disk await).
  4. Переконайтеся, що відкат можливий і швидкий.
  5. Запустіть канарку достатнього розміру, щоб влучати в реальні кеші і черги.

Питання та відповіді

1) Чи справді Білл Гейтс сказав «640 КБ достатньо для будь-кого»?

Немає надійних первинних джерел. Цитату широко вважають невірно приписаною або принаймні непідтвердженою.
Ставтеся до неї як до фольклору, а не до історії.

2) Якщо цитата сумнівна, навіщо про неї говорити?

Бо вона є зручним проксі для реального режиму відмов: команди плутають архітектурну межу або дефолт із незмінною істинною.
Міф дратує; урок — цінний.

3) Що саме означала межа «640 КБ»?

Звичайна пам’ять в архітектурі IBM PC: використовувана ОЗП нижче верхньої зарезервованої області в першому 1 МБ адресному просторі.
Потреби апаратного відображення (відео, ROM) споживали решту.

4) Чому просто не «використати більше ніж 1 МБ»?

Пізніші системи так зробили, але сумісність була важливою. Раннє ПЗ, припущення DOS реального режиму і екосистема зробили обхідні шляхи (EMS/XMS) практичнішими, ніж ламання всього.

5) Який сучасний еквівалент бар’єра 640 КБ?

Будь-яка прихована стеля: ліміти пам’яті контейнера, таблиці conntrack, ліміти дескрипторів файлів, глибина черг, виснаження inode, крихітні дефолтні томи або насичені пристрої сховища.
«Бар’єр» — це де ваша система влучає в жорсткий ліміт, який ви не моделювали.

6) Хіба це не просто «завжди плануйте ріст»?

Не зовсім. «Планувати ріст» перетворюється на помах рукою. Справжня робота — це: ідентифікувати конкретні ліміти, відстежувати використання проти них і відрепетирувати, що відбувається на 80/90/100%.

7) Чи завжди піднімати ліміти наперед?

Ні. Сліпе підняття лімітів може перенести відмову кудиінде або збільшити зону ураження. Піднімайте ліміти, коли розумієте вартість ресурсу і маєте моніторинг та зворотний тиск.

8) Як не допустити, щоб оптимізації продуктивності обернулися проти нас?

Бюджетуйте їх. Кожна оптимізація споживає щось: пам’ять, IO, CPU, складність або операційний ризик.
Вимагайте «рахунок за ресурси» в рев’ю і тестуйте під реалістичними піками.

9) Що робити, якщо у нас немає часу на повне планування ємності?

Спочатку зробіть інвентар лімітів. Це дешево і відразу корисно. Більшість відмов не з невідомих невідомостей; вони з відомих лімітів, які ніхто не записав.

10) Яку одну метрику ви б додали скрізь завтра?

«Використання vs ліміт» для кожної критичної стелі: байти диска, inode, memory.current vs memory.max, відкриті fds vs ulimit, conntrack_count vs nf_conntrack_max.
Відсотки самі по собі брешуть; потрібна видима стеля.

Наступні кроки, які можна виконати цього тижня

Припиніть сперечатися, чи хтось сказав рядок у 1980-х. Ваша продакшн-система щосили творить власну цитату.
Виправлення — не цинізм; це інструментування і дисципліна.

  1. Запишіть свої топ-10 жорстких лімітів для кожного сервісу (пам’ять, диск, inode, fds, conntrack, глибина черг, з’єднання БД).
  2. Додайте алерти на реальні стелі, а не на проксі. Алертуйте при наближенні до стіни, а не коли вже кровоточите.
  3. Проведіть одне тренування ліміту: виберіть обмеження і перевірте, що ви можете його виявити, пом’якшити і запобігти повторенню.
  4. Бюджетуйте кеші явно. Якщо у кеша немає максимального розміру, це не кеш; це повільний інцидент у часі.
  5. Розділіть гарячі IO шляхи (логи/WAL/tmp), щоб шумний сусід не вбив вашу основну систему збереження.

Міф про 640 КБ не вмирає, бо він запам’ятовується. Зробіть свої ліміти запам’ятовуваними теж — покладіть їх на дашборди і в руниби, де їм місце.

← Попередня
WordPress .htaccess зламав сайт: правильно відновіть безпечний дефолт
Наступна →
Стабільність проти продуктивності вдома: де провести межу

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