PostgreSQL и настройки за последователност на записа за всяко конкретно свързване

Преводът на статията е подготвен специално за студентите в курса «Бази Данни». Интересно ли ви е да се развивате в тази сфера? Каним ви на Ден на Отворените Врати, където подробно разглеждаме програмата, особеностите на онлайн формата, компетенциите и кариерните перспективи, които очакват завършилите след обучението.

PostgreSQL и настройки за последователност на записа за всяко конкретно свързване

PostgreSQL и настройки за последователност на записа за всяко конкретно свързване
В Compose работим с много бази данни, именно това ни дава шанса да се запознаем отблизо с тяхната функционалност и недостатъци. Докато учим да ценим функционалните характеристики на новите бази данни, понякога започваме да се замисляме как би било добре, ако подобни функции бяха налични и в по-зрели инструменти, с които работим от дълго време. Една от новите функции, която желаехме да видим в PostgreSQL, беше настраиваемата последователност на записите според свързването в целия кластер. И се оказа, че вече я имаме, и днес искаме да споделим с вас как можете да я използвате.

Защо ми е това?

Това как трябва да се държи кластерът зависи от вашето приложение. Например, ако имате приложение за плащане на сметки. Ще ви трябва сто процента последователност в кластера, така че ще трябва да активирате синхронни ангажименти, за да изчакате базата данни, докато бъдат направени всички промени. Въпреки това, ако вашето приложение е бързо развиваща се социална мрежа, вероятно ще предпочетете бърз отговор пред сто процента последователност. За да постигнете това, можете да използвате асинхронни ангажименти във вашия кластер.

Запознайте се с компромиса

Ще трябва да направите компромис между последователността на данните и производителността. PostgreSQL се движи от последователността, тъй като конфигурацията по подразбиране в такъв случай е предсказуема и без неочаквани изненади. А сега нека се запознаем с компромисите.

Компромис 1: Производителност

Ако PostgreSQL клъстерът не изисква последователност, той спокойно може да работи асинхронно. Записите се извършват при водещия на клъстера, а обновленията ще бъдат изпратени на репликите му след няколко милисекунди. Когато клъстерът PostgreSQL изисква последователност, той трябва да работи синхронно. Записът ще бъде извършен при водещия на клъстера, който ще изпрати обновленията на репликите и ще изчака потвърждение, че всяка от тях е направила записа, преди да изпрати потвърждение на клиента, който е инициирал записа, че той е успешен. Практическата разлика между тези подходи е, че асинхронният метод изисква два мрежови скока, а синхронният – четири.

Компромис 2: Последователност

Резултатът при повреда на водещия в тези два подхода също ще бъде различен. Ако работата се изпълнява асинхронно, то при възникването на такава грешка не всички записи ще бъдат потвърдени от репликите. Колко ще бъде загубено? Зависимостта е от самото приложение и ефективността на репликацията. Репликацията на Compose предотвратява репликата да стане водеща, в случай че количеството информация в нея е с 1 MB по-малко от водещия, т.е. потенциално може да бъде загубено до 1 MB записи при асинхронна работа.

В синхронен режим това не се случва. Ако водещият се провали, всички реплики се обновяват, тъй като всеки запис, потвърден от водещия, трябва да бъде потвърден и при репликите. Ето я – последователността.

Синхронното поведение е целесъобразно да се използва в приложение за плащане на сметки, където последователността има явна предимство при търсенето на компромис между последователността и производителността. Най-важното за такова приложение е валидните данни. А сега помислете за социална мрежа, в която основната задача е да задържи вниманието на потребителя, отговаряйки на запитванията колкото се може по-бързо. В такъв случай производителността с по-малко мрежови скокове и по-малко изчакване на комитите ще бъде приоритет. Въпреки това компромисът между производителността и последователността не е единственият, за който трябва да се мисли.

Компромис 3: Повреди

Много важно е да разберете как се държи клъстерът по време на срив. Нека разгледаме ситуация, в която една или повече реплики отказват. Когато комитите се обработват асинхронно, лидерът ще продължи да функционира, т.е. да приема и обработва записи, без да чака липсващите реплики. Когато репликите се върнат в клъстера, те настигат лидера. При синхронна репликация, ако репликите не отговарят, лидерът няма да има избор и ще продължи да чака потвърждение на комита, докато репликата не се върне в клъстера и не може да приеме и потвърди записа.

По едно свързване на транзакция?

На всяко приложение му е нужен специален тип комбинация между последователност и производителност. Освен ако това не е нашето приложение за плащане на сметки, което си представяме, че е напълно последователно, или нашето почти ефимерно приложение за социална мрежа. Във всички останали случаи ще има моменти, когато част от операциите трябва да бъдат синхронни, а някои – асинхронни. Може да не искате системата да чака, докато съобщението, изпратено в чата, бъде закомитено, но ако в това същото приложение протича плащане, ще трябва да чакате.

Всички тези решения, разбира се, взима разработчикът на приложението. Правилните решения относно това кога да се прилага едно или друго подходство ще помогнат да извлечете максимума от клъстера. Важно е разработчикът да може да преминава между тях на ниво SQL за свързванията и за транзакциите.

Осигуряване на контрол на практика

По подразбиране PostgreSQL осигурява последователност. Това се контролира от параметъра на сървъра synchronous_commit. По подразбиране е в положение включено, но има три други варианта: local, remote_write или off.

При задаване на параметъра на off всички синхронни комити спират, дори в локалната система. Параметърът в local определя синхронния режим за локалната система, но записите в репликите се извършват асинхронно. Remote_write отива още по-далеч: записите в репликите се извършват асинхронно, но се връщат, когато репликата е приела записа, но не го е записала на диск.

Разглеждайки наличния диапазон от опции, ние избираме поведението и, помнейки че включено – това са синхронни записи, ще изберем local за асинхронни комити през мрежата, оставяйки локалните комити синхронни.

Сега ще ви разкажем как да настроите това за нула време, но си представете, че сме инсталирали synchronous_commit в local за сървъра. Зададохме си въпроса, може ли да променим параметъра synchronous_commit на лету и се оказа, че не само че може, а за това има цели два начина. Първият е да зададете сесията на вашето свързване по следния начин:

SET SESSION synchronous_commit TO ON;  
// Вашите записи идват тук

Всички последващи записи в сесията ще потвърдят операциите за запис за репликите, преди да върнат положителен резултат на свързания клиент. Разбира се, ако не промените настройката synchronous_commit отново. Може да опуснете част SESSION в командата, тъй като тя ще бъде с подразбираща стойност.

Вторият начин е добър, когато просто искате да се уверите, че получавате синхронна репликация за една транзакция. В много бази данни от поколение «NoSQL» концепцията за транзакции не съществува, но в PostgreSQL тя съществува. В този случай стартирате транзакция и след това задавате synchronous_commit в включено преди да извършите запис за транзакцията. COMMIT ще фиксира транзакцията, използвайки всяка стойност на параметъра synchronous_commit, която е била зададена в този момент, въпреки че е най-добре да зададете променливата предварително, за да сте сигурни, че другите разработчици разбират, че записите не са асинхронни.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Вашите записи идват тук
COMMIT;  

Всички комити на транзакции сега ще бъдат потвърдени, като записани в реплики преди базата данни да върне положителен отговор на свързания клиент.

Настройка на PostgreSQL

Преди това си представяхме система PostgreSQL с synchronous_commit, инсталиран в local. За да бъде това реално от страна на сървъра, трябва да инсталирате два параметъра за конфигурация на сървъра. Друг параметър synchronous_standby_names влиза в сила, когато synchronous_commit е в включено. Той определя кои реплики имат право на синхронни комити и ние ще го зададем на *, което ще означава активиране на всички реплики. Тези стойности обикновено се настройват в конфигурационният файл чрез добавяне:

synchronous_commit = local  
synchronous_standby_names='*'

Като зададем параметъра synchronous_commit на стойността local, създаваме система, в която локалните дискове остават синхронни, но комитите на мрежовите реплики по подразбиране са асинхронни. Разбира се, ако не решим да направим тези комити синхронни, както е показано по-горе.

Ако сте следили развитието на проекта Governor, може да сте забелязали някои наскоро настъпили промени (1, 2), които позволиха на потребителите Governor да тестват тези параметри и да контролират тяхната последователност.

Още малко...

Буквално преди седмица щях да ви кажа, че е невъзможно да настроите PostgreSQL толкова прецизно. Тогава Кърт, член на платформата Compose, настояваше, че такава възможност съществува. Той потуши моите възражения и намери в документацията на PostgreSQL следното:

PostgreSQL и настройки за последователност на записа за всяко конкретно свързване

Тази настройка може да бъде променена по всяко време. Поведението при всяка транзакция се определя от настройката, действаща при ангажимента. Затова е възможно и полезно за някои транзакции ангажиментите да се извършват синхронно, а за други - асинхронно. Например, за да накарате един multistatement транзакция да прави ангажименти асинхронно, когато стойността на параметъра по подразбиране е противоположна, задайте SET LOCAL synchronous_commit TO OFF в транзакцията.

С помощта на тази малка модификация в конфигурационния файл предоставихме на потребителите възможността да контролират своята последователност и производителност.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster