Як визначити солодке місце між розміром пулу та підключеннями до бази даних у 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

Ви людина, яка запитувала про це у списку розсилки протягом останніх кількох тижнів? Якщо так, я додаю зворотні посилання до цього обговорення. Також: Яке обладнання та налаштування вашого сервера БД ? wiki.postgresql.org/wiki/Slow_Query_Questions . Включіть параметри, що не використовуються за замовчуванням: wiki.postgresql.org/wiki/Server_Configuration . Ви читали wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server ? Чи пропонуєте ви обробляти більші транзакції, де це можливо? Ви використовуєте шар кешування, і якщо так, то що? Ви використовуєте synchronous_commit = offабо a commit_delay?
Крейг Рінгер

Отже, у вас є 20 підключень до сервера PostgreSQL? 5 на ігровий сервер? З цими 5 коннами з кожного ігрового сервера діляться 16 робітників-єдинорогів?
Крейг Рінгер

О, ви ведете журнал повільних запитів? Якщо так, то які у вас гарячі точки? Простий INSERTs? Яка ваша схема - чи розділена вона? Що таке explain analyzeдеякі зразки запитів? Наскільки часто бувають ваші контрольно-пропускні пункти і скільки часу вони займають? (див. параметри реєстрації контрольних точок). І якщо серйозно, то яка у вас версія PostgreSQL ? (Оновлення: Здається, ви перераховуєте тут своє обладнання: dba.stackexchange.com/questions/28061/… )
Крейг Рінгер

У будь-якому випадку, для спеціальної настройки розміру пулу єдиними реальними відповідями є встановлення надійного вимірювання навантаження та пропускної здатності сервера БД, а потім почніть налаштування вгору та вниз, поки не знайдете приємне місце.
Крейг Рінгер

@CraigRinger Ні, я не та людина. Але дякую за зворотні посилання! Я читав Налаштування вашого сервера PostgreSQL і дотримувався деяких згаданих порад. Зараз я включив налаштування, які не використовуються за замовчуванням. Зараз ми розглядаємо великі транзакції та тестуванняsynchronous_commit = off
lorgartzor

Відповіді:


14

Коротка відповідь тут - "проба та помилка керуються моніторингом та показниками ефективності".

Існують деякі загальні правила, які допоможуть вам знайти неясну область, з якої слід почати, але вони дуже загальні. Найчастіше цитуються загальні рекомендації "кількість процесорів плюс кількість незалежних дисків", але це лише неймовірно груба відправна точка.

Насправді вам потрібно зробити надійні показники ефективності для вашої програми. Почніть статистику запису.

Інтегрованого інструментарію для цього не багато. Є такі речі, як check_postgresсценарій nagios , реєстрація лічильників ефективності системи Cacti , збирач статистики PostgreSQL тощо ..., але це не так багато, що поєднує це все. На жаль, вам доведеться зробити цей шматочок самостійно. Для сторони PostgreSQL див. Моніторинг у посібнику з PostgreSQL. Існують деякі сторонні варіанти, наприклад Postgres Enterprise Monitor Monitor EnterpriseDB .

Для згаданих тут показників на рівні додатків ви хочете записати їх у спільні структури даних або у зовнішній нетривалий БД, наприклад Redis, та об'єднати їх під час запису або перед тим, як записати їх у свій постgreSQL БД. Спроба ввійти безпосередньо до Pg, спотворить ваші вимірювання накладними, створеними записом вимірювань, і погіршить проблему.

Найпростіший варіант - це, мабуть, синглтон на кожному сервері додатків, який ви використовуєте для запису статистики додатків. Ви, мабуть, хочете постійно оновлювати min, max, n, total та mean; таким чином вам не доведеться зберігати кожну статистичну точку, лише агрегати. Цей сингл може записувати свої сукупні статистичні дані в Pg кожні х хвилин, достатньо низький показник, що вплив на продуктивність буде мінімальним.

Починати з:

  • Яка затримка запиту? Іншими словами, скільки часу програмі потрібно отримати від запиту від клієнта, поки він не відповість клієнту. Записуйте це у сукупності за певний проміжок часу, а не як окремі записи. Згрупуйте його за типом запиту; скажімо, за сторінкою.

  • Яка затримка доступу до бази даних для кожного запиту чи типу запиту, який виконує додаток? Скільки часу потрібно просити БД для інформації / зберігання інформації, поки вона не буде виконана, і перейти до наступного завдання? Знову ж, агрегуйте ці статистичні дані у програмі та запишіть у БД лише сукупну інформацію.

  • Яка ваша пропускна здатність? За будь-які х хвилин, скільки запитів кожного основного класу, що виконується вашим додатком, обслуговує DB?

  • За той самий часовий діапазон х хвилин, скільки запитів клієнтів було?

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

  • Знову вибірки та агрегації за той самий часовий інтервал, якими були показники ефективності хост-системи? Скільки читають і скільки записують вводу-виводу в секунду? Мегабайти на секунду диска читає і записує? Використання процесора? Середнє завантаження? Використання оперативної пам'яті?

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

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

Коли ви будете графікувати транзакції за секунду відповідно до кількості одночасних з'єднань та виправити різну швидкість запитів, яку бачить додаток, ви зможете краще зрозуміти, де знаходиться ваша пропускна здатність.

Якщо у вас немає швидкого зберігання даних (BBU RAID або швидкі міцні SSD), ви не хочете більше ніж досить невелика кількість активно записуючих з'єднань, можливо, максимум 2 рази кількість дисків у вас, ймовірно, менше, залежно від розташування RAID , продуктивність диска тощо. У цьому випадку навіть не варто проб і помилок; просто оновіть підсистему зберігання даних до такої, яка швидко проганяє диск .

Подивіться pg_test_fsyncна інструмент, який допоможе вам визначити, чи це може бути проблемою для вас. Більшість пакетів PostgreSQL встановлюють цей інструмент як частину contrib, тому вам не потрібно буде його компілювати. Якщо ви отримуєте менше пари тисяч оп / секунду, pg_test_fsyncвам терміново потрібно оновити систему зберігання. Мій ноутбук, оснащений SSD, отримує 5000-7000. Моя робоча станція при роботі з 4-дисковим масивом RAID 10 з 7200 об / хв SATA-дисками та записом (без кешування-запису) отримує приблизно 80 оп / секунду f_datasync, до 20 ops / секунду fsync(); це в сотні разів повільніше . Для порівняння: ноутбук з SSD проти станції з записом через (НЕ кешування запису) RAID 10. SSD цього ноутбука коштує дешево, і я не обов'язково довіряю йому очищати кеш запису щодо втрати електроенергії; Я зберігаю гарні резервні копії і не використовую їх для даних, які мені важливі. Високоякісні SSD-накопичувачі виконуються так само добре, якщо не краще, і є надійними для запису.

Що стосується вашої заявки, я настійно раджу поглянути на:

  • Хороша підсистема зберігання з швидкими потоками. Я не можу наголосити на цьому достатньо. Якісні SSD-накопичувачі та / або RAID-контролер належної якості з кешованим захищеним кешем.
  • Використовуючи UNLOGGEDтаблиці для даних, які ви можете дозволити собі втратити. Періодично агрегуйте його в журнали, що входять в систему. Наприклад, зберігайте незавершені ігри в незамкнутих таблицях і записуйте їх у звичайні міцні таблиці.
  • Використання commit_delay(менш корисне для швидкого промивання сховища - підказка)
  • Вимкнення synchronous_commitтранзакцій, які ви можете дозволити собі втратити (менш корисно, якщо швидко зберігається сховище - підказка)
  • Таблиці розділів, особливо таблиці, де дані "старіють" та очищаються. Замість видалення з розділеної таблиці опустіть розділ.
  • Часткові показники
  • Зменшення кількості створених індексів. Кожен індекс має вартість запису.
  • Об'ємна робота в більші транзакції
  • Використання гарячих резервних реплік лише для читання для зняття завантаження читання з основної БД
  • Використання шару кешування, подібного до перемикання або повторного редагування, для даних, які змінюються рідше або можуть дозволити собі бути несвіжими. Ви можете використовувати LISTENта NOTIFYвиконувати відключення кешу, використовуючи тригери на таблицях PostgreSQL.

Якщо ви сумніваєтесь: http://www.postgresql.org/support/professional_support/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.