Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Në artikull do t'ju tregoj se si iu qasëm çështjes së tolerancës së gabimeve PostgreSQL, pse u bë e rëndësishme për ne dhe çfarë ndodhi në fund.

Ne kemi një shërbim shumë të ngarkuar: 2,5 milionë përdorues në mbarë botën, 50 mijë + përdorues aktivë çdo ditë. Serverët janë të vendosur në Amazone në një rajon të Irlandës: 100+ serverë të ndryshëm janë vazhdimisht në funksionim, nga të cilët pothuajse 50 janë me baza të dhënash.

E gjithë pjesa e pasme është një aplikacion i madh monolit me gjendje Java që mban një lidhje konstante me klientin. Kur disa përdorues punojnë në të njëjtën tabelë në të njëjtën kohë, ata të gjithë i shohin ndryshimet në kohë reale, sepse ne e shkruajmë çdo ndryshim në bazën e të dhënave. Ne kemi rreth 10 mijë kërkesa në sekondë në bazat tona të të dhënave. Në ngarkesën maksimale në Redis, ne shkruajmë 80-100 mijë kërkesa në sekondë.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Pse kaluam nga Redis në PostgreSQL

Fillimisht, shërbimi ynë punoi me Redis, një dyqan me vlerë kyçe që ruan të gjitha të dhënat në RAM-in e serverit.

Të mirat e Redis:

  1. Shpejtësia e lartë e reagimit, sepse gjithçka ruhet në kujtesë;
  2. Lehtësia e kopjimit dhe riprodhimit.

Disavantazhet e Redis për ne:

  1. Nuk ka transaksione reale. Ne u përpoqëm t'i simulonim ato në nivelin e aplikacionit tonë. Fatkeqësisht, kjo nuk funksiononte gjithmonë mirë dhe kërkonte shkrimin e një kodi shumë kompleks.
  2. Sasia e të dhënave është e kufizuar nga sasia e memories. Ndërsa sasia e të dhënave rritet, memoria do të rritet dhe, në fund, do të hasim në karakteristikat e shembullit të zgjedhur, i cili në AWS kërkon ndalimin e shërbimit tonë për të ndryshuar llojin e shembullit.
  3. Është e nevojshme të ruhet vazhdimisht një nivel i ulët latente, sepse. kemi një numër shumë të madh kërkesash. Niveli optimal i vonesës për ne është 17-20 ms. Në një nivel prej 30-40 ms, marrim përgjigje të gjata ndaj kërkesave nga aplikacioni ynë dhe degradim i shërbimit. Fatkeqësisht, kjo na ndodhi në shtator 2018, kur një nga rastet me Redis për disa arsye mori vonesë 2 herë më shumë se zakonisht. Për të zgjidhur problemin, ne e ndaluam shërbimin në mesditë për mirëmbajtje të paplanifikuar dhe zëvendësuam shembullin problematik Redis.
  4. Është e lehtë të marrësh mospërputhje të të dhënave edhe me gabime të vogla në kod dhe më pas të shpenzosh shumë kohë duke shkruar kodin për të korrigjuar këto të dhëna.

Ne morëm parasysh të këqijat dhe kuptuam se duhej të kalonim në diçka më të përshtatshme, me transaksione normale dhe më pak varësi nga vonesa. Kryer kërkime, analizoi shumë opsione dhe zgjodhi PostgreSQL.

Ne kemi lëvizur në një bazë të dhënash të re për 1,5 vjet tashmë dhe kemi zhvendosur vetëm një pjesë të vogël të të dhënave, kështu që tani po punojmë njëkohësisht me Redis dhe PostgreSQL. Më shumë informacion rreth fazave të lëvizjes dhe ndërrimit të të dhënave midis bazave të të dhënave janë shkruar në artikulli i kolegut tim.

Kur filluam të lëviznim për herë të parë, aplikacioni ynë punoi drejtpërdrejt me bazën e të dhënave dhe aksesoi masterin Redis dhe PostgreSQL. Grupi PostgreSQL përbëhej nga një master dhe një kopje me replikim asinkron. Kështu dukej skema e bazës së të dhënave:
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Zbatimi i PgBouncer

Ndërsa ne po lëviznim, produkti po zhvillohej gjithashtu: numri i përdoruesve dhe numri i serverëve që punonin me PostgreSQL u rrit, dhe filluam të na mungojnë lidhjet. PostgreSQL krijon një proces të veçantë për çdo lidhje dhe konsumon burime. Ju mund të rrisni numrin e lidhjeve deri në një pikë të caktuar, përndryshe ekziston një shans për të marrë performancën jo optimale të bazës së të dhënave. Opsioni ideal në një situatë të tillë do të ishte të zgjidhni një menaxher lidhjeje që do të qëndrojë përpara bazës.

Ne kishim dy opsione për menaxherin e lidhjes: Pgpool dhe PgBouncer. Por e para nuk e mbështet mënyrën transaksionale të punës me bazën e të dhënave, kështu që ne zgjodhëm PgBouncer.

Ne kemi vendosur skemën e mëposhtme të punës: aplikacioni ynë akseson një PgBouncer, pas të cilit janë masterat PostgreSQL dhe pas çdo masteri është një kopje me replikim asinkron.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Në të njëjtën kohë, ne nuk mund të ruanim të gjithë sasinë e të dhënave në PostgreSQL dhe shpejtësia e punës me bazën e të dhënave ishte e rëndësishme për ne, kështu që filluam të ndajmë PostgreSQL në nivelin e aplikacionit. Skema e përshkruar më sipër është relativisht e përshtatshme për këtë: kur shtoni një copëz të re PostgreSQL, mjafton të përditësoni konfigurimin PgBouncer dhe aplikacioni mund të punojë menjëherë me copëzën e re.

Dështimi i PgBouncer

Kjo skemë funksionoi deri në momentin kur i vetmi shembull i PgBouncer vdiq. Jemi në AWS, ku të gjitha rastet po funksionojnë në pajisje që vdesin periodikisht. Në raste të tilla, shembulli thjesht kalon në një pajisje të re dhe funksionon përsëri. Kjo ndodhi me PgBouncer, por u bë i padisponueshëm. Rezultati i kësaj rënie ishte mosdisponueshmëria e shërbimit tonë për 25 minuta. AWS rekomandon përdorimin e tepricës nga ana e përdoruesit për situata të tilla, e cila nuk ishte zbatuar në vendin tonë në atë kohë.

Pas kësaj, ne menduam seriozisht për tolerancën e gabimeve të grupimeve PgBouncer dhe PostgreSQL, sepse një situatë e ngjashme mund të ndodhë me çdo shembull në llogarinë tonë AWS.

Ne ndërtuam skemën e tolerancës së gabimeve PgBouncer si më poshtë: të gjithë serverët e aplikacionit hyjnë në Balancuesin e Ngarkimit të Rrjetit, pas të cilit ka dy PgBouncer. Çdo PgBouncer shikon të njëjtin master PostgreSQL të secilit copë. Nëse ndodh përsëri një përplasje e shembullit AWS, i gjithë trafiku ridrejtohet përmes një tjetër PgBouncer. Dështimi i balancuesit të ngarkesës së rrjetit ofrohet nga AWS.

Kjo skemë e bën të lehtë shtimin e serverëve të rinj PgBouncer.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Krijoni një grup të dështimit të PostgreSQL

Gjatë zgjidhjes së këtij problemi, ne shqyrtuam opsione të ndryshme: dështimi i vetë-shkruar, repmgr, AWS RDS, Patroni.

Skriptet e shkruara vetë

Ata mund të monitorojnë punën e masterit dhe, nëse dështon, të promovojnë kopjen te masteri dhe të përditësojnë konfigurimin e PgBouncer.

Përparësitë e kësaj qasjeje janë thjeshtësia maksimale, sepse ju shkruani vetë skriptet dhe kuptoni saktësisht se si funksionojnë.

Cons:

  • Masteri mund të mos ketë vdekur, përkundrazi mund të ketë ndodhur një dështim i rrjetit. Failover, i pavetëdijshëm për këtë, do të promovojë kopjen te mjeshtri, ndërsa mjeshtri i vjetër do të vazhdojë të punojë. Si rezultat, ne do të marrim dy serverë në rolin e masterit dhe nuk do të dimë se cili prej tyre ka të dhënat më të fundit të përditësuara. Kjo situatë quhet ndryshe edhe truri i ndarë;
  • Kemi mbetur pa përgjigje. Në konfigurimin tonë, master dhe një kopje, pas ndërrimit, kopja lëviz lart në master dhe ne nuk kemi më kopje, kështu që duhet të shtojmë manualisht një kopje të re;
  • Ne kemi nevojë për monitorim shtesë të operacionit të dështimit, ndërsa kemi 12 copëza PostgreSQL, që do të thotë se duhet të monitorojmë 12 grupe. Me një rritje të numrit të copëzave, duhet të mbani mend gjithashtu të përditësoni dështimin.

Failover i shkruar vetë duket shumë i ndërlikuar dhe kërkon mbështetje jo të parëndësishme. Me një grup të vetëm PostgreSQL, ky do të ishte opsioni më i lehtë, por nuk shkallëzohet, kështu që nuk është i përshtatshëm për ne.

Repmgr

Menaxheri i replikimit për grupimet PostgreSQL, i cili mund të menaxhojë funksionimin e një grupi PostgreSQL. Në të njëjtën kohë, ai nuk ka një dështim automatik jashtë kutisë, kështu që për punë do t'ju duhet të shkruani "mbështjellësin" tuaj në krye të zgjidhjes së përfunduar. Pra, gjithçka mund të dalë edhe më e ndërlikuar sesa me skenarë të shkruar vetë, kështu që ne nuk e provuam as Repmgr.

AWS RDS

Mbështet gjithçka që na nevojitet, di të krijojë kopje rezervë dhe mban një grup lidhjesh. Ka ndërrim automatik: kur masteri vdes, kopja bëhet masteri i ri dhe AWS ndryshon rekordin dns në master të ri, ndërsa replikat mund të vendosen në AZ të ndryshme.

Disavantazhet përfshijnë mungesën e rregullimeve të imta. Si shembull i akordimit të imët: rastet tona kanë kufizime për lidhjet tcp, të cilat, për fat të keq, nuk mund të bëhen në RDS:

net.ipv4.tcp_keepalive_time=10
net.ipv4.tcp_keepalive_intvl=1
net.ipv4.tcp_keepalive_probes=5
net.ipv4.tcp_retries2=3

Për më tepër, AWS RDS është pothuajse dy herë më i shtrenjtë se çmimi i shembullit të rregullt, i cili ishte arsyeja kryesore për braktisjen e kësaj zgjidhjeje.

Patroni

Ky është një shabllon python për menaxhimin e PostgreSQL me dokumentacion të mirë, dështim automatik dhe kod burimor në github.

Të mirat e Patroni:

  • Çdo parametër i konfigurimit është përshkruar, është e qartë se si funksionon;
  • Dështimi automatik funksionon jashtë kutisë;
  • E shkruar në python, dhe meqenëse ne vetë shkruajmë shumë në python, do të jetë më e lehtë për ne të merremi me problemet dhe, ndoshta, edhe të ndihmojmë zhvillimin e projektit;
  • Menaxhon plotësisht PostgreSQL, ju lejon të ndryshoni konfigurimin në të gjitha nyjet e grupit menjëherë dhe nëse grupi duhet të riniset për të aplikuar konfigurimin e ri, atëherë kjo mund të bëhet përsëri duke përdorur Patroni.

Cons:

  • Nuk është e qartë nga dokumentacioni se si të punohet saktë me PgBouncer. Edhe pse është e vështirë ta quash minus, sepse detyra e Patronit është të menaxhojë PostgreSQL, dhe si do të shkojnë lidhjet me Patroni është tashmë problemi ynë;
  • Ka pak shembuj të zbatimit të Patroni në vëllime të mëdha, ndërsa ka shumë shembuj të zbatimit nga e para.

Si rezultat, ne zgjodhëm Patroni për të krijuar një grup të dështimit.

Procesi i Zbatimit të Patroni

Përpara Patroni, ne kishim 12 copëza PostgreSQL në një konfigurim të një masteri dhe një kopjeje me replikim asinkron. Serverët e aplikacionit aksesonin bazat e të dhënave përmes Network Load Balancer, pas të cilit ishin dy instanca me PgBouncer dhe pas tyre ishin të gjithë serverët PostgreSQL.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Për të zbatuar Patroni, na duhej të zgjidhnim një konfigurim të grupit të ruajtjes së shpërndarë. Patroni punon me sisteme të ruajtjes së konfigurimit të shpërndarë si etcd, Zookeeper, Consul. Ne thjesht kemi një grup konsullor të plotë në treg, i cili funksionon në lidhje me Vault dhe ne nuk e përdorim më atë. Një arsye e shkëlqyer për të filluar përdorimin e Konsullit për qëllimin e synuar.

Si punon Patroni me Konsullin

Kemi një grup konsulli, i cili përbëhet nga tre nyje dhe një grup Patroni, i cili përbëhet nga një udhëheqës dhe një kopje (në Patroni, mjeshtri quhet udhëheqës i grupit, dhe skllevërit quhen replika). Çdo instancë e grupit Patroni vazhdimisht i dërgon Konsullit informacion për gjendjen e grupit. Prandaj, nga Konsulli gjithmonë mund të zbuloni konfigurimin aktual të grupit Patroni dhe kush është udhëheqësi për momentin.

Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Për të lidhur Patroni me Konsullin, mjafton të studioni dokumentacionin zyrtar, i cili thotë se duhet të specifikoni një host në formatin http ose https, në varësi të mënyrës se si punojmë me Konsullin dhe skemës së lidhjes, opsionalisht:

host: the host:port for the Consul endpoint, in format: http(s)://host:port
scheme: (optional) http or https, defaults to http

Duket e thjeshtë, por këtu fillojnë të metat. Me Konsullin, ne punojmë për një lidhje të sigurt përmes https dhe konfigurimi ynë i lidhjes do të duket si ky:

consul:
  host: https://server.production.consul:8080 
  verify: true
  cacert: {{ consul_cacert }}
  cert: {{ consul_cert }}
  key: {{ consul_key }}

Por kjo nuk funksionon. Në startup, Patroni nuk mund të lidhet me Konsullin, sepse gjithsesi përpiqet të kalojë përmes http.

Kodi burimor i Patroni ndihmoi në zgjidhjen e problemit. Është mirë që është shkruar në python. Rezulton se parametri pritës nuk analizohet në asnjë mënyrë, dhe protokolli duhet të specifikohet në skemë. Kështu duket për ne blloku i konfigurimit të punës për të punuar me Konsullin:

consul:
  host: server.production.consul:8080
  scheme: https
  verify: true
  cacert: {{ consul_cacert }}
  cert: {{ consul_cert }}
  key: {{ consul_key }}

konsull-shabllon

Pra, ne kemi zgjedhur ruajtjen për konfigurim. Tani duhet të kuptojmë se si PgBouncer do të ndërrojë konfigurimin e tij kur ndryshon liderin në grupin Patroni. Nuk ka përgjigje për këtë pyetje në dokumentacion, sepse. atje, në parim, puna me PgBouncer nuk përshkruhet.

Në kërkim të një zgjidhjeje, gjetëm një artikull (për fat të keq nuk e mbaj mend titullin) ku shkruhej se Сonsul-template ndihmoi shumë në çiftimin e PgBouncer dhe Patroni. Kjo na shtyu të hetojmë se si funksionon modeli i konsullit.

Doli që Consul-template monitoron vazhdimisht konfigurimin e grupit PostgreSQL në Konsul. Kur lideri ndryshon, ai përditëson konfigurimin e PgBouncer dhe dërgon një komandë për ta ringarkuar atë.

Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Një plus i madh i shabllonit është se ai ruhet si kod, kështu që kur shtoni një copëz të re, mjafton të bëni një commit të ri dhe të përditësoni shabllonin automatikisht, duke mbështetur parimin Infrastruktura si kod.

Arkitekturë e re me Patroni

Si rezultat, morëm skemën e mëposhtme të punës:
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Të gjithë serverët e aplikacionit hyjnë në balancuesin → ka dy raste të PgBouncer pas tij → në secilin shembull, lançohet Сonsul-template, i cili monitoron statusin e çdo grupi Patroni dhe monitoron rëndësinë e konfigurimit PgBouncer, i cili i dërgon kërkesa udhëheqësit aktual të çdo grupi.

Testimi manual

Ne e zbatuam këtë skemë përpara se ta nisnim në një mjedis të vogël testimi dhe kontrolluam funksionimin e ndërrimit automatik. Hapën tabelën, lëvizën ngjitësin dhe në atë moment “vranë” drejtuesin e grupit. Në AWS, kjo është aq e thjeshtë sa mbyllja e shembullit përmes tastierës.

Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Ngjitësja u kthye brenda 10-20 sekondave, dhe më pas përsëri filloi të lëvizte normalisht. Kjo do të thotë që grupi Patroni funksionoi si duhet: ndryshoi liderin, dërgoi informacionin te Сonsul dhe Сonsul-template e mori menjëherë këtë informacion, zëvendësoi konfigurimin e PgBouncer dhe dërgoi komandën për të ringarkuar.

Si të mbijetoni nën ngarkesë të lartë dhe të mbani kohën e ndërprerjes minimale?

Gjithçka funksionon në mënyrë perfekte! Por ka pyetje të reja: si do të funksionojë nën ngarkesë të lartë? Si të hapni shpejt dhe me siguri gjithçka në prodhim?

Mjedisi i testimit në të cilin kryejmë testimin e ngarkesës na ndihmon t'i përgjigjemi pyetjes së parë. Ai është plotësisht identik me prodhimin për sa i përket arkitekturës dhe ka gjeneruar të dhëna testimi që janë afërsisht të barabarta në vëllim me prodhimin. Ne vendosim të "vrasim" një nga mjeshtrat e PostgreSQL gjatë testit dhe të shohim se çfarë ndodh. Por para kësaj, është e rëndësishme të kontrolloni rrotullimin automatik, sepse në këtë mjedis kemi disa copëza PostgreSQL, kështu që do të marrim testime të shkëlqyera të skripteve të konfigurimit përpara prodhimit.

Të dyja detyrat duken ambicioze, por ne kemi PostgreSQL 9.6. A mund ta përmirësojmë menjëherë në 11.2?

Ne vendosim ta bëjmë atë në 2 hapa: së pari azhurnoni në 11.2, më pas nisni Patroni.

Përditësimi i PostgreSQL

Për të përditësuar shpejt versionin PostgreSQL, përdorni opsionin -k, në të cilin krijohen lidhje të forta në disk dhe nuk ka nevojë të kopjoni të dhënat tuaja. Në bazat 300-400 GB, përditësimi zgjat 1 sekondë.

Ne kemi shumë copëza, kështu që përditësimi duhet të bëhet automatikisht. Për ta bërë këtë, ne kemi shkruar një libër lojërash Ansible që trajton të gjithë procesin e përditësimit për ne:

/usr/lib/postgresql/11/bin/pg_upgrade 
<b>--link </b>
--old-datadir='' --new-datadir='' 
 --old-bindir=''  --new-bindir='' 
 --old-options=' -c config_file=' 
 --new-options=' -c config_file='

Është e rëndësishme të theksohet këtu se përpara se të filloni përmirësimin, duhet ta kryeni atë me parametrin -- kontrollonipër t'u siguruar që mund të përmirësoni. Skripti ynë gjithashtu bën zëvendësimin e konfigurimeve për kohëzgjatjen e azhurnimit. Skenari ynë përfundoi në 30 sekonda, që është një rezultat i shkëlqyer.

Nis Patroni

Për të zgjidhur problemin e dytë, thjesht shikoni konfigurimin Patroni. Depoja zyrtare ka një shembull konfigurimi me initdb, i cili është përgjegjës për inicializimin e një baze të dhënash të re kur filloni për herë të parë Patroni. Por meqenëse tashmë kemi një bazë të dhënash të gatshme, thjesht e hoqëm këtë seksion nga konfigurimi.

Kur filluam instalimin e Patroni në një grup tashmë ekzistues PostgreSQL dhe ekzekutimin e tij, hasëm në një problem të ri: të dy serverët filluan si udhëheqës. Patroni nuk di asgjë për gjendjen e hershme të grupit dhe përpiqet të nisë të dy serverët si dy grupime të veçanta me të njëjtin emër. Për të zgjidhur këtë problem, duhet të fshini drejtorinë me të dhëna në skllav:

rm -rf /var/lib/postgresql/

Kjo duhet të bëhet vetëm për skllavin!

Kur lidhet një kopje e pastër, Patroni krijon një udhëheqës bazë rezervë dhe e rikthen atë në kopje, dhe më pas arrin me gjendjen aktuale sipas regjistrave wal.

Një vështirësi tjetër që kemi hasur është se të gjitha grupimet PostgreSQL emërtohen si kryesore si parazgjedhje. Kur secili grup nuk di asgjë për tjetrin, kjo është normale. Por kur dëshironi të përdorni Patroni, atëherë të gjitha grupimet duhet të kenë një emër unik. Zgjidhja është ndryshimi i emrit të grupit në konfigurimin PostgreSQL.

testi i ngarkesës

Kemi nisur një test që simulon përvojën e përdoruesit në borde. Kur ngarkesa arriti vlerën tonë mesatare ditore, ne përsëritëm saktësisht të njëjtin test, ne çaktivizuam një shembull me një udhëheqës PostgreSQL. Failover automatik funksionoi siç prisnim: Patroni ndryshoi drejtuesin, Consul-template përditësoi konfigurimin e PgBouncer dhe dërgoi një komandë për të ringarkuar. Sipas grafikëve tanë në Grafana, ishte e qartë se kishte vonesa prej 20-30 sekondash dhe një sasi të vogël gabimesh nga serverët që lidhen me lidhjen me bazën e të dhënave. Kjo është një situatë normale, vlera të tilla janë të pranueshme për dështimin tonë dhe janë padyshim më të mira se koha e ndërprerjes së shërbimit.

Sjellja e Patronit në prodhim

Si rezultat, ne dolëm me planin e mëposhtëm:

  • Vendosni modelin e Konsullit në serverët PgBouncer dhe lansoni;
  • Përditësimet e PostgreSQL në versionin 11.2;
  • Ndryshoni emrin e grupit;
  • Fillimi i grupit Patroni.

Në të njëjtën kohë, skema jonë na lejon të bëjmë pikën e parë pothuajse në çdo kohë, ne mund të heqim çdo PgBouncer nga puna me radhë dhe të vendosim dhe ekzekutojmë modelin e konsullit mbi të. Kështu bëmë.

Për vendosje të shpejtë, ne përdorëm Ansible, pasi tashmë i kemi testuar të gjithë librat e lojës në një mjedis testimi dhe koha e ekzekutimit të skenarit të plotë ishte nga 1,5 në 2 minuta për çdo copëz. Ne mund të shpërndajmë gjithçka me radhë në çdo copëz pa ndërprerë shërbimin tonë, por do të na duhej të çaktivizonim çdo PostgreSQL për disa minuta. Në këtë rast, përdoruesit të dhënat e të cilëve janë në këtë copëz nuk mund të funksionojnë plotësisht në këtë moment dhe kjo është e papranueshme për ne.

Rruga për të dalë nga kjo situatë ishte mirëmbajtja e planifikuar, e cila bëhet çdo 3 muaj. Kjo është një dritare për punën e planifikuar, kur ne mbyllim plotësisht shërbimin tonë dhe përmirësojmë rastet tona të bazës së të dhënave. Kishte mbetur një javë deri në dritaren tjetër, dhe ne vendosëm të prisnim dhe të përgatiteshim më tej. Gjatë kohës së pritjes, ne gjithashtu siguruam veten: për çdo fragment PostgreSQL, ngritëm një kopje rezervë në rast të dështimit për të mbajtur të dhënat më të fundit dhe shtuam një shembull të ri për çdo copëz, i cili duhet të bëhet një kopje e re në grupin Patroni. në mënyrë që të mos ekzekutohet një komandë për fshirjen e të dhënave. E gjithë kjo ndihmoi për të minimizuar rrezikun e gabimit.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Ne rifilluam shërbimin tonë, gjithçka funksionoi siç duhej, përdoruesit vazhduan të punonin, por në grafikët vumë re një ngarkesë anormalisht të lartë në serverët e Konsullit.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Pse nuk e pamë këtë në mjedisin e testimit? Ky problem ilustron shumë mirë se është e nevojshme të ndiqet parimi i Infrastrukturës si kod dhe të rafinohet e gjithë infrastruktura, nga mjediset e testimit deri te prodhimi. Përndryshe, është shumë e lehtë të marrim problemin që kemi. Cfare ndodhi? Konsulli u shfaq fillimisht në prodhim, dhe më pas në mjediset e provës, si rezultat, në mjediset e provës, versioni i Konsullit ishte më i lartë se në prodhim. Vetëm në një nga publikimet, një rrjedhje e CPU-së u zgjidh gjatë punës me modelin e konsullit. Prandaj, ne thjesht e përditësuam Konsullin, duke e zgjidhur kështu problemin.

Rinis grupin Patroni

Megjithatë, ne kemi një problem të ri, për të cilin as që e dyshonim. Kur përditësojmë Konsullin, ne thjesht heqim nyjen e Konsullit nga grupi duke përdorur komandën e largimit të konsullit → Patroni lidhet me një server tjetër të Konsullit → gjithçka funksionon. Por kur arritëm në instancën e fundit të grupit të konsullit dhe i dërguam komandën e largimit të konsullit, të gjitha grupet Patroni thjesht u rifilluan dhe në regjistrat pamë gabimin e mëposhtëm:

ERROR: get_cluster
Traceback (most recent call last):
...
RetryFailedError: 'Exceeded retry deadline'
ERROR: Error communicating with DCS
<b>LOG: database system is shut down</b>

Grupi Patroni nuk mundi të merrte informacion rreth grupimit të tij dhe u rifillua.

Për të gjetur një zgjidhje, ne kontaktuam autorët Patroni përmes një problemi në github. Ata sugjeruan përmirësime në skedarët tanë të konfigurimit:

consul:
 consul.checks: []
bootstrap:
 dcs:
   retry_timeout: 8

Ne ishim në gjendje ta riprodhonim problemin në një mjedis testimi dhe i testuam këto opsione atje, por për fat të keq ato nuk funksionuan.

Problemi mbetet ende i pazgjidhur. Ne planifikojmë të provojmë zgjidhjet e mëposhtme:

  • Përdorni agjentin konsullor në çdo rast të grupit Patroni;
  • Rregulloni problemin në kod.

Ne e kuptojmë se ku ndodhi gabimi: problemi është ndoshta përdorimi i afatit të paracaktuar, i cili nuk anashkalohet përmes skedarit të konfigurimit. Kur serveri i fundit i Konsullit hiqet nga grupi, i gjithë grupi i Konsullit varet për më shumë se një sekondë, për shkak të kësaj, Patroni nuk mund të marrë statusin e grupit dhe rinis plotësisht të gjithë grupin.

Fatmirësisht nuk kemi hasur më gabime.

Rezultatet e përdorimit të Patroni

Pas lëshimit të suksesshëm të Patroni, ne shtuam një kopje shtesë në çdo grup. Tani në çdo grup ka një pamje të një kuorumi: një udhëheqës dhe dy kopje, për rrjetë sigurie në rast të ndarjes së trurit gjatë ndërrimit.
Failover Cluster PostgreSQL + Patroni. Përvoja e zbatimit

Patroni ka më shumë se tre muaj që punon në prodhim. Gjatë kësaj kohe, ai tashmë ka arritur të na ndihmojë. Kohët e fundit, drejtuesi i një prej grupeve vdiq në AWS, dështimi automatik funksionoi dhe përdoruesit vazhduan të punojnë. Patroni e përmbushi detyrën kryesore.

Një përmbledhje e vogël e përdorimit të Patroni:

  • Lehtësia e ndryshimeve të konfigurimit. Mjafton të ndryshoni konfigurimin në një shembull dhe ai do të tërhiqet në të gjithë grupin. Nëse kërkohet një rindezje për të aplikuar konfigurimin e ri, atëherë Patroni do t'ju njoftojë. Patroni mund të rifillojë të gjithë grupin me një komandë të vetme, e cila është gjithashtu shumë e përshtatshme.
  • Dështimi automatik funksionon dhe tashmë ka arritur të na ndihmojë.
  • Përditësimi i PostgreSQL pa ndërprerje të aplikacionit. Së pari duhet të përditësoni kopjet në versionin e ri, më pas të ndryshoni liderin në grupin Patroni dhe të përditësoni liderin e vjetër. Në këtë rast, ndodh testimi i nevojshëm i dështimit automatik.

Burimi: www.habr.com

Shto një koment