Skip to content

Latest commit

 

History

History
157 lines (114 loc) · 8.95 KB

03_db01.md

File metadata and controls

157 lines (114 loc) · 8.95 KB

Тестирование postgresql - HA-кластер web с http-балансировкой

Тесты были направлены на VIP-адрес http-балансировщиков, соответственно, трафик распределялся на два уже оптимизированных web-сервера. Pgbouncer отключён.

yandex.tank > haproxy > 2 x web > haproxy > postgresql

Web-сервера

  • оборудование - 2 ядра ЦП и 6 ГБ ОЗУ

  • php-fpm - для максимальной производительности установлены параметры:
    pm = static
    pm.max_children = 800
    rlimit_files = 8192
    в файле /etc/systemd/system/php-fpm.service.d/override.conf сделаны соответствующие настройки:

    [Service]
    LimitNOFILE=8192

Сервера БД - оптимизация и тесты

В результате множества тестов я пришёл к следующим настройкам:

  • аппаратная конфигурация:

    4 ядра ЦП и 8 ГБ ОЗУ

  • конфигурация postgresql:

    # DB Version: 11
    # OS Type: linux
    # DB Type: oltp
    # Total Memory (RAM): 8 GB
    # CPUs num: 4
    # Connections num: 200
    # Data Storage: hdd
    
    max_connections = 200
    shared_buffers = 2GB
    effective_cache_size = 6GB
    maintenance_work_mem = 512MB
    checkpoint_completion_target = 0.9
    wal_buffers = 16MB
    default_statistics_target = 100
    random_page_cost = 4
    effective_io_concurrency = 2
    work_mem = 5242kB
    min_wal_size = 2GB
    max_wal_size = 4GB
    max_worker_processes = 4
    max_parallel_workers_per_gather = 2
    max_parallel_workers = 4
    synchronous_commit = off
    wal_compression = on

    synchronous_commit = off - выключены синхронные коммиты и теперь мастер кластера БД не будет ждать, пока записи из WAL сохранятся на диске мастера и на дисках обоих реплик, прежде чем сообщить клиенту об успешном завершении операции

    wal_compression = on - включено сжатие образа полной страницы, записываемого в WAL

  • каталог pg_stat_tmp с данными статистики вынесен в ОЗУ на каждой ноде кластера БД

    systemctl stop patroni && \
    sleep 5 && \
    echo "tmpfs /var/lib/pgsql/11/data/pg_stat_tmp tmpfs noatime,nodiratime,defaults,size=128M,mode=700,uid=$(id -u postgres),gid=$(id -g postgres)" >> /etc/fstab && \
    mount -v /var/lib/pgsql/11/data/pg_stat_tmp && \
    systemctl start patroni

    Но необходимо иметь в виду, что теперь переинициализация любой проблемной ноды будет выглядеть, примерно, так:

    systemctl stop patroni && \
    umount /var/lib/pgsql/11/data/pg_stat_tmp && \
    systemctl start patroni && \
    patronictl -c /etc/patroni.yml reinit otus имя_проблемной_ноды --force && \
    #тут нужно дождаться, пока закончится переинициализация проблемной_ноды
    systemctl stop  patroni && \
    mount -v /var/lib/pgsql/11/data/pg_stat_tmp/ && \
    systemctl start patroni

После выполнения вышеуказанных настроек удалось добиться 125 запросов в секунду (rps) без появления ошибок при заметном снижении инстансов yandex.tank.

ТЕСТ https://overload.yandex.net/224076

  • включены huge_pages

    Необходимое количество huge_pages вычислялось и применялось таким образом:

    #!/bin/bash
    PGDATA=/var/lib/pgsql/11/data/
    pid=`head -1 $PGDATA/postmaster.pid`
    echo -e "pid:\t\t\t$pid"
    peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'`
    echo -e "VmPeak:\t\t\t$peak kB"
    hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'`
    echo -e "Hugepagesize:\t\t$hps kB"
    hp=$((peak/hps+1))
    echo -e "set Huge Pages:\t\t$hp"
    echo "vm.nr_hugepages = $hp" >> /etc/sysctl.d/30-postgresql.conf
    sysctl -p --system

ТЕСТ https://overload.yandex.net/224079

  • добавление noatime в опции монтирования корневого раздела (xfs) (для ext4 обычно добавляют barrier=0,noatime)

    Первый тест после перезагрузки ОС (62 инстанса yandex.tank)

ТЕСТ https://overload.yandex.net/224081

Второй тест с накопленной статистикой из первого теста (37 инстансов yandex.tank)

ТЕСТ https://overload.yandex.net/224082

  • отключены Transparent Huge Pages и выполнена настройка параметров ядра ОС linux (sysctl)

    echo never > /sys/kernel/mm/transparent_hugepage/defrag;
    echo never > /sys/kernel/mm/transparent_hugepage/enabled;
    echo "vm.hugetlb_shm_group = $(id -g postgres)" >> /etc/sysctl.d/30-postgresql.conf;
    echo "kernel.sched_migration_cost_ns = 5000000" >> /etc/sysctl.d/30-postgresql.conf;
    sysctl -p --system;
    systemctl restart patroni

    После настройки параметров ядра было выполнено три теста:

ТЕСТ https://overload.yandex.net/224113
ТЕСТ https://overload.yandex.net/224114
ТЕСТ https://overload.yandex.net/224115

соответствующий комплексный экран

03_db01.png

В момент снятия скриншота mamonsu ещё не успел перечитать значение "max connections" и оно всё ещё равно 400, хотя при проведении всех тестов фактически было 200.

Вывод

В результате различных оптимизационных мероприятий удалось добиться значительного повышения производительности кластера СУБД без увеличения времени между ключевыми точками.

Тем не менее, на графике "hl-pgMASTER: PostgreSQL locks sampling" видно, что основное количество блокировок БД приходится на RO-запросы. Но к сожалению, со стороны приложения (Zabbix) нет возможности каким-либо образом настроить отправку read-only запросов на другой сервер БД. https://support.zabbix.com/browse/ZBXNEXT-1603
Pgbouncer так же не умеет автоматически разделять входящие RW- и RO-запросы на разные ноды. Соответственно, далее нужно проработать вариант перенаправления RO-запросов на реплики с помощью, например, pgpool-II.

Дополнение к выводу

Для разделения RW- и RO-запросов на разные ноды кластера мною было изучено и протестировано следующее ПО:

Pgpool-II - Кроме прочего, позволяет балансировать RW- и RO-запросы на разные ноды и задействовать кеш запросов в ОЗУ. Но всё это работает только в том случае, если управление кластером БД настроено с помощью самого pgpool-II. При попытках настроить балансировку и/или кеш без управления кластером все форки pgpool-II начинают стабильно падать с ошибками сегментации.

SQL Rrelay - Полноценный sql-прокси с анализом и модификацией sql-запросов. Если клиентское ПО умеет работать с postgresql, то требуется подключение собственной встраиваемой библиотеки через LD_PRELOAD. В итоге, psql отлично работает с этой библиотекой, а php-fpm и zabbix-server не могут с ней работать.