Как определить разницу между размером пула и подключением к базе данных в PostgreSQL

14

У нас проблемы с обработкой трафика в часы пик на наш сервер базы данных. Мы пытаемся улучшить аппаратное обеспечение (см. Этот вопрос об этой стороне вещей ), но мы также хотим поработать над настройкой пула и настройкой сервера.

Приложение, над которым мы работаем, представляет собой пошаговую многопользовательскую игру для смартфонов, где бэкэнд состоит из Rails с единорогом и PostgreSQL 9.1 в качестве базы данных. В настоящее время у нас зарегистрировано 600 000 пользователей, и, поскольку состояние игры хранится в базе данных, каждые несколько секунд производится несколько тысяч записей. Мы проанализировали файлы журналов из PostgreSQL, используя PgBadger, и в критические часы мы получаем много

FATAL: remaining connection slots are reserved for non-replication superuser connections

Наивным решением этой проблемы было бы увеличение max_connections (которое в настоящее время равно 100) в postgresql.conf . Я прочитал http://wiki.postgresql.org/wiki/Number_Of_Database_Connections, где указано, что это может быть неправильно. В вышеупомянутой статье говорится о том, чтобы найти точку между max_connections и размером пула .

Что можно сделать, чтобы найти это сладкое место? Есть ли хорошие инструменты для измерения производительности ввода-вывода для различных значений max_connections и размера пула ?

Наша текущая настройка - 4 игровых сервера, каждый из которых имеет 16 рабочих-единорогов и размер пула 5.

Вот нестандартные настройки postgres, которые мы используем:

version                      | PostgreSQL 9.1.5 on x86_64-unknown-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
checkpoint_completion_target | 0.9
checkpoint_segments          | 60
checkpoint_timeout           | 6min
client_encoding              | UTF8
effective_cache_size         | 2GB
lc_collate                   | en_US.UTF-8
lc_ctype                     | en_US.UTF-8
log_destination              | csvlog
log_directory                | pg_log
log_filename                 | postgresql-%Y-%m-%d_%H%M%S.log
log_line_prefix              | %t
log_min_duration_statement   | 200ms
log_rotation_age             | 1d
log_rotation_size            | 10MB
logging_collector            | on
max_connections              | 100
max_stack_depth              | 2MB
server_encoding              | UTF8
shared_buffers               | 1GB
ssl                          | on
TimeZone                     | localtime
wal_buffers                  | 16MB
work_mem                     | 8MB
lorgartzor
источник
Вы тот человек, который спрашивал об этом в списке рассылки за последние несколько недель? Если так, я добавлю обратные ссылки на это обсуждение. Кроме того: Каково оборудование и конфигурация вашего сервера БД ? wiki.postgresql.org/wiki/Slow_Query_Questions . Включите нестандартные настройки: wiki.postgresql.org/wiki/Server_Configuration . Вы читали wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server ? Работаете ли вы в больших транзакциях, где это возможно? Используете ли вы слой кэширования и если да, то что? Вы используете synchronous_commit = offили commit_delay?
Крейг Рингер
Таким образом, у вас есть 20 подключений к серверу PostgreSQL? 5 за игровой сервер? С этими 5 жетонами с каждого игрового сервера, которые делятся между 16 работниками единорога?
Крейг Рингер
О, вы регистрируете медленные запросы? Если да, то каковы ваши горячие точки? Простой INSERTс? Как выглядит ваша схема - она ​​разделена? Каковы explain analyzeнекоторые примеры запросов? Как часто ваши контрольно-пропускные пункты и сколько времени они занимают? (см. параметры регистрации контрольных точек). А если серьезно, какая у вас версия PostgreSQL ? (Обновление: кажется, вы перечислите свое оборудование здесь: dba.stackexchange.com/questions/28061/… )
Крейг Рингер,
В любом случае, особенно для настройки размера пула, единственные реальные ответы - это настроить надежное измерение нагрузки и пропускной способности сервера БД, а затем начать настройку вверх и вниз до тех пор, пока вы не найдете подходящее место.
Крейг Рингер,
@CraigRinger Нет, я не тот человек. Но спасибо за обратные ссылки! Я прочитал Tuning Your PostgreSQL сервер и следовал некоторым из упомянутых советов. Теперь я включил настройки не по умолчанию. Сейчас мы synchronous_commit = off
изучаем возможность

Ответы:

14

Краткий ответ здесь: «Метод проб и ошибок, основанный на показателях мониторинга и производительности».

Есть несколько общих практических правил, которые должны помочь вам найти неопределенную область, с которой вы должны начать, но они очень общие. Часто приводятся общие рекомендации «количество процессоров плюс количество независимых дисков», но это только невероятно грубая отправная точка.

Что вам действительно нужно, так это установить надежные показатели производительности для вашего приложения. Начать запись статистики.

Для этого не так много интегрированных инструментов. Существуют такие вещи, как check_postgresсценарий nagios , ведение журнала счетчика производительности системы Cacti, сборщик статистики PostgreSQL и т. Д., Но не так много, что объединяет все это. К сожалению, вам придется сделать это самостоятельно. Что касается PostgreSQL, см. Мониторинг в руководстве PostgreSQL. Существуют некоторые сторонние варианты, такие как Postgres Enterprise Monitor от EnterpriseDB .

Для метрик уровня приложения, упомянутых здесь, вы захотите записать их в общих структурах данных или во внешнюю недолговечную БД, такую ​​как Redis, и агрегировать их либо во время записи, либо перед записью их в базу данных PostgreSQL. Попытка войти непосредственно в Pg исказит ваши измерения с накладными расходами, созданными записью измерений, и усугубит проблему.

Самым простым вариантом, вероятно, является одиночный файл на каждом сервере приложений, который вы используете для записи статистики приложений. Вы, вероятно, хотите постоянно обновлять min, max, n, total и mean; Таким образом, вам не нужно хранить каждую статистическую точку, только агрегаты. Этот синглтон может записывать свои статистические данные в Pg каждые x минут, что является достаточно низким показателем, чтобы влияние на производительность было минимальным.

Начните с:

  • Какова задержка запроса? Другими словами, сколько времени приложение получает от получения запроса от клиента, пока оно не ответит клиенту. Запишите это в совокупности за период времени, а не как отдельные записи. Группируйте его по типу запроса; скажем, по странице.

  • Какая задержка доступа к базе данных для каждого запроса или типа запроса, выполняемого приложением? Сколько времени требуется от запроса к БД информации / хранения информации, пока это не будет сделано и может перейти к следующей задаче? Опять же, агрегируйте эту статистику в приложении и записывайте только агрегированную информацию в БД.

  • Какова ваша пропускная способность? За какие x минут сколько запросов каждого основного класса, выполняемых вашим приложением, обслуживается БД?

  • За тот же промежуток времени х минут, сколько было запроса клиента?

  • Выборка каждые несколько секунд и агрегирование по тем же x минутным окнам в БД, сколько было подключений к БД? Сколько из них были простаивают? Сколько было активных? Во вставках? Обновления? выбирает? удаления? Сколько транзакций было проведено за этот период? Видеть документацию сборщика статистики

  • Опять же, выборка и агрегация за один и тот же промежуток времени, каковы показатели производительности хост-системы? Сколько читают и сколько пишут дисковые операции ввода-вывода / секунду? Мегабайт в секунду диска читает и пишет? Загрузка процессора? Нагрузка средняя? ОЗУ использовать?

Теперь вы можете начать изучать производительность вашего приложения, сопоставляя данные, составляя их график и т. Д. Вы начнете видеть шаблоны, начнете находить узкие места.

Возможно, вы узнаете, что ваша система имеет узкое место INSERTи работает UPDATEс высокой скоростью транзакций, несмотря на довольно низкий дисковый ввод-вывод в мегабайтах в секунду. Это будет подсказкой о том, что вам нужно улучшить производительность очистки диска с помощью RAID-контроллера кэширования с обратной записью с резервным питанием от батареи или некоторых высококачественных твердотельных накопителей с защитой питания. Вы также можете использовать, synchronous_commit = offесли все нормально, чтобы потерять несколько транзакций при сбое сервера, и / или a commit_delay, чтобы снять часть нагрузки синхронизации.

Когда вы будете отображать количество транзакций в секунду в зависимости от количества одновременных подключений и корректируете изменяющуюся частоту запросов, которую видит приложение, вы сможете лучше понять, в каком месте находится ваша пропускная способность.

Если у вас нет быстро сбрасываемого хранилища (BBU RAID или быстродействующие твердотельные накопители), вам не нужно больше, чем достаточно небольшое количество активно записывающих соединений, возможно, самое большее, в два раза больше дисков, которые у вас есть, возможно, меньше в зависимости от расположения RAID производительность диска и т. д. В этом случае это даже не стоит проб и ошибок; просто обновите свою подсистему хранения до одной с быстрой очисткой диска .

Найдите pg_test_fsyncинструмент, который поможет вам определить, может ли это быть проблемой для вас. Большинство пакетов PostgreSQL устанавливают этот инструмент как часть contrib, поэтому вам не нужно его компилировать. Если вы получаете менее пары тысяч операций в секунду, pg_test_fsyncвам необходимо срочно обновить систему хранения. Мой ноутбук с SSD получает 5000-7000. Моя рабочая станция при работе с 4-дисковым массивом RAID 10 с 7200 об / мин дисками SATA и сквозной записью (без кэширования при записи) получает около 80 операций в секунду f_datasync, а для 20 операций в секунду fsync(); это в сотни раз медленнее . Сравните: ноутбук с рабочей станцией ssd vs с сквозной записью (без кэширования записи) RAID 10, SSD этого ноутбука дешев, и я не обязательно доверяю ему, чтобы очистить кэш записи при отключении питания; Я сохраняю хорошие резервные копии и не буду использовать их для данных, которые меня волнуют. Твердотельные накопители хорошего качества работают так же хорошо, если не лучше, и долговечны при записи.

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

  • Хорошая подсистема хранения с быстрыми сбросами. Я не могу подчеркнуть это достаточно. Высококачественные отказоустойчивые твердотельные накопители и / или RAID-контроллер с защищенным кешем обратной записи.
  • Используя UNLOGGEDтаблицы для данных, вы можете позволить себе потерять. Периодически объединяйте его в зарегистрированные таблицы. Например, ведите игры в незанятых таблицах и записывайте результаты в обычные таблицы длительного пользования.
  • Использование commit_delay(менее полезно с быстрой промывкой хранилища - подсказка)
  • Выключать synchronous_commit для транзакций, которые вы можете позволить себе потерять (менее полезно с быстрой очисткой хранилища - подсказка)
  • Таблицы секционирования, особенно таблицы, в которых данные «стареют» и очищаются. Вместо удаления из многораздельной таблицы удалите раздел.
  • Частичные индексы
  • Сокращение количества создаваемых вами индексов. Каждый индекс имеет стоимость записи.
  • Пакетная работа в большие транзакции
  • Использование реплики горячего резервирования только для чтения для снятия нагрузки чтения с основной БД
  • Использование слоя кэширования, такого как memcached или redis, для данных, которые изменяются реже или могут позволить себе устаревать. Вы можете использовать LISTENи NOTIFYдля аннулирования кэша, используя триггеры для таблиц PostgreSQL.

Если есть сомнения: http://www.postgresql.org/support/professional_support/

Крейг Рингер
источник