Рекомендации по настройке производительности
Закрома.Хранение хранит метаданные объектов в PostgreSQL, поэтому скорость операций с объектами, особенно с мелкими, во многом определяется производительностью базы данных. В статье описаны рекомендации по настройке PostgreSQL, подключений и шардов Закрома.Хранение, а также памяти, дисков и сети операционной системы на сервере БД.
Размещение PostgreSQL
- По возможности выносите PostgreSQL на отдельный сервер. Совмещение с узлами Закрома.Хранение и ZDS приводит к конкуренции за CPU, память (page cache) и диски.
- Для промышленной эксплуатации используйте HA-кластер PostgreSQL (например, роль
postgresql-haиз поставки). - Размещайте PostgreSQL в той же сети (L2-сегменте), что и узлы Закрома.Хранение: каждая операция с объектом выполняет несколько запросов к БД, и сетевая задержка складывается.
Где задаются параметры PostgreSQL
Расположение параметров зависит от способа установки PostgreSQL.
| Способ установки PostgreSQL | Где задаются параметры | Как применить |
|---|---|---|
| Собственный экземпляр PostgreSQL | postgresql.conf или отдельный файл в conf.d/ (в Debian/Ubuntu — /etc/postgresql/<версия>/main/conf.d/), либо ALTER SYSTEM SET ... (записывается в postgresql.auto.conf в каталоге данных) | SELECT pg_reload_conf(); или перезапуск — см. столбец «Перезапуск» в таблицах ниже |
Роль postgresql-ha из поставки (Patroni) | Переменная postgresql_ha_postgresql_parameters в group_vars инвентаря роли (примеры — roles/postgresql-ha/examples/<пример>/group_vars/all.yml). Параметры хранятся в etcd и применяются ко всему кластеру | Повторный прогон роли. postgresql.conf вручную не редактируйте — Patroni перезапишет его |
Пример для роли postgresql-ha (сервер 16 ГБ RAM, SSD):
1postgresql_ha_postgresql_parameters: 2 max_connections: 500 3 shared_buffers: 4GB 4 effective_cache_size: 8GB 5 work_mem: 32MB 6 maintenance_work_mem: 512MB 7 max_wal_size: 4GB 8 min_wal_size: 1GB 9 wal_compression: zstd 10 random_page_cost: 1.1 11 effective_io_concurrency: 200 12 huge_pages: try
Перезапуск при PatroniРоль
postgresql-haне перезапускает PostgreSQL. Параметры, требующие перезапуска (shared_buffers,max_connections,huge_pages,wal_buffers), переводят узлы в состояниеpending_restart. Перезапускайте сначала реплики, затем выполнитеpatronictl switchoverи перезапустите бывшего лидера.
Проверка действующих значений:
1SELECT name, setting, unit, source, sourcefile, pending_restart 2FROM pg_settings 3WHERE name IN ('shared_buffers','effective_cache_size','work_mem','maintenance_work_mem', 4 'max_connections','max_wal_size','wal_compression','huge_pages', 5 'random_page_cost','effective_io_concurrency','synchronous_commit');
Столбец sourcefile показывает, из какого файла взято значение, pending_restart = true — что значение изменено, но ещё не применено.
Параметры PostgreSQL
Память
| Параметр | Рекомендация | Перезапуск | Назначение |
|---|---|---|---|
shared_buffers | 25% RAM сервера БД (не более 32 ГБ) | да | Собственный кэш страниц PostgreSQL. Значение по умолчанию (128 МБ) мало для любой промышленной нагрузки |
effective_cache_size | 50–75% RAM | нет | Оценка суммарного кэша (shared_buffers + page cache ОС) для планировщика. Память не выделяет, влияет только на выбор индексных планов |
work_mem | 32MB | нет | Память на одну операцию сортировки или хеширования в каждом запросе. При большом max_connections суммарное потребление может достигать work_mem × число операций × число соединений, поэтому не завышайте значение |
maintenance_work_mem | 512MB–1GB | нет | Память для VACUUM, CREATE INDEX. Ускоряет обслуживание больших таблиц метаданных |
WAL и контрольные точки
| Параметр | Рекомендация | Перезапуск | Назначение |
|---|---|---|---|
max_wal_size | 4GB и больше (должен вмещать WAL, генерируемый за checkpoint_timeout) | нет | Объём WAL, после которого запускается внеплановая контрольная точка. Малое значение вызывает частые checkpoint и всплески записи |
min_wal_size | 1GB | нет | Объём переиспользуемых сегментов WAL |
checkpoint_timeout | 15min | нет | Интервал плановых контрольных точек |
checkpoint_completion_target | 0.9 (значение по умолчанию с PostgreSQL 14) | нет | Растягивает запись грязных страниц на 90% интервала |
wal_compression | zstd (PostgreSQL 15+) или on | нет | Сжатие полных образов страниц в WAL: меньше объём записи и сетевого трафика репликации ценой небольшой нагрузки на CPU |
Результат тестаНа транзакционной нагрузке настройка WAL и контрольных точек дала +164% TPS — больше, чем любая другая оптимизация после памяти. Каждая первая модификация страницы после контрольной точки записывает в WAL её полный образ (8 КБ), поэтому редкие контрольные точки и сжатие WAL кратно сокращают объём записи. Наибольший эффект — на дисках с ограниченной пропускной способностью.
Проверить, вызываются ли контрольные точки по объёму WAL (а не по таймеру), можно включив log_checkpoints = on или через pg_stat_checkpointer (PostgreSQL 17+) / pg_stat_bgwriter (до 16): большое num_requested / checkpoints_req по сравнению с плановыми означает, что max_wal_size мал.
Не отключайте
fsyncиfull_page_writesОтключение приводит к повреждению базы при сбое питания или ОС.synchronous_commit = offне повреждает базу, но при сбое теряются последние подтверждённые транзакции (до3 × wal_writer_delay), то есть метаданные уже загруженных объектов. На тестовом стендеsynchronous_commit = offдал +67% TPS на транзакционной нагрузке — меньше, чем корректная настройка WAL и контрольных точек (см. Результаты тестирования), которая не жертвует надёжностью. Не используйте этот параметр для базы Закрома.Хранение.
Планировщик для SSD/NVMe
| Параметр | Рекомендация | Перезапуск | Назначение |
|---|---|---|---|
random_page_cost | 1.1 | нет | Стоимость случайного чтения относительно последовательного. Значение по умолчанию (4) рассчитано на HDD и заставляет планировщик чаще выбирать последовательное сканирование |
effective_io_concurrency | 200 | нет | Число параллельных запросов предвыборки для bitmap heap scan |
maintenance_io_concurrency | 200 | нет | То же для операций обслуживания |
Количество подключений
Установите max_connections по инструкции по расчёту с запасом 20–30%. Каждое соединение — отдельный процесс PostgreSQL, потребляющий память, поэтому не задавайте значение «с большим запасом».
Подключения Закрома.Хранение к PostgreSQL
Пулы подключений компонентов настраиваются в inventories/<вариант установки>/group_vars/zakroma-storage.yml архива поставки.
| Переменная | Значение по умолчанию | Описание |
|---|---|---|
zakroma_storage_postgresql_max_open_conns | 10 | Максимальное число открытых подключений к БД. Глобальное значение, наследуется всеми компонентами |
zakroma_storage_postgresql_max_idle_conns | 5 | Максимальное число неактивных подключений, удерживаемых в пуле |
zakroma_storage_workers[].postgresql_max_open_conns | {{ zakroma_storage_postgresql_max_open_conns }} | Переопределение для конкретного worker (шарда) |
zakroma_storage_workers[].postgresql_max_idle_conns | {{ zakroma_storage_postgresql_max_idle_conns }} | То же для неактивных подключений |
Рекомендации для нагрузки с высокой параллельностью:
- Увеличьте у worker
max_open_connsдо 40 иmax_idle_connsдо 40. Точное значение зависит от размера объектов и параллельности клиентской нагрузки. - Выдерживайте соотношение
max_open_conns × <количество узлов Закрома.Хранение> > <concurrency>, гдеconcurrency— число одновременных S3-запросов клиентов ко всему кластеру. Иначе запросы будут ждать свободного соединения в пуле. - Задавайте
max_idle_conns = max_open_conns, чтобы при всплесках нагрузки соединения не закрывались и не открывались заново: установка соединения с PostgreSQL занимает единицы миллисекунд и порождает новый процесс на сервере БД.
Пример — увеличение подключений только для worker, без изменения остальных компонентов:
1zakroma_storage_workers: 2 - postgresql_host: "{{ zakroma_storage_postgresql_host }}" 3 postgresql_port: "{{ zakroma_storage_postgresql_port }}" 4 postgresql_username: "{{ zakroma_storage_postgresql_username }}" 5 postgresql_password: "{{ zakroma_storage_postgresql_password }}" 6 postgresql_dbname: "{{ zakroma_storage_postgresql_dbname }}" 7 postgresql_schema_name: worker0 8 postgresql_sslmode: "{{ zakroma_storage_postgresql_sslmode }}" 9 postgresql_max_open_conns: 40 10 postgresql_max_idle_conns: 40 11 # остальные параметры worker оставьте без изменений
После увеличения пулов пересчитайте max_connections PostgreSQL по формуле: подключения worker умножаются на число шардов и узлов.
Шарды метаданных
Метаданные объектов распределяются между шардами — схемами или базами данных, каждую из которых обслуживает свой worker. Увеличение числа шардов распараллеливает запись и чтение метаданных.
- Используйте от 2 до 10 шардов. Количество шардов определяется совместно с технической поддержкой по требованиям к RPS и планируемому количеству объектов.
- При большой параллельности клиентов увеличение числа шардов может давать кратный рост RPS записи и чтения мелких объектов (4–256 КБ) — при условии, что дисковая подсистема ZDS не является узким местом.
- Шард добавляется новым элементом списка
zakroma_storage_workersсо своей схемой (worker1,worker2, …) или базой данных. Порядок добавления без остановки обслуживания описан в статье Масштабирование объёма хранения. - По возможности размещайте шарды в разных базах данных и на разных дисках с помощью отдельных
TABLESPACE— так шарды не конкурируют за IOPS одного тома.
Пример создания шарда на отдельном диске (/pgdata2 смонтирован на отдельный том):
1-- от суперпользователя 2CREATE TABLESPACE ts_worker1 OWNER zakroma_user LOCATION '/pgdata2/ts_worker1'; 3CREATE DATABASE zakroma_worker1 WITH OWNER zakroma_user TABLESPACE ts_worker1; 4\c zakroma_worker1 5CREATE SCHEMA worker1 AUTHORIZATION zakroma_user;
Каталог LOCATION должен существовать, быть пустым и принадлежать пользователю postgres. Для кластера Patroni каталог tablespace должен быть создан на всех узлах.
Операционная система: память и page cache
Параметры ядра задавайте в отдельном файле, например /etc/sysctl.d/90-postgresql.conf, и применяйте командой sudo sysctl --system.
Huge pages
При больших shared_buffers таблицы страниц каждого процесса PostgreSQL занимают значительный объём памяти, а промахи TLB увеличивают нагрузку на CPU. Huge pages (2 МБ вместо 4 КБ) снимают обе проблемы.
-
Узнайте требуемое количество страниц (PostgreSQL 15+, значение рассчитывается по текущим
shared_buffers):1SHOW shared_memory_size_in_huge_pages; -
Зарезервируйте страницы с небольшим запасом в
/etc/sysctl.d/90-postgresql.conf:1vm.nr_hugepages = <значение из п.1 + 2–3%> -
Задайте
huge_pages = on(PostgreSQL не запустится, если страниц не хватает) илиtry(молча использует обычные страницы) и перезапустите PostgreSQL. -
Проверьте использование: в
/proc/meminfoзначениеHugePages_Rsvdили разницаHugePages_Total − HugePages_Freeдолжна соответствоватьshared_buffers.
Зарезервированные huge pages недоступны остальным процессам, поэтому пересчитывайте vm.nr_hugepages при каждом изменении shared_buffers.
Резервируйте huge pages при загрузкеЯдро выделяет huge pages только из непрерывных блоков памяти по 2 МБ. На работающем сервере память фрагментирована page cache, и
sysctl -w vm.nr_hugepages=Nможет выделить меньше страниц, чем запрошено, без сообщения об ошибке. На тестовом стенде из 547 запрошенных страниц было выделено 467, и PostgreSQL сhuge_pages = onне запустился с ошибкойcould not map anonymous shared memory.
- Задавайте
vm.nr_hugepagesв/etc/sysctl.d/— параметр применится при загрузке, пока память не фрагментирована.- После изменения без перезагрузки проверяйте фактическое значение
HugePages_Totalв/proc/meminfo. При нехватке освободите page cache и уплотните память:sync; echo 3 > /proc/sys/vm/drop_caches; echo 1 > /proc/sys/vm/compact_memory— и повторите установку.- Значение
huge_pages = tryне остановит запуск PostgreSQL при нехватке страниц, но PostgreSQL молча будет работать без них — проверяйтеHugePages_Rsvdпосле перезапуска.
Результат тестаHuge pages при
shared_buffers = 1GB: +8,6% TPS на нагрузке метаданных из памяти, на прочих нагрузках — в пределах погрешности. Эффект растёт с размеромshared_buffersи числом соединений.
Transparent Huge Pages
Отключите Transparent Huge Pages (THP) в режиме always: дефрагментация памяти ядром вызывает непредсказуемые задержки. Режим madvise (значение по умолчанию в Ubuntu 24.04) безопасен — PostgreSQL не запрашивает THP.
1cat /sys/kernel/mm/transparent_hugepage/enabled # [madvise] или [never] — допустимо
Для постоянного отключения добавьте transparent_hugepage=never в параметры ядра (GRUB_CMDLINE_LINUX) или используйте профиль tuned.
Сброс грязных страниц
По умолчанию ядро начинает фоновую запись при vm.dirty_background_ratio = 10% и блокирует процессы при vm.dirty_ratio = 20% от доступной памяти. На сервере с 128 ГБ RAM это 12 и 25 ГБ несброшенных данных: во время контрольной точки или fsync они записываются одним всплеском, и задержки запросов резко растут. Задайте пороги в абсолютных значениях, соизмеримых с производительностью дисков:
1# /etc/sysctl.d/90-postgresql.conf 2vm.dirty_background_bytes = 67108864 # 64 МБ 3vm.dirty_bytes = 268435456 # 256 МБ (для быстрых NVMe — до 1 ГБ)
Параметры *_bytes и *_ratio взаимоисключающие: установка одного обнуляет другой.
Результат тестаНа стенде с 4 ГБ RAM изменение порогов не дало устойчивого эффекта: 0…+0,5% на транзакционной нагрузке и от −1,8% до +6,2% на нагрузке метаданных в двух сериях — в пределах погрешности. При малом объёме памяти пороги по умолчанию (400/800 МБ) и так невелики. Параметр важен на серверах с большим объёмом RAM, где он сглаживает всплески задержек во время контрольных точек.
Swap и overcommit
1# /etc/sysctl.d/90-postgresql.conf 2vm.swappiness = 1 3vm.overcommit_memory = 2 4vm.overcommit_ratio = 80 # подберите так, чтобы CommitLimit ≈ RAM − резерв ОС
vm.swappiness = 1— ядро вытесняет в swap только при реальной нехватке памяти, а не вместо освобождения page cache. Полностью отключать swap не рекомендуется: при нехватке памяти вместо замедления сработает OOM killer.vm.overcommit_memory = 2запрещает выделять больше памяти, чемCommitLimit(swap + (RAM − huge pages) × overcommit_ratio / 100, см./proc/meminfo). Процесс PostgreSQL получит ошибку выделения памяти вместо того, чтобы OOM killer завершил процесс и PostgreSQL перезапустил весь экземпляр. Зарезервированные huge pages вычитаются из RAM при расчётеCommitLimit, поэтому после их включения проверьтеCommitLimitи при необходимости увеличьтеovercommit_ratio.
Эти параметры влияют на стабильность под нагрузкой, а не на пиковую производительность, поэтому в A/B-тестах не измерялись.
NUMA
На многопроцессорных серверах отключите vm.zone_reclaim_mode (значение 0 по умолчанию в современных ядрах): при значении 1 ядро предпочитает освобождать page cache локального узла NUMA вместо использования памяти соседнего, и эффективный размер кэша падает.
1sysctl vm.zone_reclaim_mode # должно быть 0 2numactl --hardware # количество узлов NUMA
Диски
Размещение данных и WAL
- Используйте SSD/NVMe. Метаданные — это случайный ввод-вывод мелкими блоками (8 КБ), и задержка диска напрямую определяет задержку операций S3.
- Вынесите WAL (
pg_wal) на отдельный том. Запись WAL — последовательная сfsyncна каждую фиксацию транзакции; на общем томе она конкурирует со случайным чтением и записью данных. - Шарды метаданных размещайте на разных томах через
TABLESPACE(см. Шарды метаданных). - Оцените задержку
fsyncтома с WAL утилитойpg_test_fsyncиз состава PostgreSQL: число операций в секунду для методаfdatasync— верхняя граница числа фиксаций одного соединения в секунду.
1/usr/lib/postgresql/16/bin/pg_test_fsync -f /var/lib/postgresql/16/main/pg_wal/fsync.test
Файловая система и опции монтирования
Используйте XFS или ext4. Монтируйте тома с данными с опцией noatime, чтобы чтение файлов не порождало запись времени доступа:
1# /etc/fstab 2UUID=<uuid> /var/lib/postgresql xfs defaults,noatime 0 0
1sudo mount -o remount,noatime /var/lib/postgresql # применить без перезагрузки 2findmnt -no OPTIONS /var/lib/postgresql # проверить
Результат теста
noatimeвместоrelatime— без устойчивого эффекта: +1…+2% на транзакционной нагрузке, от −7% до 0% на нагрузке метаданных в двух сериях (в пределах погрешности этой нагрузки).relatimeуже обновляет время доступа не чаще раза в сутки. Опцию можно применять как стандартную, но прироста от неё ждать не стоит.
Планировщик ввода-вывода и read-ahead
- Для NVMe и SSD (а также виртуальных дисков, за которыми стоит СХД) используйте планировщик
noneилиmq-deadline;bfqдаёт заметные накладные расходы на CPU. read_ahead_kbвлияет на последовательное чтение (VACUUM, последовательное сканирование, резервное копирование,pg_basebackup). На случайное чтение по индексам read-ahead практически не влияет.
Проверка и постоянная настройка через udev:
1cat /sys/block/<диск>/queue/scheduler /sys/block/<диск>/queue/read_ahead_kb
1# /etc/udev/rules.d/60-postgresql-io.rules 2# NVMe и SSD 3ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]*|sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none", ATTR{queue/read_ahead_kb}="128" 4# виртуальные диски virtio 5ACTION=="add|change", KERNEL=="vd[a-z]", ATTR{queue/scheduler}="none", ATTR{queue/read_ahead_kb}="128"
Виртуальные диски часто сообщают rotational = 1 (cat /sys/block/<диск>/queue/rotational), даже если за ними SSD-хранилище, поэтому условие по rotational к ним не применяется.
1sudo udevadm control --reload && sudo udevadm trigger --subsystem-match=block
Результат тестаНа виртуальном диске
mq-deadlineвместоnoneдал от −3,4% до +0,8% (в среднем −1,5%), аread_ahead_kb = 4096вместо 128 — −2% на случайном чтении во всех четырёх парах прогонов. Для виртуальных и NVMe-дисков оставляйтеnoneиread_ahead_kbпо умолчанию; увеличенный read-ahead имеет смысл только для томов, где преобладает последовательное чтение.
Проверка дисковой подсистемы
Перед вводом в эксплуатацию измерьте фактическую производительность тома утилитой fio, имитируя профиль PostgreSQL:
1# случайное чтение/запись страницами 8 КБ (файлы данных) 2fio --name=data --filename=/pgdata/fio.test --size=4G --direct=1 --ioengine=libaio \ 3 --rw=randrw --rwmixread=70 --bs=8k --iodepth=32 --runtime=60 --time_based --group_reporting 4# последовательная запись с fdatasync (WAL) 5fio --name=wal --filename=/pgwal/fio.test --size=1G --direct=1 --ioengine=libaio \ 6 --rw=write --bs=8k --iodepth=1 --fdatasync=1 --runtime=60 --time_based
Во время нагрузки контролируйте утилизацию и задержку дисков командой iostat -x 1 (столбцы r_await, w_await, %util). Удалите тестовые файлы после проверки.
Сеть
Каждая операция S3 выполняет несколько коротких запросов к PostgreSQL, поэтому для метаданных важнее задержка сети, чем её пропускная способность. Пропускная способность важна для репликации, резервного копирования (pg_basebackup) и трафика ZDS.
Очереди подключений и буферы TCP
1# /etc/sysctl.d/90-postgresql.conf 2# очередь входящих подключений: всплески подключений пулов worker после рестарта 3net.core.somaxconn = 4096 4net.ipv4.tcp_max_syn_backlog = 8192 5# буферы сокетов: репликация и резервное копирование по сети с RTT > 1 мс 6net.core.rmem_max = 16777216 7net.core.wmem_max = 16777216 8net.ipv4.tcp_rmem = 4096 131072 16777216 9net.ipv4.tcp_wmem = 4096 16384 16777216
somaxconnиtcp_max_syn_backlogзащищают от отказов в подключении при одновременном старте всех пулов Закрома.Хранение. Переполнение очереди видно в счётчикеListenOverflowsкомандыnstat -az TcpExtListenOverflows.- Увеличение буферов TCP имеет смысл, если произведение пропускной способности на задержку (BDP) превышает размер буфера по умолчанию — например, при репликации между площадками. В пределах одного ЦОД с RTT < 0,5 мс эффекта, как правило, нет.
Результат тестаВ одной подсети (RTT ~0,4 мс) увеличение буферов TCP до 16 МБ в двух сериях не изменило ни пропускную способность
iperf3(±1,5%), ни TPS запросов по сети (±3%). Буферы по умолчанию уже покрывают BDP такой сети.
Обнаружение разорванных соединений
Соединения пулов Закрома.Хранение долгоживущие. Если между узлами есть межсетевой экран, NAT или балансировщик с тайм-аутом неактивных сессий, «зависшее» соединение обнаружится только при следующем запросе — по тайм-ауту TCP, через несколько минут. Включите keepalive на стороне PostgreSQL с интервалом меньше тайм-аута сетевого оборудования:
| Параметр | Рекомендация | Перезапуск |
|---|---|---|
tcp_keepalives_idle | 60 | нет |
tcp_keepalives_interval | 10 | нет |
tcp_keepalives_count | 6 | нет |
tcp_user_timeout | 60000 (мс) | нет |
Прерывания и очереди сетевой карты
- Убедитесь, что включён
irqbalanceили прерывания сетевой карты распределены по ядрам вручную:grep <интерфейс> /proc/interrupts. - Используйте все аппаратные очереди карты (
ethtool -l <интерфейс>,ethtool -L <интерфейс> combined <N>) и максимальный размер кольцевых буферов при потерях пакетов (ethtool -g/-G, счётчикиethtool -S <интерфейс> | grep -i drop). - Перегрузку CPU обработкой сети видно по столбцу
%softв выводеmpstat -P ALL 1.
Jumbo frames
Jumbo frames (MTU больше 1500, обычно 9000) уменьшают число пакетов и прерываний на единицу переданных данных. Эффект проявляется на потоковом трафике — репликация, pg_basebackup, выгрузки, передача частей объектов ZDS. На коротких запросах метаданных, которые укладываются в один пакет, выигрыша нет.
MTU должен совпадать на всём путиJumbo frames должны быть включены на всех узлах сегмента, на коммутаторах, в VLAN, bond-интерфейсах и overlay-сетях. Если какой-то участок пропускает меньший размер кадра, крупные пакеты молча отбрасываются (PMTU blackhole): подключение устанавливается, короткие запросы работают, а крупные ответы и передача данных «зависают». Такую проблему сложно диагностировать — включайте jumbo frames только после проверки пути.
Порядок включения:
-
Узнайте максимальный MTU сети у сетевых инженеров или провайдера облака. В облачных сетях он часто меньше 9000.
-
Задайте MTU на интерфейсе в конфигурации сети (пример для netplan):
1network: 2 version: 2 3 ethernets: 4 eth0: 5 mtu: 9000 -
Проверьте путь между каждой парой узлов (PostgreSQL ↔ Закрома.Хранение, PostgreSQL ↔ реплики) пакетами с запретом фрагментации. Размер данных = MTU − 28 байт (заголовки IP и ICMP):
1ping -c 3 -M do -s 8972 <адрес узла> # для MTU 9000Пакеты должны доходить без ошибок и потерь. Сообщение
message too longозначает, что MTU локального интерфейса меньше; 100% потерь — что пакет теряется по пути.
Не полагайтесь на
tracepathОпределяйте реальный пределping -M do, последовательно уменьшая размер пакета. При этом TCP-соединения могут работать и при MTU 9000 — то есть при неверном MTU приложения могут выглядеть исправными, а теряться будет только часть трафика.
Если jumbo frames поддерживаются только внутри сегмента, а путь в другие сети (шлюз по умолчанию) — нет, ограничьте MTU маршрута по умолчанию:
1ip route change default via <шлюз> dev eth0 mtu 1500
Результат тестаMTU 8900 вместо 1500 между узлом PostgreSQL и клиентом (две серии, во второй узлы поменялись ролями клиента и сервера):
- потоковая передача (
iperf3) — с 4,7–5,6 до 13–14,5 Гбит/с (+133…209%);- короткие запросы метаданных — без изменений (−1…+5%, в пределах погрешности);
- выгрузка таблицы 640 МБ через
\copy— без устойчивого эффекта (−18…+15% в разных сериях): скорость ~200 МБ/с ограничена CPU сервера БД, а не сетью.Одновременно число повторных передач TCP при 4 параллельных потоках выросло примерно с 300–1200 до 14 000–16 000 за 15 секунд: сеть облака теряла часть крупных кадров под нагрузкой. Пропускная способность при этом выросла, но при включении jumbo frames контролируйте счётчик
nstat -az TcpRetransSegs.Вывод: включайте jumbo frames для сегментов с потоковым трафиком — репликация, резервное копирование, ZDS. Для подключений Закрома.Хранение к PostgreSQL заметного выигрыша нет.
Чек-лист
PostgreSQL:
- PostgreSQL размещён на отдельном сервере в одной сети с узлами Закрома.Хранение.
-
shared_buffers≈ 25% RAM,effective_cache_size50–75% RAM,work_mem32MB,maintenance_work_mem512MB–1GB. -
max_wal_size≥ 4GB,wal_compressionвключён, контрольные точки запускаются по таймеру, а не по объёму WAL. - Для SSD:
random_page_cost = 1.1,effective_io_concurrency = 200. -
max_connectionsрассчитан по формуле с запасом 20–30%. - Включены
tcp_keepalives_*, если между узлами есть межсетевой экран или NAT.
Закрома.Хранение:
- Пулы worker:
max_open_conns × узлы > concurrency клиентов,max_idle_conns = max_open_conns. - Количество шардов согласовано с технической поддержкой; шарды по возможности размещены на разных томах.
ОС узла PostgreSQL:
- Huge pages зарезервированы под
shared_buffers, THP не в режимеalways. -
vm.dirty_background_bytes/vm.dirty_bytesзаданы в абсолютных значениях. -
vm.swappiness = 1,vm.overcommit_memory = 2с провереннымCommitLimit. - Данные на SSD/NVMe, WAL на отдельном томе,
noatime, планировщикnone/mq-deadline. - Jumbo frames включены только после проверки
ping -M doмежду всеми узлами. - Настройки сохранены в
sysctl.d, udev-правилах,fstabи конфигурации сети и переживают перезагрузку.