Как устроить хайлоад на ровном месте
Что такое хайлоад
Что такое хайлоад на самом деле?
Производительные и масштабируемые системы высокой доступности.
Highload — чисто русское слово. Остальные используют high-volume.
Хайлоад — это ситуация в системе, грозящая отказом в обслуживании из-за недостатка ресурсов. Внештатная ситуация.
В идеале хайлоада не должно быть, но есть человеческие ошибки, которые ведут к недостатку ресурсов (железа, людей, денег), а он приводит к угрозе отказа в обслуживании.
Спешная починка костылями.
Костыль — решение задачи без серьёзного редизайна системы. Документированный костыль — полноценная фича системы.
Про что доклад:
- действия, которые создают хайлоад на ровном месте
- известные, но важные ошибки
- в частности про PostgreSQL
Ошибки проектирования
- Неэффективное использование ресурсов, блокирование спящим процессом. Процесс ждёт, пока клиент заберёт свой запрос.
- База наружу — внешний трафик внутри сети.
- Разные сервисы на одной машине дерутся за ресурсы.
- Останов мастера при исчезновении единственной синхронной реплики. Используйте одну синхронную и одну асинхронную реплику.
- Неправильное или недостаточное тестирование
- Пиковые нагрузки — по времени, по событиям, таймзонам.
- Разумный отлуп роботов
Ошибки проектирования БД
- Пагинация. На страницу N+1 попадают 3% посетителей, и это скорее всего роботы. Не надо заранее выгружать вторую страницу с LIMIT/OFFSET. А если пользователь все-таки перешел на вторую, то далее выгружайте больше страниц сразу в кэш.
- Узкие таблицы — оверхед постгресовых заголовков. Заголовок в постгресе всё равно займет не меньше чем 32 байта, даже если колонки — два bool.
Пример: id-координата, 60 терабайт. Объединили 200 точек в 1 JSON, получилось 10 терабайт. * Широкие таблицы — тоже плохо. * NoSQL когда не надо. На больших данных джойны в клиенте приводят к аду. * JSON/XML когда не надо. * «Ненужная» точность вычислений * Виртуализация и докер
Graceful degradation
- Мало кто думает
- ПОС по нагрузке
- Лучше обслужить кого-то, чем попытаться обслужить всех и упасть.
- Поисковые системы лучше всего ищут в ночь с субботы на воскресенье. Когда нагрузки больше, они ограничивают задачу, чуть ухудшают качество, но зато не деградируют.
Нелепости
- Забытая клавиатура на стойке блокирует отвод тепла, процы понижают частоту.
- Скомпилировали с дебагом (
--enable-cassert
). - Не материализация настроек — настроили, но не сохранили нигде
- Логирование (prepared statements & syslog).
- foreign keys / triggers
- бесконечные with recursive
- зависшие транзакции — вакуум встаёт намертво
- freeze и вообще автовакуум
- неумеренное использование временных таблиц (bloat системного каталога)
- ненужные и бесполезные индексы
- много памяти без huge pages
- ненужное шифрование
- множественные savepoint (SubtransControlLock)
- планируемые дедлоки
- отключение генетического оптимизатора (geqo)
Сложность оптимизации — факториал от количества таблиц индексов. Генетический оптимизатор избавляет от этой зависимости.
В PostgreSQL есть таймауты! Используйте их!
authentification_timeout
wal_sender_timeout
statement_timeout
lock_timeout
idle_in_transaction_session_timeout
deadlock_timeout
- TCP keepalive (оба два!)
И еще много других!
Камни, под которые редко заглядывают:
Max_files_per_process
bgwriter_*
Effective_io_concurrency
Effective_cache_size
- Параллелизм помогает только когда есть свободные ядра.
Wal_level
Random_page_cost
*_collapse_limit
если скорость работы зависит от порядка джойнов — упёрлись в этот лимит.default_transaction_read_only
max_connection
(и на реплике!)- временные файлы постгреса — следить, чтобы постгрес создавал их меньше
- отстающие реплики (гроханье таблиц по одной для освобождения диска)
Срочные костыли (не делайте так)
- fsync = off (data_loss = on)
- synchronous commit = on (лог и миримся с потерями)
- unlogged table (кстати, и hash index тоже (до PG10))
Хайлоада не избежать!
- Всегда нужен план Б:
- жертвуем доступностью, чтобы избежать эффекта домино
- сохраняем целостность данных
- Обязательны полевые учения.