{"id":35706,"date":"2019-10-31T22:05:50","date_gmt":"2019-10-31T19:05:50","guid":{"rendered":"https:\/\/prohoster.info\/blog\/otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya\/"},"modified":"2026-05-18T20:58:46","modified_gmt":"2026-05-18T18:58:46","slug":"otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya","title":{"rendered":"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>I artikeln kommer jag att ber\u00e4tta hur vi n\u00e4rmade oss fr\u00e5gan om tillf\u00f6rlitlighet f\u00f6r PostgreSQL, varf\u00f6r det blev viktigt f\u00f6r oss och vad vi slutligen \u00e5stadkom.<\/p>\n<p>Vi har en h\u00f6gbelastad tj\u00e4nst: 2,5 miljoner anv\u00e4ndare v\u00e4rlden \u00f6ver, \u00f6ver 50 000 aktiva anv\u00e4ndare varje dag. Servrarna ligger i Amazon inom en region i Irland: mer \u00e4n 100 olika servrar \u00e4r st\u00e4ndigt i drift, varav n\u00e4stan 50 har databaser.<\/p>\n<p>Hela backend-omr\u00e5det \u00e4r en stor monolitisk stateful-applikation p\u00e5 Java, som uppr\u00e4tth\u00e5ller en konstant websocket-anslutning till klienten. N\u00e4r flera anv\u00e4ndare arbetar samtidigt p\u00e5 samma tavla ser alla f\u00f6r\u00e4ndringar i realtid, eftersom varje f\u00f6r\u00e4ndring registreras i databasen. Vi har ungef\u00e4r 10 000 f\u00f6rfr\u00e5gningar per sekund till v\u00e5ra databaser. Under toppbelastning skriver vi i Redis med 80-100 000 f\u00f6rfr\u00e5gningar per sekund.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/443f85815b0560fade7db5b639942935.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><br \/>\n<a rel=\"nofollow\" name=\"habracut\"><\/a><\/p>\n<h2>Varf\u00f6r vi gick fr\u00e5n Redis till PostgreSQL<\/h2>\n<p>Ursprungligen fungerade v\u00e5r tj\u00e4nst med Redis, en key-value-lagring som lagrar all data i minnet. <a href=\"https:\/\/prohoster.info\/sv\/server\/\">servern<\/a>.<\/p>\n<p>F\u00f6rdelar med Redis:<\/p>\n<ol>\n<li>H\u00f6g svarsf\u00f6rm\u00e5ga, eftersom allt lagras i minnet;<\/li>\n<li>Bekv\u00e4m backup och replikering.<\/li>\n<\/ol>\n<p>Nackdelar med Redis f\u00f6r oss:<\/p>\n<ol>\n<li>Det finns inga verkliga transaktioner. Vi f\u00f6rs\u00f6kte simulera dem p\u00e5 applikationsniv\u00e5. Tyv\u00e4rr fungerade detta inte alltid bra och kr\u00e4vde mycket komplicerad kod.<\/li>\n<li>Datam\u00e4ngden \u00e4r begr\u00e4nsad av m\u00e4ngden minne. N\u00e4r datam\u00e4ngden \u00f6kar kommer minnet att v\u00e4xa, och till slut kommer vi att n\u00e5 kapacitetsgr\u00e4nserna f\u00f6r den valda instansen, vilket i AWS kr\u00e4ver att vi stoppar v\u00e5r tj\u00e4nst f\u00f6r att \u00e4ndra typ av instans.<\/li>\n<li>Det \u00e4r n\u00f6dv\u00e4ndigt att st\u00e4ndigt uppr\u00e4tth\u00e5lla en l\u00e5g latensniv\u00e5, eftersom vi har ett mycket stort antal f\u00f6rfr\u00e5gningar. Optimal latens f\u00f6r oss \u00e4r 17-20 ms. Vid en latens p\u00e5 30-40 ms f\u00e5r vi l\u00e5nga svar p\u00e5 v\u00e5ra applikationsf\u00f6rfr\u00e5gningar och degradering av tj\u00e4nsten. Tyv\u00e4rr intr\u00e4ffade detta i september 2018, n\u00e4r en av instanserna med Redis av n\u00e5gon anledning fick en latens som var dubbelt s\u00e5 h\u00f6g som vanligt. F\u00f6r att l\u00f6sa problemet stoppade vi tj\u00e4nsten mitt p\u00e5 dagen f\u00f6r underh\u00e5ll och ersatte den problematiska Redis-instansen.<\/li>\n<li>Det \u00e4r l\u00e4tt att f\u00e5 inkonsekvens i datan \u00e4ven vid sm\u00e5 fel i koden och sedan spendera mycket tid p\u00e5 att skriva kod f\u00f6r att r\u00e4tta till dessa data.<\/li>\n<\/ol>\n<p>Vi har beaktat nackdelarna och insett att vi beh\u00f6ver flytta till n\u00e5got mer bekv\u00e4mt, med normala transaktioner och mindre beroende av latens. Vi genomf\u00f6rde en unders\u00f6kning, analyserade m\u00e5nga alternativ och valde PostgreSQL.<\/p>\n<p>Vi har flyttat till den nya databasen i 1,5 \u00e5r och har bara flyttat en liten del av datan, s\u00e5 vi arbetar f\u00f6r n\u00e4rvarande med b\u00e5de Redis och PostgreSQL. Mer om etapperna f\u00f6r flytten och \u00f6verg\u00e5ngen av data mellan databaserna st\u00e5r det i <a href=\"https:\/\/habr.com\/ru\/company\/miro\/blog\/437826\/\" rel=\"nofollow\">artikeln av min kollega<\/a>.<\/p>\n<p>N\u00e4r vi precis b\u00f6rjade flytta, arbetade v\u00e5r applikation direkt med databasen och kommunicerade med master Redis och PostgreSQL. PostgreSQL-klustret bestod av en master och en replik med asynkron replikering. S\u00e5 h\u00e4r s\u00e5g schemat ut f\u00f6r arbete med databaserna:<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/674dd77de4c8b48a946c9f64c0b2fdd1.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<h2>Implementering av PgBouncer<\/h2>\n<p>Under tiden vi flyttade, utvecklades produkten ocks\u00e5: antalet anv\u00e4ndare och servrar som arbetade med PostgreSQL \u00f6kade, och vi b\u00f6rjade f\u00e5 brist p\u00e5 anslutningar. PostgreSQL skapar en separat process f\u00f6r varje anslutning och f\u00f6rbrukar resurser. Antalet anslutningar kan \u00f6kas till en viss punkt, annars finns risken att databasen arbetar suboptimalt. Den ideala l\u00f6sningen i en s\u00e5dan situation \u00e4r att v\u00e4lja en anslutningshanterare som placeras framf\u00f6r databasen.<\/p>\n<p>Vi hade tv\u00e5 alternativ f\u00f6r anslutningshanterare: Pgpool och PgBouncer. Men den f\u00f6rsta st\u00f6der inte transaktionsl\u00e4ge med databasen, s\u00e5 vi valde PgBouncer.<\/p>\n<p>Vi har st\u00e4llt in f\u00f6ljande arbetsschema: v\u00e5r applikation kommunicerar med en PgBouncer, som har PostgreSQL-masters bakom sig, och bakom varje master finns en replik med asynkron replikering.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/dabcb7f6006520c4fec85fb925e8975e.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>Samtidigt kunde vi inte lagra hela datam\u00e4ngden i PostgreSQL och hastigheten p\u00e5 datahanteringen var viktig f\u00f6r oss, s\u00e5 vi b\u00f6rjade shardera PostgreSQL p\u00e5 applikationsniv\u00e5. Det ovan beskrivna schemat \u00e4r relativt bekv\u00e4mt f\u00f6r detta: vid till\u00e4gg av ett nytt shard \u00e4r det tillr\u00e4ckligt att uppdatera PgBouncer-konfigurationen s\u00e5 att applikationen kan b\u00f6rja arbeta med det nya shardet.<\/p>\n<h3>Felresistens f\u00f6r PgBouncer<\/h3>\n<p>Detta system fungerade fram till dess att den enda instansen av PgBouncer dog. Vi befinner oss i AWS, d\u00e4r alla instanser k\u00f6rs p\u00e5 h\u00e5rdvara som ibland g\u00e5r ner. I s\u00e5dana fall flyttas instansen bara till ny h\u00e5rdvara och fungerar igen. S\u00e5 var \u00e4ven fallet med PgBouncer, men den blev otillg\u00e4nglig. Resultatet av detta nedfall blev att v\u00e5r tj\u00e4nst var otillg\u00e4nglig i 25 minuter. AWS rekommenderar f\u00f6r s\u00e5dana situationer att anv\u00e4nda redundans p\u00e5 anv\u00e4ndarsidan, vilket vi inte hade implementerat vid den tidpunkten.<\/p>\n<p>Efter detta b\u00f6rjade vi seri\u00f6st fundera p\u00e5 tillf\u00f6rlitlighet f\u00f6r PgBouncer och PostgreSQL-kluster, eftersom en liknande situation kunde intr\u00e4ffa med vilken instans som helst i v\u00e5rt AWS-konto.<\/p>\n<p>Vi byggde PgBouncer:s redundansmodell p\u00e5 f\u00f6ljande s\u00e4tt: alla applikationsservrar kontaktar Network Load Balancer, bakom vilken det finns tv\u00e5 PgBouncer-instanser. Varje PgBouncer pekar p\u00e5 samma master PostgreSQL f\u00f6r varje shard. Om en instans av AWS faller, omdirigeras all trafik genom den andra PgBouncer. AWS s\u00e4kerst\u00e4ller redundans f\u00f6r Network Load Balancer.<\/p>\n<p>Denna konfiguration g\u00f6r det problemfritt att l\u00e4gga till nya PgBouncer-servrar.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/2c1f1e7d9f7be4fdeb43858520d55e36.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<h2>Att skapa ett tillf\u00f6rlitligt PostgreSQL-kluster<\/h2>\n<p>Vid l\u00f6sningen av denna uppgift \u00f6verv\u00e4gde vi olika alternativ: skr\u00e4ddarsydd failover, repmgr, AWS RDS, Patroni.<\/p>\n<h3>Egenutvecklade skript<\/h3>\n<p>Dessa kan \u00f6vervaka masterns status och, om den faller, h\u00f6ja en replik till master och uppdatera PgBouncer-konfigurationen.<\/p>\n<p>F\u00f6rdelarna med detta tillv\u00e4gag\u00e5ngss\u00e4tt ligger i den maximala enkelheten, eftersom du sj\u00e4lv skriver skripten och exakt f\u00f6rst\u00e5r hur de fungerar.<\/p>\n<p>Nackdelar:<\/p>\n<ul>\n<li>Master kan ha \u00f6verlevt, ist\u00e4llet kan ett n\u00e4tverksfel ha intr\u00e4ffat. Failover, utan att veta detta, kommer att h\u00f6ja en replik till master, och den gamla master kommer att forts\u00e4tta att fungera. Som ett resultat f\u00e5r vi tv\u00e5 servrar i rollen som master och vi vet inte vilken av dem som har de senaste aktuella uppgifterna. En s\u00e5dan situation kallas ocks\u00e5 split-brain;<\/li>\n<li>Vi blev utan replik. I v\u00e5r konfiguration finns det en master och en replik, efter omkopplingen h\u00f6js replik till master och vi har inga fler replikar, s\u00e5 vi m\u00e5ste manuellt l\u00e4gga till en ny replik;<\/li>\n<li>Ytterligare \u00f6vervakning av failover-processen beh\u00f6vs, och vi har 12 shard av PostgreSQL, vilket inneb\u00e4r att vi m\u00e5ste \u00f6vervaka 12 kluster. Vid \u00f6kning av antalet shards f\u00e5r vi inte gl\u00f6mma att uppdatera failover.<\/li>\n<\/ul>\n<p>Egenutvecklad failover verkar mycket komplicerad och kr\u00e4ver omfattande support. N\u00e4r det g\u00e4ller en PostgreSQL-kluster \u00e4r detta den enklaste l\u00f6sningen, men den \u00e4r inte skalbar, s\u00e5 den passar oss inte.<\/p>\n<h3>Repmgr<\/h3>\n<p>Replication Manager f\u00f6r PostgreSQL-kluster, som kan hantera driften av ett PostgreSQL-kluster. Det finns ingen automatisk failover \u2018ur l\u00e5dan\u2019, s\u00e5 det kr\u00e4vs att man skriver sin egen \u2018wrapper\u2019 ovanp\u00e5 den f\u00e4rdiga l\u00f6sningen. S\u00e5 det kan visa sig vara \u00e4nnu mer komplicerat \u00e4n med egenutvecklade skript, d\u00e4rf\u00f6r best\u00e4mde vi oss f\u00f6r att inte ens pr\u00f6va Repmgr.<\/p>\n<h3>AWS RDS<\/h3>\n<p>St\u00f6der allt n\u00f6dv\u00e4ndigt f\u00f6r oss, kan g\u00f6ra backups och st\u00f6der connection pool. Har automatisk switchning: n\u00e4r huvudservern d\u00f6r blir en replica den nya huvudservern, och AWS \u00e4ndrar DNS-posterna till den nya huvudservern, medan replication kan finnas i olika AZ.<\/p>\n<p>Nackdelar inkluderar avsaknaden av finjustering. Ett exempel p\u00e5 finjusteringar: p\u00e5 v\u00e5ra instanser finns det begr\u00e4nsningar f\u00f6r TCP-anslutningar, vilket tyv\u00e4rr inte g\u00e5r att g\u00f6ra i RDS:<\/p>\n<pre><code class=\"python\">net.ipv4.tcp_keepalive_time=10\nnet.ipv4.tcp_keepalive_intvl=1\nnet.ipv4.tcp_keepalive_probes=5\nnet.ipv4.tcp_retries2=3\n<\/code><\/pre>\n<p>Dessutom \u00e4r priset f\u00f6r AWS RDS n\u00e4stan dubbelt s\u00e5 h\u00f6g som det vanliga priset f\u00f6r instansen, vilket var den huvudsakliga anledningen till att vi avstod denna l\u00f6sning.<\/p>\n<h3>Patroni<\/h3>\n<p>Detta \u00e4r en mal p\u00e5 python f\u00f6r att hantera PostgreSQL med bra dokumentation, automatisk failover och \u00f6ppen k\u00e4llkod p\u00e5 GitHub.<\/p>\n<p>F\u00f6rdelar med Patroni:<\/p>\n<ul>\n<li>Varje konfigurationsparameter \u00e4r tydligt beskriven, det \u00e4r klart hur allt fungerar;<\/li>\n<li>Automatisk failover fungerar ur l\u00e5dan;<\/li>\n<li>Skriven i python, och eftersom vi sj\u00e4lva skriver mycket i python, kommer vi att ha l\u00e4ttare att hantera problem och kanske till och med hj\u00e4lpa till med projektets utveckling;<\/li>\n<li>Hanterar PostgreSQL helt och h\u00e5llet, g\u00f6r att man kan \u00e4ndra konfigurationen direkt p\u00e5 alla noder i klustret, och om en omstart av klustret kr\u00e4vs f\u00f6r att till\u00e4mpa den nya konfigurationen, kan detta ocks\u00e5 g\u00f6ras med hj\u00e4lp av Patroni.<\/li>\n<\/ul>\n<p>Nackdelar:<\/p>\n<ul>\n<li>Det framg\u00e5r inte tydligt i dokumentationen hur man korrekt arbetar med PgBouncer. \u00c4ven om det \u00e4r sv\u00e5rt att kalla detta en nackdel, eftersom uppgiften f\u00f6r Patroni \u00e4r att hantera PostgreSQL, och hur anslutningar g\u00e5r till Patroni \u00e4r v\u00e5rt problem;<\/li>\n<li>F\u00e5 exempel p\u00e5 implementering av Patroni i stor skala, samtidigt som det finns m\u00e5nga exempel p\u00e5 implementering fr\u00e5n grunden.<\/li>\n<\/ul>\n<p>Slutligen valde vi att anv\u00e4nda just Patroni f\u00f6r att skapa en h\u00f6g tillg\u00e4nglighet kluster.<\/p>\n<h2>Implementeringsprocessen av Patroni<\/h2>\n<p>Innan vi introducerade Patroni hade vi 12 PostgreSQL-shardar med konfigurationen en master och en replika med asynkron replikering. Applikationsservrarna kontaktade databaserna via Network Load Balancer, som hade tv\u00e5 instanser med PgBouncer, som i sin tur hade alla PostgreSQL-servrar.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/8e5350d2466311593e11add30d5b1bdc.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>F\u00f6r att implementera Patroni beh\u00f6vde vi v\u00e4lja en distribuerad lagring f\u00f6r klusterkonfigurationen. Patroni fungerar med distribuerade konfigurationslagringssystem som etcd, Zookeeper och Consul. Vi har faktiskt en fullt funktionell Consul-kluster i produktion som arbetar i samverkan med Vault och som vi inte anv\u00e4nder p\u00e5 n\u00e5got annat s\u00e4tt. Ett utm\u00e4rkt tillf\u00e4lle att b\u00f6rja anv\u00e4nda Consul f\u00f6r sitt avsedda syfte.<\/p>\n<h3>Hur fungerar Patroni med Consul<\/h3>\n<p>Vi har ett Consul-kluster som best\u00e5r av tre noder och ett Patroni-kluster som best\u00e5r av en ledare och en replik (i Patroni kallas master f\u00f6r klusterledare och slavarna f\u00f6r replikor). Varje instans av Patroni-klustret skickar kontinuerligt information om klusterstatus till Consul. D\u00e4rf\u00f6r kan man alltid i Consul ta reda p\u00e5 den aktuella konfigurationen av Patroni-klustret och vem som f\u00f6r tillf\u00e4llet \u00e4r ledare.<\/p>\n<p><img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/3234594b363904424fdce64c9d77fca5.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>F\u00f6r att koppla Patroni till Consul r\u00e4cker det med att studera den officiella dokumentationen, som s\u00e4ger att man m\u00e5ste ange v\u00e4rd i formatet http eller https beroende p\u00e5 hur vi arbetar med Consul, samt kopplingsschema, vilket \u00e4r valfritt:<\/p>\n<pre><code class=\"plaintext\">host: v\u00e4rd:port f\u00f6r Consul-slutpunkten, i formatet: http(s):\/\/host:port\nschema: (valfritt) http eller https, standardinst\u00e4llningen \u00e4r http<\/code><\/pre>\n<p>Det ser enkelt ut, men h\u00e4r b\u00f6rjar understr\u00f6mmarna. Vi arbetar med Consul via en s\u00e4ker anslutning genom https, och v\u00e5r anslutningskonfiguration ser ut p\u00e5 f\u00f6ljande s\u00e4tt:<\/p>\n<pre><code class=\"python\">consul:\n  host: https:\/\/server.production.consul:8080 \n  verify: true\n  cacert: {{ consul_cacert }}\n  cert: {{ consul_cert }}\n  key: {{ consul_key }}<\/code><\/pre>\n<p>Men s\u00e5 fungerar det inte. Vid starten kan inte Patroni ansluta till Consul, eftersom den f\u00f6rs\u00f6ker g\u00e5 via http.<\/p>\n<p>F\u00f6r att l\u00f6sa problemet hj\u00e4lpte k\u00e4llkoden f\u00f6r Patroni. Tur att den \u00e4r skriven i python. Det visar sig att v\u00e4rdparametern inte parsas alls, utan protokollet m\u00e5ste anges i schema. S\u00e5 h\u00e4r ser blocket f\u00f6r fungerande konfiguration ut f\u00f6r att arbeta med Consul hos oss:<\/p>\n<pre><code class=\"python\">consul:\n  host: server.production.consul:8080\n  scheme: https\n  verify: true\n  cacert: {{ consul_cacert }}\n  cert: {{ consul_cert }}\n  key: {{ consul_key }}<\/code><\/pre>\n<h3>Consul-template<\/h3>\n<p>S\u00e5, vi har valt en lagringsl\u00f6sning f\u00f6r konfigurationen. Nu m\u00e5ste vi f\u00f6rst\u00e5 hur PgBouncer kommer att byta sin konfiguration n\u00e4r ledaren i klustret Patroni \u00e4ndras. Det finns inget svar p\u00e5 denna fr\u00e5ga i dokumentationen, eftersom det inte finns n\u00e5gon beskrivning av hur PgBouncer fungerar.<\/p>\n<p>I jakten p\u00e5 en l\u00f6sning fann vi en artikel (tyv\u00e4rr minns jag inte titeln) d\u00e4r det stod att Consul-template hj\u00e4lpte mycket i kopplingen mellan PgBouncer och Patroni. Detta fick oss att unders\u00f6ka hur Consul-template fungerar.<\/p>\n<p>Det visade sig att Consul-template st\u00e4ndigt \u00f6vervakar konfigurationen av PostgreSQL-klustret i Consul. Vid byte av ledare uppdaterar den PgBouncer-konfigurationen och skickar ett kommando f\u00f6r att ladda om den.<\/p>\n<p><img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/6cf92996a127bb6637ab81dc45fdd60a.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>En stor f\u00f6rdel med template \u00e4r att den lagras i kodform, s\u00e5 n\u00e4r en ny shard l\u00e4ggs till beh\u00f6ver vi bara g\u00f6ra ett nytt commit och uppdatera template automatiskt, vilket st\u00f6der principen om Infrastructure as Code.<\/p>\n<h3>Ny arkitektur med Patroni<\/h3>\n<p>Resultatet blev f\u00f6ljande arbetsm\u00f6nster:<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/bf9a9eff675a26039e3f76b16c6cd713.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>Alla applikationsservrar kontaktar load balancern \u2192 bakom den st\u00e5r tv\u00e5 instanser av PgBouncer \u2192 p\u00e5 varje instans k\u00f6rs Consul-template, som \u00f6vervakar statusen f\u00f6r varje Patroni-kluster och ser till att PgBouncer-konfigurationen \u00e4r aktuell, vilket dirigerar f\u00f6rfr\u00e5gningar till den nuvarande ledaren i varje kluster.<\/p>\n<h3>Manuell testning<\/h3>\n<p>Innan denna l\u00f6sning implementerades i produktion testade vi den i en liten testmilj\u00f6 och kontrollerade det automatiska v\u00e4xlingen. Vi \u00f6ppnade en tavla, flyttade en lapp och just d\u00e5 \"d\u00f6dade\" vi ledaren i klustret. I AWS r\u00e4cker det med att st\u00e4nga av instansen via konsolen.<\/p>\n<p><img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/d670fe373b774f1b52bfd8a8c3b53a21.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>Lappen \u00e5terv\u00e4nde inom 10-20 sekunder, och sedan b\u00f6rjade den flytta normalt igen. Det betyder att Patroni-klustret fungerade korrekt: det bytte ledare, skickade information till Consul och Consul-template plockade omedelbart upp denna information, ersatte PgBouncer-konfigurationen och skickade ett kommando f\u00f6r reload.<\/p>\n<h2>Hur \u00f6verlever man h\u00f6g belastning och bibeh\u00e5ller minimal driftstopp?<\/h2>\n<p>Allt fungerar utm\u00e4rkt! Men nya fr\u00e5gor dyker upp: Hur fungerar det under h\u00f6g belastning? Hur snabbt och s\u00e4kert ska allt rullas ut p\u00e5 produktion?<\/p>\n<p>Att svara p\u00e5 den f\u00f6rsta fr\u00e5gan hj\u00e4lper oss att anv\u00e4nda en testmilj\u00f6 d\u00e4r vi genomf\u00f6r belastningstestning. Den \u00e4r helt identisk med produktionen n\u00e4r det kommer till arkitektur och har genererade testdata som ungef\u00e4r motsvarar produktionens volym. Vi beslutar oss f\u00f6r att \"ta ner\" en av PostgreSQL-m\u00e4starna under testet och se vad som h\u00e4nder. Men innan vi g\u00f6r det \u00e4r det viktigt att kontrollera den automatiska distributionen, eftersom vi i denna milj\u00f6 har flera PostgreSQL-shards, vilket inneb\u00e4r att vi f\u00e5r en utm\u00e4rkt testning av konfigurationsskripten f\u00f6re produktion.<\/p>\n<p>B\u00e5da uppgifterna ser ambiti\u00f6sa ut, men vi har PostgreSQL 9.6. Kanske vi b\u00f6r uppgradera direkt till 11.2?<\/p>\n<p>Vi planerar att g\u00f6ra detta i tv\u00e5 steg: f\u00f6rst uppgradera versionen till 11.2, och sedan starta Patroni.<\/p>\n<h3>Uppgradering av PostgreSQL<\/h3>\n<p>F\u00f6r att snabbt uppgradera versionen av PostgreSQL m\u00e5ste du anv\u00e4nda alternativet <b>-k<\/b>, som skapar h\u00e5rda l\u00e4nkar p\u00e5 disken och eliminerar behovet av att kopiera dina data. F\u00f6r databaser p\u00e5 300-400 GB tar uppgraderingen 1 sekund.<\/p>\n<p>Vi har m\u00e5nga shards, s\u00e5 uppgraderingen m\u00e5ste ske automatiskt. F\u00f6r detta har vi skrivit en Ansible-playbook som utf\u00f6r hela uppgraderingsprocessen \u00e5t oss:<\/p>\n<pre><code class=\"plaintext\">\/usr\/lib\/postgresql\/11\/bin\/pg_upgrade \n&lt;b&gt;--l&auml;nk &lt;\/b&gt;\n--gammal-datadir=&#039;&#039; --ny-datadir=&#039;&#039; \n --gammal-bindir=&#039;&#039;  --ny-bindir=&#039;&#039; \n --gammal-alternativ=&#039; -c konfigurationsfil=&#039; \n --nya-alternativ=&#039; -c konfigurationsfil=&#039;<\/code><\/pre>\n<p>H\u00e4r \u00e4r det viktigt att notera att innan uppgraderingen p\u00e5b\u00f6rjas m\u00e5ste den k\u00f6ras med parametern <b>&#8212;check<\/b>, f\u00f6r att vara s\u00e4ker p\u00e5 att uppgraderingen \u00e4r m\u00f6jlig. V\u00e5rt skript g\u00f6r ocks\u00e5 en ers\u00e4ttning av konfigurationerna under uppgraderingen. Skriptet k\u00f6rde p\u00e5 30 sekunder, vilket \u00e4r ett utm\u00e4rkt resultat.<\/p>\n<h3>Starta Patroni<\/h3>\n<p>F\u00f6r att l\u00f6sa det andra problemet r\u00e4cker det med att titta p\u00e5 konfigurationen f\u00f6r Patroni. I det officiella repository finns ett exempel p\u00e5 en konfiguration med initdb som hanterar initialiseringen av en ny databas vid f\u00f6rsta starten av Patroni. Men eftersom vi redan har en f\u00e4rdig databas, har vi helt enkelt tagit bort den delen fr\u00e5n konfigurationen.<\/p>\n<p>N\u00e4r vi b\u00f6rjade installera Patroni p\u00e5 en befintlig PostgreSQL-kluster och starta den st\u00f6tte vi p\u00e5 ett nytt problem: b\u00e5da servrarna startades som ledare. Patroni vet inget om det tidigare tillst\u00e5ndet av klustret och f\u00f6rs\u00f6ker starta b\u00e5da servrarna som tv\u00e5 separata kluster med samma namn. F\u00f6r att l\u00f6sa detta problem \u00e4r det n\u00f6dv\u00e4ndigt att ta bort datakatalogen fr\u00e5n slaven:<\/p>\n<pre><code class=\"plaintext\">rm -rf \/var\/lib\/postgresql\/<\/code><\/pre>\n<p><b>Detta m\u00e5ste g\u00f6ras endast p\u00e5 slaven!<\/b><\/p>\n<p>Vid anslutning av en ren replik g\u00f6r Patroni en basebackup av ledaren och \u00e5terst\u00e4ller den p\u00e5 repliken, f\u00f6r att sedan h\u00e4mta det aktuella tillst\u00e5ndet via wal-loggar.<\/p>\n<p>En annan utmaning vi st\u00f6tt p\u00e5 \u00e4r att alla PostgreSQL-kluster som standard kallas main. N\u00e4r varje kluster inte vet n\u00e5got om de andra \u00e4r det okej. Men n\u00e4r du vill anv\u00e4nda Patroni m\u00e5ste alla kluster ha ett unikt namn. L\u00f6sningen \u00e4r att byta namn p\u00e5 klustret i PostgreSQL-konfigurationen.<\/p>\n<h3>Belastningstest<\/h3>\n<p>Vi genomf\u00f6rde ett test som simulerar anv\u00e4ndarbeteende p\u00e5 plattformarna. N\u00e4r belastningen n\u00e5dde v\u00e5rt genomsnittliga dagliga v\u00e4rde upprepade vi exakt samma test, vi st\u00e4ngde av en instans med ledande PostgreSQL. Den automatiska failovern fungerade som f\u00f6rv\u00e4ntat: Patroni bytte ledare, Consul-template uppdaterade PgBouncers konfiguration och skickade en reload-kommando. Fr\u00e5n v\u00e5ra grafer i Grafana kunde vi se att det fanns f\u00f6rdr\u00f6jningar p\u00e5 20-30 sekunder och ett litet antal fel fr\u00e5n servrar relaterade till anslutningen till databasen. Det \u00e4r en normal situation, s\u00e5dana v\u00e4rden \u00e4r acceptabla f\u00f6r v\u00e5r failover och absolut b\u00e4ttre \u00e4n driftsstopp.<\/p>\n<h2>Utrullning av Patroni i produktion<\/h2>\n<p>Som ett resultat fick vi f\u00f6ljande plan:<\/p>\n<ul>\n<li>Utrullning av Consul-template p\u00e5 PgBouncer-servrar och start;<\/li>\n<li>Uppgradering av PostgreSQL till version 11.2;<\/li>\n<li>Byta klusternamn;<\/li>\n<li>Starta Patroni-klustret.<\/li>\n<\/ul>\n<p>V\u00e5r plan g\u00f6r det m\u00f6jligt att utf\u00f6ra f\u00f6rsta punkten n\u00e4stan n\u00e4r som helst, vi kan gradvis ta bort varje PgBouncer fr\u00e5n drift och genomf\u00f6ra utrullning och start av consul-template. Det var precis vad vi gjorde.<\/p>\n<p>F\u00f6r snabb utrullning anv\u00e4nde vi Ansible, eftersom vi redan hade testat alla playbooks i testmilj\u00f6n, och tiden f\u00f6r att genomf\u00f6ra hela scenariot var mellan 1,5 och 2 minuter f\u00f6r varje shard. Vi kunde rulla ut varje shard sekventiellt utan att st\u00e4nga av v\u00e5r tj\u00e4nst, men vi skulle beh\u00f6va st\u00e4nga av varje PostgreSQL i n\u00e5gra minuter. I s\u00e5dana fall kunde anv\u00e4ndare vars data finns p\u00e5 den shard inte arbeta fullt ut under tiden, vilket \u00e4r oacceptabelt f\u00f6r oss.<\/p>\n<p>L\u00f6sningen p\u00e5 den h\u00e4r situationen blev ett planerat underh\u00e5ll som genomf\u00f6rs var tredje m\u00e5nad. Detta \u00e4r ett f\u00f6nster f\u00f6r planerat arbete n\u00e4r vi st\u00e4nger av v\u00e5r tj\u00e4nst helt och uppgraderar databasinstanser. Det var en vecka kvar till n\u00e4sta f\u00f6nster, och vi valde att v\u00e4nta och f\u00f6rbereda oss ytterligare. Under v\u00e4ntetiden vidtog vi extra precaution: f\u00f6r varje PostgreSQL-shard lyfte vi en reservreplik f\u00f6r att hantera eventuella misslyckanden och en ny instans f\u00f6r varje shard, som skulle bli en ny replik i Patroni-klustret, s\u00e5 att vi inte beh\u00f6vde k\u00f6ra ett kommando f\u00f6r att ta bort data. Allt detta hj\u00e4lpte till att minimera risken f\u00f6r fel.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/29e5c5f50dbfebfe5665fa0aeb009728.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>Vi startade om v\u00e5r tj\u00e4nst och allt fungerade som det skulle, anv\u00e4ndarna fortsatte sitt arbete, men vi m\u00e4rkte en onormalt h\u00f6g belastning p\u00e5 Consul-servrarna.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/af0eef9ac235706c0aac62d2e1ee179d.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>Varf\u00f6r s\u00e5g vi inte detta i testmilj\u00f6n? Detta problem illustrerar tydligt vikten av att f\u00f6lja principen Infrastructure as code och att utveckla hela infrastrukturen, fr\u00e5n testmilj\u00f6er till produktionsmilj\u00f6er. Annars \u00e4r det l\u00e4tt att f\u00e5 s\u00e5dana problem som vi fick. Vad h\u00e4nde? Consul kom f\u00f6rst till produktion och senare till testmilj\u00f6erna, vilket resulterade i att versionen av Consul i testmilj\u00f6erna var h\u00f6gre \u00e4n i produktion. Just i en av versionerna r\u00e4ttades en CPU-l\u00e4ckage n\u00e4r man arbetade med consul-template. S\u00e5 vi uppdaterade helt enkelt Consul f\u00f6r att l\u00f6sa problemet.<\/p>\n<h3>Starta om Patroni-klustret<\/h3>\n<p>Men vi fick ett nytt problem som vi inte ens misst\u00e4nkte. Vid uppdateringen av Consul tar vi helt enkelt bort Consul-noden fr\u00e5n klustret med kommandot consul leave \u2192 Patroni ansluter till en annan Consul-server \u2192 allting fungerar. Men n\u00e4r vi kom till den sista instansen av Consul-klustret och skickade kommando consul leave till den, startade alla Patroni-kluster om, och i loggarna s\u00e5g vi f\u00f6ljande felmeddelande:<\/p>\n<pre><code class=\"plaintext\">FEL: get_cluster\nSp&aring;r tillbaka (senaste anropet sist):\n...\nRetryFailedError: &#039;&Ouml;verskred &aring;terf&ouml;rs&ouml;ksfristen&#039;\nFEL: Fel vid kommunikation med DCS\n&lt;b&gt;LOGG: databasystemet &auml;r avst&auml;ngt&lt;\/b&gt;<\/code><\/pre>\n<p>Patroni-klustret kunde inte f\u00e5 information om sitt kluster och startade om.<\/p>\n<p>F\u00f6r att hitta en l\u00f6sning kontaktade vi f\u00f6rfattarna till Patroni genom en issue p\u00e5 GitHub. De f\u00f6reslog f\u00f6rb\u00e4ttringar av v\u00e5ra konfigurationsfiler:<\/p>\n<pre><code class=\"python\">consul:\n consul.checks: []\nbootstrap:\n dcs:\n   retry_timeout: 8<\/code><\/pre>\n<p>Vi lyckades reproducera problemet i testmilj\u00f6n och testade dessa inst\u00e4llningar d\u00e4r, men tyv\u00e4rr fungerade de inte.<\/p>\n<p>Problemet \u00e4r fortfarande ol\u00f6st. Vi planerar att prova f\u00f6ljande l\u00f6sningar:<\/p>\n<ul>\n<li>Anv\u00e4nda Consul-agent p\u00e5 varje instans i Patroni-klustret;<\/li>\n<li>Korrigera problemet i koden.<\/li>\n<\/ul>\n<p>Vi f\u00f6rst\u00e5r var felet uppst\u00e5r: problemet ligger troligen i anv\u00e4ndningen av standardtimeouten, som inte \u00e5sidos\u00e4tts via konfigurationsfilen. N\u00e4r den sista Consul-servern tas bort fr\u00e5n klustret fryser hela Consul-klustret, vilket varar l\u00e4ngre \u00e4n en sekund, och d\u00e4rf\u00f6r kan Patroni inte f\u00e5 klustrets status och startar om hela klustret.<\/p>\n<p>Lyckligtvis har vi inte st\u00f6tt p\u00e5 n\u00e5gra fler fel.<\/p>\n<h2>Resultat av anv\u00e4ndningen av Patroni<\/h2>\n<p>Efter en framg\u00e5ngsrik start av Patroni l\u00e5nade vi en extra replika i varje kluster. Nu finns det en form av kvorum i varje kluster: en ledare och tv\u00e5 repliker, f\u00f6r s\u00e4kerhets skull vid split-brain under omkoppling.<br \/>\n<img decoding=\"async\" style=\"display: block; margin: 0 auto;\" src=\"\/wp-content\/uploads\/2019\/06\/3bb4c0495fea274b04edd2e99b59eacb.png\" alt=\"Fels\u00e4kert PostgreSQL-kluster + Patroni. Implementeringserfarenhet\" \/><\/p>\n<p>Patroni har fungerat p\u00e5 produktion i mer \u00e4n tre m\u00e5nader. Under denna tid har det redan hj\u00e4lpt oss. Nyligen dog ledaren f\u00f6r ett av klustren i AWS, automatisk failover utl\u00f6ste, och anv\u00e4ndarna kunde forts\u00e4tta arbeta. Patroni uppfyllde sin huvuduppgift.<\/p>\n<p><b>En liten sammanfattning av anv\u00e4ndningen av Patroni:<\/b><\/p>\n<ul>\n<li>Bekv\u00e4mligheterna med att \u00e4ndra konfigurationen. Det r\u00e4cker att \u00e4ndra konfigurationen p\u00e5 en instans s\u00e5 synkroniseras den \u00f6ver hela klustret. Om en omstart kr\u00e4vs f\u00f6r att till\u00e4mpa den nya konfigurationen, kommer Patroni att meddela detta. Patroni kan starta om hela klustret med ett enda kommando, vilket ocks\u00e5 \u00e4r mycket bekv\u00e4mt.<\/li>\n<li>Automatisk failover fungerar och har redan hj\u00e4lpt oss.<\/li>\n<li>Uppgradering av PostgreSQL utan driftstopp f\u00f6r applikationen. F\u00f6rst m\u00e5ste replikerna uppgraderas till den nya versionen, sedan byta ledare i Patroni-klustret och uppgradera den gamla ledaren. Under detta sker n\u00f6dv\u00e4ndig testning av den automatiska failovern.<\/li>\n<\/ul>\n<p>K\u00e4lla: <a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/miro\/blog\/457326\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 PostgreSQL, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u0430\u0436\u043d\u043e \u0438 \u0447\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u0423 \u043d\u0430\u0441 \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441: 2,5 \u043c\u043b\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043c\u0438\u0440\u0443, 50\u041a+ \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c. \u0421\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 Amazone \u0432 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u0433\u0438\u043e\u043d\u0435 \u0418\u0440\u043b\u0430\u043d\u0434\u0438\u0438: \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e 100+ \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u0447\u0442\u0438 50 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26749,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35706","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 PostgreSQL, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u0430\u0436\u043d\u043e \u0438 \u0447\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sv_SE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 PostgreSQL + Patroni. \u041e\u043f\u044b\u0442 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 PostgreSQL, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u0430\u0436\u043d\u043e \u0438 \u0447\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:05:50+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-05-18T18:58:46+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Felaktig kluster PostgreSQL + Patroni. Implementerings erfarenhet | ProHoster","description":"I artikeln kommer jag att ber\u00e4tta hur vi n\u00e4rmade oss fr\u00e5gan om tillf\u00f6rlitlighet f\u00f6r PostgreSQL, varf\u00f6r det blev viktigt f\u00f6r oss och vad vi slutligen \u00e5stadkom.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 PostgreSQL + Patroni. \u041e\u043f\u044b\u0442 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f | ProHoster","og:description":"\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 PostgreSQL, \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u0430\u0436\u043d\u043e \u0438 \u0447\u0442\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.","og:url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/otkazoustojchivyj-klaster-postgresql-patroni-opyt-vnedreniya","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:05:50+00:00","article:modified_time":"2026-05-18T18:58:46+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35706","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 00:26:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:51:06","updated":"2026-01-22 00:26:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/35706","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=35706"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/35706\/revisions"}],"predecessor-version":[{"id":172654,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/35706\/revisions\/172654"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/26749"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=35706"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=35706"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=35706"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}