
Në raport, Andrei Borodin do të flasë se si ata morën parasysh përvojën e shkallëzimit të PgBouncer gjatë projektimit të pool-it të lidhjeve. , si e vendosën atë në prodhim. Për më tepër, do të diskutojmë se cilat funksione të pool-it do të dëshironim të shihnim në versionet e reja: na intereson jo vetëm të mbushim nevojat tona, por të zhvillojmë komunitetin e përdoruesve. .
Video:


Përshëndetje të gjithëve! Unë quhem Andrei.

Në Yandex, merrem me zhvillimin e bazave të të dhënave open source. Dhe sot tema jonë është për connection pooler-in e lidhjeve.

Nëse e dini si të emërtoni connection pooler-in në rusisht, më tregoni. Dua shumë të gjej një termin teknik të mirë që duhet të konsolidohet në literaturën teknike.
Tema është mjaft e ndërlikuar, sepse në shumë baza të dhënash, connection pooler është e integruar dhe as nuk është nevoja të dihet për të. Disa konfigurime, sigurisht, ekzistojnë kudo, por në Postgres nuk funksionon kështu. Dhe paralelisht (në HighLoad++ 2019) po zhvillohet një prezantim nga Nikolai Samokhvalov për konfigurimin e kërkesave në Postgres. Dhe kuptoj që këtu erdhën njerëz që tashmë i kanë konfiguruar kërkesat në mënyrë perfekte, dhe këta janë njerëz që përballen me probleme sistemike më të rralla, të lidhura me rrjetin dhe përdorimin e burimeve. Edhe në disa raste mund të ketë qenë mjaft e komplikuar, në kuptimin që problemet nuk ishin të dukshme.

Në Yandex ka Postgres. Në Yandex.Cloud jetojnë shumë shërbime të Yandex-it. Dhe ne kemi disa petabajt të dhënash, të cilat gjenerojnë jo më pak se një milion kërkesa në sekondë në Postgres.

Dhe ne ofrojmë një klaster mjaft tipik për të gjithë shërbimet – kjo është nodi kryesor primar, dy replika të zakonshme (një sinkronike dhe një asinkronike), kopjimi rezervë, dhe shkallëzimi i kërkesave lexuese në replikë.

Çdo nod i klasterit është një Postgres, në të cilin, përveç Postgres dhe sistemeve të monitorimit, është instaluar gjithashtu connection pooler. Connection pooler përdoret për fencing dhe për qëllimin e tij kryesor.

Cila është qëllimi kryesor i connection pooler?

Në Postgres është pranuar një model procesi për të punuar me bazën e të dhënave. Kjo do të thotë se një lidhje është një proces, një backend Postgres. Dhe në këtë backend ka shumë cache të ndryshme, të cilat janë mjaft të kushtueshme për t'u bërë të ndryshme për lidhje të ndryshme.

Për më tepër, në kodin e Postgres ka një masiv, i quajtur procArray. Ai përmban të dhëna kryesore mbi lidhjet rrjetërore. Dhe pothuajse të gjitha algorithmet që trajtojnë procArray kanë komplekse lineare, ata kalojnë përmes gjithë masivit të lidhjeve rrjetërore. Kjo është një cikël mjaft i shpejtë, por me numrin e madh të lidhjeve rrjetërore hyrëse, gjithçka bëhet paksa më e shtrenjtë. Dhe kur gjithçka bëhet pak më e shtrenjtë, në fund mund të paguani një çmim shumë të lartë për numrin e madh të lidhjeve rrjetërore.

Ekzistojnë 3 qasje të mundshme:
- Nga ana e aplikacionit.
- Nga ana e bazës së të dhënave.
- Dhe në mes, dmth. të gjitha kombinimet e mundshme.
Fatkeq, pooler i integruar aktualisht është në fazën e zhvillimit. Shokët në kompaninë PostgreSQL Professional kryesisht po merren me këtë. Kur do të dalë, është e vështirë të parashikohet. Dhe në të vërtetë, për zgjedhjen e arkitektit kemi dy zgjidhje. Kjo është pool aplikacioni dhe pool proxy.

Pool-i i aplikacionit është mënyra më e thjeshtë. Dhe pothuajse të gjithë drejtorët e klientëve ofrojnë një mënyrë: miliardet e lidhjeve tuaja në kod të përfaqësohen si disa dhjetëra lidhje në bazën e të dhënave.

Këtu shfaqet problemi që në një moment dëshironi të skaloni backend-in, dëshironi ta shpërndani atë në disa makina virtuale.

Më pas, e kuptoni se keni gjithashtu disa zona disponueshmërie, disa qendra të të dhënave. Dhe qasja me pool-in në anën e klientit çon në numra të mëdhenj. Të mëdhenj do të thotë rreth 10,000 lidhje. Ky është kufiri që mund të funksionojë normalisht.

Nëse flasim për poolerët e proxy, ka dy pooler që dinë të bëjnë shumë gjëra. Ato nuk janë vetëm poolerë. Ato janë pooler dhe një funksionalitet të mrekullueshëm. Kjo është dhe .
Por fatke, kjo funksionalitet shtesë nuk është e nevojshme për të gjithë. Dhe kjo çon në faktin se poolers mbështet vetëm pooling sesionesh, dmth një klient të ardhur, një klient të dalë në bazën e të dhënave.
Për ne, kjo nuk përshtatet aq mirë, prandaj ne përdorim PgBouncer, i cili implementon pooling transaksionesh, dmth lidhjet e serverit i përputhen lidhjeve klientëve vetëm për kohën e transaksionit.

Dhe për ngarkesën tonë – është e vërtetë. Por ka disa probleme.
Problemet fillojnë kur dëshironi të diagnostikoni një sesion, sepse të gjitha lidhjet e ardhshme janë lokale. Të gjitha erdhën nga loopback dhe siç e keni kuptuar, është e vështirë të gjurmohet sesioni.

Sigurisht, mund të përdorni application_name_add_host. Ky është një mënyrë nga ana e Bouncer për të shtuar IP-në në application_name. Por application_name vendoset me një lidhje shtesë.

Në këtë grafik, ku linja e verdhë tregon kërkesat reale, ndërsa linja blu – kërkesat që hyjnë në bazë. Dhe kjo diferencë – është pikërisht vendosja e application_name, e cila nevojitet vetëm për gjurmim, por nuk është krejtësisht pa kosto.

Për më tepër, në Bouncer nuk mund të kufizoni një pool, domethënë numrin e lidhjeve me bazën e të dhënave për një përdorues të caktuar, në një bazë të caktuar.

Çfarë ndikimi ka kjo? Keni një shërbim të ngarkuar, të shkruar në C++ dhe afër tij një shërbim të vogël në node, i cili nuk bën asgjë të keqe me bazën, por drejtuesi i tij del nga kontrolli. Ai hap 20,000 lidhje, ndërsa gjithë e tjerë presin. Keni madje kod të mirë.

Natyrisht, kemi shkruar një patch të vogël për Bouncer, i cili shtoi këtë cilësim, domethënë kufizimin e klientëve në pool.

Kjo mund të bëhej në anën e Postgres, domethënë, rolet në bazën e të dhënave të kufizoheshin me numrin e lidhjeve.

Por atëherë humbni mundësinë për të kuptuar pse nuk keni lidhje me serverin. PgBouncer nuk transmeton gabimin e lidhjes, ai gjithmonë kthen të njëjtin informacion. Dhe nuk mund të kuptoni: ndoshta keni ndryshuar fjalëkalimin, ndoshta thjesht baza ka rënë, ndoshta ka ndodhur diçka tjetër. Por nuk ka diagnostikim. Nëse seanca nuk mund të vendoset, nuk do të dini pse nuk mund të bëhet.

Në një moment të caktuar, shikoni grafikat e aplikacionit dhe shihni që aplikacioni nuk funksionon.

Shikoni në majë dhe shihni se Bouncer është njëqindsh. Kjo është një pikë kthese në jetën e shërbimit. Ju kuptoni se keni përgatitur për zgjerimin e bazës së të dhënave brenda një viti e gjysmë, por tani duhet të zmadhoni pooler-in.

Kemi arritur në përfundimin se na nevojiten më shumë PgBouncer.

Përmirësuam pak Bouncer-in.

Dhe e bëmë që të mund të ngrihen disa Bouncers me ripërdorimin e portit TCP. Tani sistemi operativ përcakton automatikisht lidhjet TCP të hyrjes mes tyre me round-robin.

Kjo është e padukshme për klientët, pra, gjithçka duket sikur keni një Bouncer, por ka një fragmentim të lidhjeve idle ndërmjet Bouncers-ve të aktivizuar.

Në një moment, mund të vëreni se këto 3 Bouncers po konsumojnë secila 100% të një bërthame. Ju nevojiten mjaft Bouncers. Pse?

Sepse keni TLS. Keni një lidhje të enkriptuar. Dhe nëse benchmarkoni Postgres me TLS dhe pa TLS, do të zbuloni se numri i lidhjeve të vendosura bie pothuajse në dy renditje me aktivizimin e enkriptimit, sepse dorëzimi TLS konsumon burime të procesorit.

Në krye mund të shihni një numër të konsiderueshëm funksionesh kriptografike që realizohen gjatë valës së lidhjeve të ardhshme. Duke qenë se primary ynë mund të kalojë midis zonave të disponueshmërisë, vala e lidhjeve të ardhshme është një situatë mjaft tipike. Kjo do të thotë se për ndonjë arsye primary-i i vjetër ishte i paqëndrueshëm, e gjithë ngarkesa iu dërgua një qendrë tjetër të të dhënave. Të gjithë ata do të vijnë njëherësh për të përshëndetur TLS.

Dhe një numër i madh i handshakëve TLS mund të mos përshëndetin më Bouncer-in, por ta ngushtojnë atë. Për shkak të vonesës, vala e lidhjeve të ardhshme mund të bëhet e pandërprerë. Nëse keni retry në bazë pa backoff eksponencial, ato do të vijnë përsëri dhe përsëri si një valë koherente.

Ky është një shembull i 16 PgBouncer që ngarkojnë 16 bërthama në 100%.

Kemi arritur në PgBouncer në kaskadë. Kjo është konfigurata më e mirë që mund të arrijmë nën ngarkesën tonë me Bouncer. Bouncers e jashtme na shërbejnë për handshakë TCP, ndërsa Bouncers e brendshme shërbejnë për pooling real, për të mos fragmentuar shumë lidhjet e jashtme.

Në këtë konfigurim, një restart i qetë është i mundur. Mund të restaërtosh këta 18 Bouncers një nga një. Por mbajtja e një konfigurimi të tillë është mjaft e vështirë. Administratorët e sistemeve, DevOps dhe ata që vërtet mbajnë përgjegjësi për këtë server nuk do të jenë shumë të kënaqur me këtë skemë.

Duket se, mund të promovojmë të gjitha përmirësimet tona në open source, por Bouncer nuk mbështetet shumë mirë. Për shembull, mundësia për të nisur disa PgBouncers në një port të vetëm u angazhua një muaj më parë. Ndërsa pull request për këtë funksionalitet ishte para disa vitesh.

Ose një shembull tjetër. Në Postgres, ju mund të anuloni një kërkesë në përpunim duke dërguar një sekret në një lidhje tjetër pa identifikim të tepërt. Por disa klientë dërgojnë thjesht TCP-reset, pra ndërpresin lidhjen rrjet. Çfarë do të bëjë atëherë Bouncer? Ai nuk do të bëjë asgjë. Ai do të vazhdojë të ekzekutojë kërkesën. Nëse keni marrë një numër të madh lidhjesh, të cilat me kërkesa të vogla kanë ngarkuar bazën, thjesht ndarja e lidhjes nga Bouncer do të jetë e pamjaftueshme, duhet të përfundojnë gjithashtu ato kërkesa që po ekzekutohen në bazë.
Kjo është patch-uar dhe kjo problematikë ende nuk është integruar në upstream të Bouncer-it.

Dhe kështu arritëm në përfundimin se na nevojitet një connection pooler, i cili do të zhvillohet, do të pritet, dhe ku do të jetë e mundur të rregullojmë problematikat shpejt, dhe sigurisht, që duhet të jetë multi-thread.

Multithreading e kemi vendosur si një qëllim kryesor. Na nevojitet që të përballojmë mirë flukset e lidhjeve TLS që hyjnë.
Për këtë na duhej të zhvillonim një bibliotekë të veçantë, e cila quhet Machinarium, e cila është e destinuar për të përshkruar gjendjet e makinës së lidhjes rrjetit si një kod të renditur. Nëse shikoni në kodin burimor libpq, do të shihni thirrje mjaft komplekse, të cilat mund t'ju kthejnë një rezultat dhe të thonë: "Më thirri pak më vonë. Tani kam IO, por, kur IO të kalojë, kam ngarkesë për procesorin." Dhe kjo është një skemë shumënivelëshe. Ndërveprimi rrjetor zakonisht përshkruhet si një makinë gjendjesh. Një mori rregullash si "Nëse më parë kam marrë një krye paketi me madhësi N, tani pres N byte", "Nëse kam dërguar paketën SYNC, tani pres një paketë me të dhëna mbi rezultatin." Kështu krijohet një kod mjaft kompleks, si të ishte një labirint i transformuar në një shtrirje të drejtpërdrejtë. Ne e bëmë që në vend të një makine gjendjesh, programuesi të përshkruajë rrugën kryesore të ndërveprimit si kod të zakonshëm imperativ. Thjesht, në këtë kod imperativ, duhet të fusni vende ku sekuenca e ekzekutimit duhet të ndërpritet duke pritur për të dhëna nga rrjeti, duke i kaluar kontekstin e ekzekutimit një korutine tjetër (thread-i i gjelbër). Ky qasje është e ngjashme me atë që rruga më e pritur në labirint e shkruajmë njëra pas tjetrës, dhe pastaj shtojmë dega.

Në përfundim, kemi një rrjedhë që bën TCP accept dhe me round-robin transferon lidhjet TPC në shumë punëtorë.
Kjo bën që çdo lidhje klienti të punojë gjithmonë në një procesor. Dhe kjo e bën atë më të favorshme për cache.
Për më tepër, kemi bërë disa përmirësime në grumbullimin e paketimeve të vogla në një paketë të madhe për të lehtësuar sistemin TCP-stack.

Gjithashtu, kemi përmirësuar pooling-un transaksional në mënyrë që Odyssey, kur është e konfiguruar, mund të dërgojë CANCEL dhe ROLLBACK në rast të ndërprerjes së lidhjes së rrjetit, domethënë, nëse askush nuk po pret për një kërkesë, Odyssey do t'i thotë bazës që të mos përpiqet të ekzekutojë atë kërkesë që mund të shpenzojë burime të çmuara.
Dhe, sa më shumë të jetë e mundur, ne ruajmë lidhjet për një klient të njëjtë. Kjo parandalon rivendosjen e application_name_add_host. Nëse është e mundur, ne nuk kemi rivendosje shtesë të parametrave që nevojiten për diagnostikim.

Ne jemi të angazhuar në shërbim të Yandex.Cloud. Nëse përdorni managed PostgreSQL dhe keni instaluar connection pooler, mund të krijoni replikim logjik jashtë, që do të thotë se mund të largohemi nga ne, nëse dëshironi, përmes replikimit logjik. Bouncer nuk do ta japë rrjedhën e replikimit logjik përjashta.

Ky është një shembull i konfigurimit të replikimit logjik.

Për më tepër, kemi mbështetje për replikimin fizik jashtë. Në Cloud, ky është, natyrisht, i pamundur, sepse në atë rast klasteri do të japë shumë informacion për veten. Por në instalimet tuaja, nëse keni nevojë për replikim fizik përmes connection pooler në Odyssey, kjo është e mundur.

Në Odyssey kemi monitorim plotësisht kompatibil me PgBouncer. Kemi një konsolë të njëjtë që ekzekuton pothuajse të njëjtat komanda. Nëse ndonjë gjë mungon, dërgoni pull request, ose të paktën një issue në GitHub, do ta plotësojmë komandën e nevojshme. Por funksionaliteti kryesor i konsolës PgBouncer tashmë e kemi.

Dhe, sigurisht, kemi forwarding të gabimeve. Ne do t'ju kthejmë atë gabim që raportoi baza. Do të merrni informacion se pse nuk po arrini në bazë, dhe jo vetëm se nuk jeni duke u lidhur.

Kjo mundësi është e shkëputur në rast se ju nevojitet përputhshmëria 100% me PgBouncer. Ne mund të veprojmë si Bouncer, vetëm për rastin e nevojës.
Zhvillimi
Disa fjalë mbi kodin burimor të Odyssey.

Për shembull, ekzistojnë komandat "Pause / Resume". Ato zakonisht përdoren për të përditësuar bazën e të dhënave. Nëse ju nevojitet të përditësoni Postgres, mund ta ndërprisni atë në pool-in e lidhjeve, të bëni pg_upgrade, e më pas ta rinisni. Dhe nga ana e klientit do të duket si të ishte baza e të dhënave në një ndalim të përkohshëm. Kjo funksionalitet është sjellë nga njerëzit në komunitet. Nuk është bërë bashkë siç duhet akoma, por shumë shpejt do të jetë. (Tashmë është bërë bashkë)

— tashmë është bërë bashkë
Për më tepër, një nga funksionet e reja në PgBouncer është mbështetja për autentikimin SCRAM, të cilin gjithashtu e solli një person që nuk punon në Yandex.Cloud. Të dyja janë funksionalitete komplekse dhe të rëndësishme.

Prandaj, do të doja të flas për atë nga çfarë është e bërë Odyssey, ndoshta ju gjithashtu dëshironi të shkruani pak kode tani.
Ju keni një bazë të përllogaritur Odyssey, e cila mbështetet në dy biblioteka kryesore. Biblioteka Kiwi është një realizim i protokollit të mesazheve të Postgres. Kështu, proto 3 natyror në Postgres janë mesazhet standarde me të cilat mund të komunikojnë front-endet dhe back-endet. Ato janë realizuar në bibliotekën Kiwi.
Biblioteka Machinarium është një bibliotekë për realizimin e rrjedhave. Një fragment i vogël i këtij Machinarium është shkruar në assembler. Por, mos u frikësoni, aty ka vetëm 15 rreshta.

Arkitektura e Odyssey. Ka një makinë kryesore, në të cilën janë aktivizuar coroutines. Në këtë makinë realizohet prania e lidhjeve TCP të ardhshme dhe shpërndarja e tyre te punëtorët.
Brenda një punëtori mund të punojë një trajtues për disa klientë. Po ashtu, në rrjedhën kryesore rrotullohen konsolën dhe përpunimi i detyrave crone për të fshirë lidhjet që nuk janë më të nevojshme në pool.

Për testimin e Odyssey përdoret seti standard i testeve të Postgres. Thjesht aktivizojmë install-check përmes Bouncer dhe Odyssey, dhe marrim një div të null. Atje disa teste që kanë të bëjnë me formatimin e datave nuk kalojnë në mënyrë të njëjtë në Bouncer dhe Odyssey.
Përveç kësaj, ka shumë driver-a që kanë testimin e tyre. Dhe testet e tyre i përdorim për të testuar Odyssey.

Përveç kësaj, për shkak të konfigurimit tonë kaskad, na duhet të testojmë kombinime të ndryshme: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey për të qenë të sigurt se, nëse Odyssey gjendet në ndonjë nga pjesët e kaskadës, ai vazhdon të funksionojë ashtu siç e presim.
Grapa

Ne përdorim Odyssey në prodhim. Dhe do të ishte e pa drejtë të thosha se gjithçka funksionon thjesht. Jo, pra, po, por jo gjithmonë. Për shembull, në prodhim gjithçka funksiononte vetëm, pastaj erdhën miqtë tanë nga PostgreSQL Professional dhe thanë se kishe një memory leak. Ata vërtet ishin, ne i korrigjuam. Por ishte e thjeshtë.

Më pas zbuluam se në connection pooler kishte lidhje TLS hyrëse dhe lidhje TLS dalëse. Dhe në lidhje nevojiten çertifikata klienti dhe çertifikata serveri.
Certifikatat e serverëve Bouncer dhe Odyssey rilexohen nga pcache, por certifikatat e klientëve nuk duhet rilexuar nga pcache, sepse Odyssey ynë i shkallëzueshëm përfundimisht përballet me performancën sistemore të leximit të këtij certifikati. Kjo ishte një surprizë për ne, sepse nuk ndodhi menjëherë. Fillimisht, ai u shkallëzua në mënyrë lineare, dhe pas 20,000 lidhjeve të koheve të njëkohshme, kjo problematikë u shfaq.

Metoda e Autentifikimit të Pjesshëm – është mundësia për t'u autentifikuar me mjete të integrare të Linux. Në PgBouncer, ajo realizohet në mënyrë që të ketë një rrjedhë të veçantë për të pritur përgjigjen nga PAM dhe ka rrjedhën kryesore PgBouncer, e cila shërben lidhjen e tanishme dhe mund t'i kërkojë atyre të jetojnë në rrjedhën PAM.
Ne nuk e realizuam këtë për një arsye të thjeshtë. Ne kemi shumë rrjedha. Pse na nevojitet?
Si pasojë, kjo mund të krijojë probleme pasi, nëse keni autentifikim PAM dhe pa autentifikim PAM, një valë e madhe e autentifikimit PAM mund të vonojë ndjeshëm autentifikimin pa PAM. Kjo është një nga ata gjëra që nuk e kemi korrigjuar. Por nëse dëshironi ta korrigjoni, mund të merret me këtë.

Një tjetër problem ishte se kemi një proces që pranon të gjitha lidhjet e ardhshme. Pastaj, ato dërgohen në grupin e punës, ku do të ndodhi TLS handshake.
Si rezultat, nëse keni një valë koherente prej 20,000 lidhjeve të rrjetit, të gjitha do të pranohen. Dhe në anën e klientit, libpq do të fillojë të regjistrojë kohët e pritjes. Për default, duket se aty është vendosur 3 sekonda.
Nëse të gjitha ato nuk mund të hyjnë në bazë njëkohësisht, atëherë ato nuk mund të hyjnë, sepse e gjithë kjo mund të mbulohet me një retry jo eksponencial.
Arritëm në përfundimin se kopjuam këtu skemën nga PgBouncer, duke pasur parasysh se kemi një kufizim të numrit të lidhjeve TCP, të cilave u bëjmë pranimin.
Nëse ne shohim se po pranojmë lidhjet, dhe ato përfundimisht nuk arrijnë të realizojnë handshake, i vendosim ato në radhë për të mos shpenzuar burimet e procesorit. Kjo çon në atë që handshake-i njëkohësisht nuk mund të bëhet për të gjitha lidhjet që janë pranuar. Por të paktën dikush do të hyjë në bazë, edhe nëse ngarkesa është mjaft e lartë.
Plani i Rrugës
Çfarë do të donim të shihnim në të ardhmen nga Odyssey? Çfarë jemi të gatshëm të zhvillojmë vetë dhe çfarë presim nga komuniteti?

Në gusht 2019.
Këtu është si dukej roadmap Odyssey në gusht:
- Ne dëshironim autentifikimin SCRAM dhe PAM.
- Ne dëshironim të çonim kërkesat e leximit në standby.
- Do ishte e dëshirueshme një restart online.
- Dhe mundësia për të bërë një pauzë në server.

Gjasat e këtij roadmap janë realizuar, përfshirë gjysmën e saj nga ne. Dhe kjo është mirë. Prandaj, le të diskutojmë për atë që ka mbetur dhe të shtojmë disa më shumë.

? У нас есть реплики, которые без выполнения запросов будут просто греть воздух. Они нам необходимы для обеспечения failover и switchover. В случае проблем в одном из дата-центре хотелось бы их занять какой-то полезной работой. Потому что те же самые центральные процессоры, ту же самую память мы не можем сконфигурировать по-другому, потому что иначе не будет работать репликация.

Në tërësi, në Postgres, që nga versioni 10, ekziston mundësia për të specifikuar gjithashtu session_attrs gjatë lidhjes. Ju mund të listoni të gjitha hostet e databazës në lidhje dhe të thoni se përse po hyni në databazë: për të shkruar ose vetëm për të lexuar. Dhe drivari do të zgjedhë hostin e parë sipas listës që i pëlqen më shumë, i cili plotëson kërkesat e session_attrs.

Por problemi i këtij qasje është se nuk kontrollon vonesën e replikimit. Mund të keni ndonjë replikë që ka mbetur prapa për një kohë të papranueshme për shërbimin tuaj. Për të realizuar kërkesat e leximit në replikë në mënyrë funksionale, në thelb, na nevojitet të mbështesim në Odyssey mundësinë që të mos funksionojë kur leximi nuk është i mundur.
Odyssey duhet të kërkojë herë pas here në bazë dhe të pyetë për distancën e replikimit nga primary. Nëse arrin një vlerë kufi, nuk duhet të lejojë kërkesa të reja në bazë, duke i thënë klientit se duhet të ri-iniciojë lidhjet dhe ndoshta të zgjedhë një host tjetër për të kryer kërkesat. Kjo do të ndihmojë bazën që të rikuperojë më shpejt vonesën e replikimit dhe të kthehet sërish në përgjigje të kërkesave.
Koha e zbatimit është e vështirë të përcaktohet, sepse është open source. Por, shpresoj që të mos jenë 2.5 vjet si kolegët e PgBouncer. Këtë funksionalitet do të doja ta shihja në Odyssey.

Tani mund të krijoni prepared statement në dy mënyra. Së pari, mund të kryeni komandën SQL, konkretisht "prepared". Për të kuptuar këtë komandë SQL, duhet të mësojmë të kuptojmë SQL nga ana e Bouncer. Kjo do të ishte mbi përmasat, sepse na nevojitet një parser i plotë. Nuk mund të analizojmë çdo komandë SQL.
Por drejtim, ekziston një prepared statement në nivelin e protokollit të mesazheve në proto3. Dhe ky është momenti kur informacioni për krijimin e një prepared statement vjen në një format të strukturuar. Ne mund të mbështesim kuptimin se në një lidhje serveri, klienti kërkoi të krijojë prepared statements. Edhe nëse transaksioni përfundon, ne duhet të mbajmë ende lidhshmërinë midis serverit dhe klientit.
Por këtu lind një mosmarrëveshje në dialog, sepse dikush flet për nevojën për të kuptuar se cilat prepared statements krijoi klienti dhe për të ndarë lidhjen e serverit mes të gjithë klientëve që krijuan këtë lidhje serveri, pra, ata që krijuan një të tillë prepared statement.
Andres Freund tha se nëse ju vjen një klient që tashmë ka krijuar një të tillë prepared statement në një lidhje tjetër serveri, atëherë krijojeni për të. Por, duket se është paksa e gabuar të ekzekutoni kërkesa në bazë të të dhënave në vend të klientit, megjithatë nga këndvështrimi i zhvilluesit që shkruan protokollin e ndërveprimit me bazën e të dhënave, do të ishte e dobishme nëse thjesht do t'i jepeshin një lidhje rrjetore që përmban një kërkesë të tillë të përgatitur.

Dhe një funksion tjetër që na nevojitet për t'u realizuar. Aktualisht kemi monitorim që është i pajtueshëm me PgBouncer. Mund të kthejmë mesataren e kohës së ekzekutimit të kërkesës. Por mesatarja është si temperatura mesatare në spital: disa janë të ftohtë, disa të ngrohtë - mesatarisht të gjithë janë të shëndetshëm. Kjo nuk është e vërtetë.
Na nevojitet të realizojmë mbështetje për percentilet, të cilat do të tregojnë se ekzistojnë kërkesa të ngadalta që po shpenzojnë burime dhe do ta bëjnë monitorimin më të pranueshëm.

E rëndësishmja është se dëshirojmë versionin 1.0 (versioni 1.1 tashmë ka dalë). Problemi është se aktualisht Odyssey është në versionin 1.0rc, pra release candidate. Të gjitha problemet që përmenda janë zgjidhur me këtë version, përveç memory leak.
Çfarë do të thotë për ne versioni 1.0? Ne e hedhim Odyssey në bazat tona. Ai tashmë po funksionon në bazat tona, por kur të arrijë në pikën e 1,000,000 kërkesave në sekondë, atëherë mund të themi se kjo është versioni i lëshuar dhe është versioni që mund të quhet 1.0.
Në komunitet disa njerëz kërkuan që në versionin 1.0 të kishte gjithashtu pauzë dhe SCRAM. Por kjo do të thotë se do na duhej të lëshonim një version të ardhshëm në prodhim, pasi as SCRAM e as pauza nuk janë akoma të bashkuara. Por, me shumë gjasa, ky çështje do të zgjidhet mjaft shpejt.

Po pres kërkesat tuaja për bashkim. Po ashtu, do doja të dëgjoj se çfarë probleme keni me Bouncer. Le të diskutojmë për to. Ndoshta mund të realizojmë disa funksione që ju nevojiten.
Këtu përfundon pjesa ime, do doja të dëgjoj ju. Faleminderit!
Pyetje
Nëse vendos emrin tim të aplikacionit, do të kalojë saktë, duke përfshirë edhe në transaction pooling në Odyssey?
Në Odyssey apo në Bouncer?
Në Odyssey. Në Bouncer kalon.
Do ta bëjmë setin.
Dhe nëse lidhja ime aktuale do të lëvizë mes lidhjeve të tjera, a do të kalojë?
Ne do të realizojmë një set të të gjitha parametrave që janë të listuar. Nuk mund të them nëse në këtë listë është application_name. Më duket se e kam parë atje. Do të vendosim të gjithë parametrat e njëjtë. Me një kërkesë atje do të bëjë gjithçka që ishte vendosur nga klienti gjatë nisjes.
Faleminderit, Andrei, për prezantimin! Ishte një prezantim i shkëlqyer! Jam i lumtur që Odyssey po zhvillohet gjithnjë e më shpejt. Uroj që kjo të vazhdojë. Ne tashmë ju kemi kërkuar që të kemi një lidhje multi data-source, për t'i mundësuar Odyssey të lidhet njëkohësisht me baza të ndryshme të të dhënave, dmth. master slave, dhe pastaj automatikisht pas një failover të lidhë me masterin e ri.
Po, duket se e mbaj mend këtë diskutim. Tani ka disa storage. Por nuk ka kalime mes tyre. Ne duhet të monitorojmë serverin nga ana jonë, që ai të jetë akoma në funksionim dhe të kuptojmë se ka ndodhur një failover, kush do ta thërrasë pg_recovery. Kam një mënyrë standarde për të kuptuar se nuk kemi ardhur në master. Dhe ne duhet të kuptojmë ndonjëherë nga gabimet, apo jo? Pra, ideja është interesante, ajo po diskutohet. Shkruani më shumë komente. Nëse keni duar punuese që dinë C, atëherë është thjesht fantastike.
Pyetja e shtrirjes për replikat na intereson gjithashtu, sepse duam ta bëjmë adoptimin e klastereve të replikimit sa më të thjeshtë për zhvilluesit e aplikacioneve. Por këtu do të doja më shumë komente, dmth. si të bëhet saktësisht, si ta bëjmë mirë.
Pyetja ka të bëjë edhe me replikat. Pra, keni një master dhe disa replika. Është e qartë se në replika bëhet ndalesë më rrallë sesa në master për lidhjet, sepse ato mund të kenë dallime. Keni thënë që dallimi në të dhëna mund të jetë i tillë që nuk do të plotësojë biznesin tuaj dhe nuk do të shkoni atje derisa të riplikohet. Nëse keni qëndruar për një kohë të gjatë duke mos shkuar atje dhe më pas filloni të shkoni, të dhënat që nevojiten nuk do të jenë menjëherë të disponueshme. Pra, nëse ne vazhdimisht shkojmë te master, atje cache është i ngrohur, ndërsa në replikë cache është pak më i pasaktë.
Po, kjo është e vërtetë. Në pcache nuk do të ketë blloqe të dhënash që dëshironi, në real cache nuk do të ketë informacion mbi tabelat që dëshironi, në planet nuk do të ketë kërkesa të shqyrtuara, në përgjithësi nuk do të ketë asgjë.
Dhe kur keni një grup të caktuar, dhe i shtoni atje një replikë të re, derisa ajo të fillojë, në të është situata e keqe, domethënë ajo po rrit cache-in e saj.
E kuptojnë idenë. Qasja e duhur do të ishte të lançonim një përqindje të vogël të kërkesave fillimisht në replikë, që do të ngrohë cache-in. Thënë ndryshe, kemi një kusht se duhet të jemi maksimumi 10 sekonda pas masterit. Dhe ky kusht të aktivizohet jo njëherë, por gradualisht për disa klientë.
Po, rritni peshën.
Kjo është një ide e mirë. Por së pari duhet të realizohet ky çaktivizim. Së pari duhet të ndalemi dhe pastaj të mendojmë se si të aktivizohemi. Kjo është një funksion shumë i mirë për të kaluar ngadalë në aktivizim.
Ka një opsion të tillë në nginx fillimisht ngadalë në klaster për serverin. Dhe ai gradualisht rrit ngarkesën.
Po, ide e shkëlqyer, do ta provojmë kur të arrijmë atje.
Burimi: habr.com
