DB master/slave - čtení/zápis na straně aplikace

vesterna12

  • **
  • 79
  • byrokracie zabíjí kreativitu
    • Zobrazit profil
    • E-mail
DB master/slave - čtení/zápis na straně aplikace
« kdy: 27. 05. 2022, 18:10:22 »
Mám testovací cluster kde je jeden master a několik replik/slave.
Pokud potřebuji data číst, můžu tuto operaci směrovat na libovolný nod (preferované jsou však repliky).
Pokud potřebuji provádět zápis tak můžu použít pouze "master".

Oba děje v aplikaci rozlišuji a podle charakteru dotazu používám buď master nebo repliku.

Dělá se to takhle nebo existuje vhodnější způsob?



Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #1 kdy: 27. 05. 2022, 21:38:04 »
Ne, dělá se to tak, že provoz z aplikace směřujete na nějakou proxy (ať už zabudovanou v databázi nebo externí), která ví, kde je master a kde slave, a podle toho směruje provoz. To vám umožňuje v případě potřeby master rychle přepnout jinam, když původní master potřebujete odstavit nebo odpadne sám. Kdybyste to dělal až v aplikacích, musíte přepnutí masteru řešit změnou konfigurace každé aplikace, což by bylo zdlouhavé, náchylné na chyby a nejspíš by se to neobešlo bez výpadků aplikací.

Logik

  • *****
  • 993
    • Zobrazit profil
    • E-mail
Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #2 kdy: 29. 05. 2022, 00:56:17 »
Nejsou toto náhodou ortogonální problémy?
Protože proxy nemůže vědět, jestli moje nová connection bude read-only, nebo read-write, takže mne nemůže sama od sebe správně přesměrovat na master (v případě zápisu) či na slave. A proxy nemůže jen tak v rámci transakce přesunout connection na jiný db server.

RDa

  • *****
  • 1 772
    • Zobrazit profil
    • E-mail
Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #3 kdy: 29. 05. 2022, 02:08:53 »
Nejsou toto náhodou ortogonální problémy?
Protože proxy nemůže vědět, jestli moje nová connection bude read-only, nebo read-write, takže mne nemůže sama od sebe správně přesměrovat na master (v případě zápisu) či na slave. A proxy nemůže jen tak v rámci transakce přesunout connection na jiný db server.

Proxy prece vidi co za dotaz provedete. A klidne muze prekladat i DB vrstvu na jiny protokol.


Podle me je spravna odpoved tady zavisla na charakteru aplikace.

Jestli dotaz do aplikace (backendu) neni kriticky a muze vratit "failed / not available" (a zotavovat se z toho bude jina cast), tak si klidne ponechte stavajici reseni, s moznosti aplikovat zmenu konfigurace pri kazdem dotazu (nebo co minutu, ci jiny casovy usek). Vetsina veci je resena timto stylem, a v pripade problemu selze nejake male procento dotazu.

Pokud se ale vyzaduje funkcionalita na vyssi urovni spolehlivosti, tak je cesta vyjmout obsluhu databaze z vaseho backendu do dalsi vrstvy - ktera bude resit klidne i failover behem zpracovani jednoho vnejsiho requestu.

Dalsi uroven je kombinace obojiho, kde klasicke RO dotazy jsou smerovany prvnim zpusobem a nevadi kdyz selzou, uzivatel nebo vzdaleny konec appky se postara o retry, ale dotazy s RW operacema budou vykonany skrze jine uzly, kde je obsluha fikanejsi (a treba nepovedene dotazy se nekde zaloguji / odlozi bokem do retry fronty, atd.)

Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #4 kdy: 29. 05. 2022, 10:19:30 »
Nejsou toto náhodou ortogonální problémy?
Protože proxy nemůže vědět, jestli moje nová connection bude read-only, nebo read-write, takže mne nemůže sama od sebe správně přesměrovat na master (v případě zápisu) či na slave. A proxy nemůže jen tak v rámci transakce přesunout connection na jiný db server.
Směrování na primary/secondary se nemusí dělat po spojeních, ale po transakcích. A jestli je transakce jen pro čtení nebo pro zápis proxy ví, je to jeden z parametrů transakce.

Samostatné aplikace (proxy), které umí směrovat transakce na správný server, jsou např. pgBouncer nebo pgPool.

Případně můžete v aplikaci použít dva zdroje dat – jeden pro čtení a druhý pro zápis. Třeba JDBC driver pro PostgreSQL pro to má podporu, můžete mu dát víc serverů najednou a určit, že má používat jen primární servery (to bude datasource pro zápis) nebo že má preferovat sekundární (datasource pro čtení).

Jinak pokud v clusteru nemáte automatický failover (třeba pomocí repmgr), ale ruční, můžete měnit ručně i konfiguraci klientů. Já jsem si pod „cluster“ automaticky představil automatický failover.


vesterna12

  • **
  • 79
  • byrokracie zabíjí kreativitu
    • Zobrazit profil
    • E-mail
Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #5 kdy: 29. 05. 2022, 15:55:49 »
Hrál jsem si o víkendu s pgpool2 a jeví se mi to jako nejlepší cesta. Děkuji za tip.

- 2x ( 3 nody, 1 master, 2x replica )
- pgpool2 také podporuje active/standby tzn. žádný "single point of failure" (pokud ignoruji redundanci nižších vrstev)
- možnost automatického i manuálního "failoveru"

Pár základních scénářů, kde testuji selhání a obnovu mi prošlo vč. zachování integrity dat.

Co je pro tento cluster specifické je možnost "nekonečného" škálování úložiště.
K tomu, používám "foreign data wrapper" a tabulky které jsou rozlezlé po 2 nodech (table partitioning + sharding) s možností přidávat další podle potřeby.
Jak takový cluster můžu replikovat do jiného regionu?

Jsem smířen, že zápis do DB se provádí jen z jednoho místa a to i za cenu horší odezvy UI.
Pro čtení bych ale rád použil regionální repliku (ta krmí cache, ale to teď neřeším), která je blíže k uživateli.
Jak takový cluster replikovat?
Pokud bych přidal slave repliky ty se budou dál kvůli konfigurací foreign data wrapper odkazkovat na původní servery.
Problém jsem zatím řešil tak, že celý cluster je znovu postavený v druhém DC a mezi clustery je použita logická replika, které funguje na bázi "publish-subscribe". Má to svoje nevýhody, ale s tím se dá žít.
Možná existuje lepší řešení? 

Kdyby první DC úplně umřelo, můžu začít používat druhé DC okamžitě, protože replikace je synchronní. Logickou replikací bych data pak mohl přelít do nového DC.

Chtěl jsem pochopit co umí Postgres tak si s tím teď hraju. Po řešení sraček s auditem v korporátu je to příjemné osvěžení...


« Poslední změna: 29. 05. 2022, 16:02:36 od vesterna12 »

vesterna12

  • **
  • 79
  • byrokracie zabíjí kreativitu
    • Zobrazit profil
    • E-mail
Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #6 kdy: 29. 05. 2022, 16:04:23 »
Pro multimaster jsem trochu paranoidní. Navíc zachováni integrity dat je prioritní.
Logická replikace mezi regiony byla zvolena taky s ohledem na objem přenesených dat.
« Poslední změna: 29. 05. 2022, 16:06:20 od vesterna12 »

Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #7 kdy: 30. 05. 2022, 09:47:00 »
V minulosti sa primitivne replikovalo docasnym pozastavenim slave nodu a replikovali sa priamo subory (rsync a podobne). Toto asi neprichadza do uvahy, kedze tam mas data na "nekonecnom ulozisku" teda rozlezene cez 2..n nodov.
Potrebujes naraz na 2..n nodoch vystihnut konzistentny stav, ktory je vhodny na repliku.
Zlepsit by to mohol vhodny filesystem, ktory by podporoval snapshoty. Tu by ale tiez bolo treba na chvilku vsetko pozastavit.
Jedina moznost ako synchronizovat bez pozastavenia je cez WAL, co myslim vyuzivas v tvojej logickej replikacii, ale to uz je mimo moje obmedzene znalosti. Snad sa tu zastavi Pavel Stehule a da ti dobru radu vyuzivajucu aktualne moznosti PostgreSQL. Pripadne aspon potvrdi, ci to robis dobre.

Logik

  • *****
  • 993
    • Zobrazit profil
    • E-mail
Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #8 kdy: 30. 05. 2022, 13:05:36 »
Citace
Proxy prece vidi co za dotaz provedete. A klidne muze prekladat i DB vrstvu na jiny protokol.
Proxy neví, jestli když na začátku provádím nějaké čtení, tak jestli bude v transakci následovat zápis. Ono dokonce to nejde ani zaručit analýzou dotazu - (pokud teda nemá ta proxy plnou informaci o struktuře DB a neprováděla by nad tím "zběsilou analýzu").
Jediné, na co se jde "spolehnout" je explicitní označování transakcí "BEGIN TRANSACTION READ ONLY" - a to ještě musí programátor "slíbit", že ji nepřepne do RW. A to už se v podstatě neliší od toho, když programátor explicitně vybere datový zdroj.

Citace
- ktera bude resit klidne i failover behem zpracovani jednoho vnejsiho requestu.
To právě IMHO není tak jednoduché, jak se to zdá. Pokud není aplikace jen čisté zobrazovadlo pro DB logiku, tak asi jo, ale jinak mi přijde, že je to principiálně nemožné. Protože ten failover znamená spustit transakci znovu: tedy výsledek dotazů může být jiný než v původní transakci, takže by aplikace prováděla něco jiného. V okamžiku, kdy mám byť nějakou logiku v aplikaci, tak failover (ve smyslu "replay" dotazů) prostě musí dělat aplikace, ne? Proxy nemůže udělat nic chytřejšího, než aktivní transakce ukončit. Nebo se pletu?

IMHO "Manuálnímu" rozdělení transakcí na read-only a read-write se nevyhnu tak jako tak, v tom mne PgPool IMHO nepomůže - jde jen o formu, jestli ji označím pomocí READ ONLY, nebo použiju k připojení jinej endpoint.
A co se týče rychlého failoveru, tak ten se přeci nemusí dělat "rekonfigurací aplikace", ale např. za pomocí IP směrování nebo..... Tím nechci říkat, že PgPool nemá své výhody. Má. Jen, že dilema buďto proxy, nebo nutnost rekonfigurace aplikace se mi zdá, že tak úplně neplatí - že Proxy je pouze jedna z variant (byť osvědčená a dobrá, takže proč vymejšlet kolo), jak se dá failover řešit, aniž by to "aplikace viděla".
 Koneckonců - PGPool je signle point of failure, což samotnej PGPool řeší pomocí přehazování "virtuální" IP. Což je přesně řešení, které se nabízí pro řešení failover i bez použití proxy.



Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #9 kdy: 30. 05. 2022, 14:34:44 »
A to už se v podstatě neliší od toho, když programátor explicitně vybere datový zdroj.
Rozdíl je v tom, že na datový zdroj mohou být navázané další věci, třeba cache. Takže použití jiného datové zdroje může mít další konsekvence.

A co se týče rychlého failoveru, tak ten se přeci nemusí dělat "rekonfigurací aplikace", ale např. za pomocí IP směrování nebo.....
Nemusí se dělat jen rekonfigurací aplikace, ale zrovna začít posílat IP pakety v průběhu navázaného spojení někam jinam podle mne není nejlepší způsob, protože to bude chvíli trvat, než se zjistí, že to spojení je nakopnuté a má se ukončit  a navázat nové.

Podstatné je říct si, k čemu vlastně má ten cluster sloužit. Pokud jde hlavně o bezpečné uložení dat, jako bonus zrychlení přístupu, ale pokud vypadne master, můžu si dovolit odstavit aplikaci třeb ai na několik hodin a během odstávky v klidu podle předem daného postupu přepnout provoz na jiný primární server, je to jiná situace, než když si od clusteru slibuju minimalizaci doby, kdy aplikace nemůže provádět zápis. V tom druhém případě je potřeba na to mít nastavené automaty. A osobně bych to nedělal tak, že někomu něco utrhnu pod nohama. Buď se víc datových zdrojů řeší na úrovni aplikace, pak by měla aplikace vědět, který je její aktuální datový zdroj. Nebo je tam nějaká proxy, takže z pohledu aplikace je to transparentní, a to, kam jde reálný provoz, zase ví proxy.

Nejhorší, co se vám s clusterem může stát, že budete mít dva (nebo více) primárů. K čemuž dojde snáz, když nevidíte, s čím se reálně komunikuje. Pak můžete mít dva aplikační servery, oba se připojují k databázi na stejné IP adrese, ale každý bude ve skutečnosti mít pod tou IP adresou jiný primár…

Logik

  • *****
  • 993
    • Zobrazit profil
    • E-mail
Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #10 kdy: 30. 05. 2022, 18:46:35 »
Citace
Nemusí se dělat jen rekonfigurací aplikace, ale zrovna začít posílat IP pakety v průběhu navázaného spojení někam jinam podle mne není nejlepší způsob...
To sice ano, ale nic lepšího moc nevymyslíš (pokud tedy nechceš mít v aplikaci explicitně zadefinových x datových zdrojů a nějaký "výběr nejlepšího" - což už ovšem není transparentní řešení a při rozšiřování clusteru musíš upravovat aplikaci, což zpravidla není žádoucí).
Pgpool funguje na přesně tomdle principu, akorát tu "plovoucí" (virtuální) IP adresu nemá přímo databáze, ale ta "master proxy" - ale i ta může selhat a má redunanci a pak dojde k úplně stejnému procesu, který se Ti nelíbí: aktuální pochcípaj, záložní pgpool si převezme IP adresu, a další spojení jdou na tu "novou master proxy".
Jasně, případů, kdy chcípne bez varování proxy je asi méně, než když chcípne rovnou databáze, ale např. v případě HW problému (což bude asi nejčastější příčina?) se to bude chovat úplně stejně.

Citace
...protože to bude chvíli trvat, než se zjistí, že to spojení je nakopnuté a má se ukončit  a navázat nové.
Všimne si toho poměrně hned, protože nový stroj pošle po prvním doručeném packetu zpátky RST packet informující o rozpadlém (z pohledu nového stroje neexistujícím) spojení.

Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #11 kdy: 30. 05. 2022, 19:15:09 »
To sice ano, ale nic lepšího moc nevymyslíš (pokud tedy nechceš mít v aplikaci explicitně zadefinových x datových zdrojů a nějaký "výběr nejlepšího" - což už ovšem není transparentní řešení a při rozšiřování clusteru musíš upravovat aplikaci, což zpravidla není žádoucí).
Výběr nejlepšího může být obyčejný round-robin nebo náhodný výběr. Datové zdroje nemusí být zadrátované v aplikaci, mohou být dané konfigurací.

Re:DB master/slave - čtení/zápis na straně aplikace
« Odpověď #12 kdy: 31. 05. 2022, 11:54:18 »
Zde https://scalegrid.io/blog/managing-high-availability-in-postgresql-part-3/ je mozne si procist, jak se zachovaly ruzna HA reseni v pripade ruznych failover scenaru.

Bohuzel implementace automaticke HA v postgresql dost pokulhava oproti jinym db resenim (nutno externi procesy, a to opet v HA...) i ve slozitosti.
Sami bychom to potrebovali, ale pri par let stare konzultaci od p. Stehule jsme se dozvedeli, ze skoro nezna firmu, kde by to meli resp. uspesne pouzivali.