Привет, ребята! В этой статье я расскажу о способах оптимизации производительности СУБД PostgreSQL, на базе которой работает Zabbix. Поехали!
Для начала разберемся с процессами Zabbix, которые прямо или косвенно утилизируют БД. В процессе исследования вопроса выяснился один любопытный факт. Оказывается, был такой ZBXNEXT-782, который зарейзил сам Алексей Владышев (напомню, что это автор Zabbix и основатель одноименной компании) аж в 2011 году. В рамках этого реквеста в версии Zabbix 5.4 были наконец-то устранены подключения поллеров к БД. То есть раньше каждый поллер имел собственное подключение к БД для апдейта статуса элементов данных и хостов. Поллеры отвечают за сбор данных. Таким образом, каждый такой поллер, работающий на Zabbix Server занимал одно соединение к БД.
Максимально допустимое число этих поллеров — 1000 штук. Несложно представить к чему это приводило. Выход — использование прокси. В крупных инсталляциях так обычно и поступают.
DBSyncers — процессы Zabbix-сервера, которые используются для записи собранных значений в БД. Их значение по умолчанию 4, но может достигать 100. В Zabbix есть счетчик NVPS (new value per second или новых значений в секунду). Рекомендуется использовать 1 DBSyncer на каждую 1000 NVPS. Если все DBSyncer загружены на 100% или около того, то это обычно вызывает цепную реакцию и влияет на остальные показатели производительности.
Configuration Syncer — это процесс обновления конфигурации Zabbix. По умолчанию запускается каждые 60 секунд, выполняя запросы к БД. Если процесс постоянно занят, в конфигурации необходимо увеличить значение CacheUpdateFrequency (максимум 3600 секунд). Это тоже разгрузит БД.
HousekeepingFrequency — частота удаления устаревших данных. По умолчанию установлено в 1 час, соответственно, максимально период данных, который будет удален, составит 4 часа.
К БД также подключается и веб-бэкэнд. максимальное количество подключений указывается в конфигурации php-fpm (обычно это файл zabbix.conf в /etc/php-fpm.d) в параметре pm.max_children.
В PostgreSQL максимальное количество подключений к БД задается в параметре max_connections. Стоит учитывать все перечисленные выше подключения, а особенно поллеры, если версия вашего Zabbix младше 5.4.
Другие важные параметры конфигурации PostgreSQL:
shared_buffers — буфер данных, который предваряет запись на диск. Обычно задаётся в размере 25% от общего объема ОЗУ на сервере.
effective_cache_size — сколько памяти доступно ОС на сервере. Обычно это 50%.
huge_pages — параметр определяет, будут ли большие страницы запрашиваться из основной области общей памяти. По умолчанию try и его можно таким и оставить. Ядро ОС при этом также должно поддерживать большие страницы.
maintenance_work_mem — задаёт максимальный объём памяти для операций обслуживания БД (vacuum, create index, alter table add foreign key). По умолчанию 64Мб. Можно увеличить.
work_mem — задаёт объём памяти, используемый для внутренних операций сортировки и хеш-таблиц до использования временных файлов на диске. По умолчанию 4Мб.
max_worker_processes — определяет максимальное число фоновых процессов, которое разрешено запускать на сервере.
max_parallel_workers — максимальное число рабочих процессов, которое система сможет поддерживать для параллельных операций. Соотношение max_worker_processes к max_parallel_workers должно равняться числу ядер CPU.
max_parallel_maintenance_workers — максимальное число рабочих процессов, которые могут запускаться одной служебной командой.
max_parallel_workers_per_gather — максимальное число рабочих процессов, которые могут запускаться одним узлом Gather или Gather Merge. Соотношение max_parallel_workers_per_gather к max_parallel_maintenance_workers должно зависеть от количества ядер. Обычно это ½ или ¼.
Перейдем к автоочистке (autovacuum). PostgreSQL использует Multiversion Concurrency Control (MVCC) для обеспечения одновременного доступа к базе данных. Один из побочных эффектов этого метода — операции удаления и обновления, выполняемые в базе данных, оставляют «мертвые» кортежи (строки), отмеченные как удаленные, но фактически не удаляемые с диска. Мертвые кортежи не будут видны транзакциям, но будут занимать дисковое пространство.
В Zabbix есть таблицы, содержащие много данных и получающие множество запросов на удаление / обновление, например, таблицы events, history, history_uint, trends и trends_uint. Эти таблицы особенно раздуваются и для бесперебойной работы БД важна правильная конфигурация автоочистки.
При настройке автоочистки стоит позаботиться о двух вещах:
Частота очистки «мертвых» кортежей может быть определена глобально или для каждой таблицы. Лучше определить его глобально, чтобы избежать дополнительного администрирования.
Есть два параметра, которые определяют, когда начинать очистку таблицы: autovacuum_vacuum_threshold и autovacuum_vacuum_scale_factor. Первый определяет минимальное количество кортежей, которые должны быть «мертвыми» для запуска автоочистки, а второй — процент «мертвых» кортежей в таблице до того, как PostgreSQL начнет автоочистку таблицы. Можно использовать autovacuum_vacuum_threshold = 50 и autovacuum_vacuum_scale_factor = 0.01. Это означает, что PostgreSQL начнет очистку таблицы, если количество мертвых кортежей превышает 1% и не менее 50 мертвых кортежей.
Сколько мертвых кортежей можно очистить за определенный период времени, и влияние очистки в системе контролируется функцией троттлинга автоочистки. Очистка — это фоновая задача, которая не должна влиять на запросы пользователей.
Троттлинг автоочистки контролируется параметрами autovacuum_vacuum_cost_delay и autovacuum_vacuum_cost_limit. Первый определяет время, в течение которого процесс автоочистки будет находиться в спящем режиме при превышении предела стоимости, а второй определяет накопленную стоимость, которая приведет к переходу процесса автоочистки в спящий режим при достижении предела.
Стоимость оценивается с использованием значений следующих параметров:
Значения autovacuum_vacuum_cost_delay = 20ms и autovacuum_vacuum_cost_limit = 3000 означают, что мы сможем обрабатывать 150 000 (1000/20 * 3000) единиц стоимости в секунду. Это переводится в 1171 МБ/с (150000 x 8/1024) при чтении из shared_buffers, 117 МБ/с (150000 x 8/1024/10) при чтении из с диска и 58 МБ/с (150000 x 8/1024/20) записи страниц, затронутых процессом автоочистки.
Кроме того, нужно определить autovacuum_max_workers = 6 и maintenance_work_mem = 64Мб. Это означает использование 384 Мб памяти для заданий автоочистки.
Следующий запрос покажет абсолютное значение и процент «мертвых» кортежей:
SELECT relname,
n_live_tup,
n_dead_tup,
n_dead_tup*100/n_live_tup::float AS dead_percent,
last_vacuum,
last_autovacuum,
autovacuum_count
FROM pg_stat_user_tables
WHERE n_dead_tup <> 0
AND n_live_tup <>0
ORDER BY relname;
Чтобы упростить задачу генерации корректной конфигурации PostgreSQL можно также использовать утилиту PGTune.
Спасибо за внимание. Надеюсь, вам был полезен этот небольшой обзор настроек производительности и вы сможете что-то улучшить в своей инсталляции Zabbix.
А ещё у нас есть:
Описание комплексного решения по мониторингу на открытых системах
Zabbix под замком: включаем опции безопасности компонентов Zabbix для доступа изнутри и снаружи
Добавляем CMDB и географическую карту к Zabbix
Если вам интересен наш подход, оставьте заявку в форме нашей обратной связи — пообщаемся.