Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Sot, disponueshmëria e lartë e shërbimeve është e nevojshme gjithmonë dhe kudo, jo vetëm në projektet e mëdha dhe të shtrenjta. Faqe të përkohshme që tregojnë "Na vjen keq, po kryhet mirëmbajtje" ende ekzistojnë, por zakonisht shkaktojnë një buzëqeshje përbuzëse. Shtoni këtu jetën në re, kur për të nisur një server shtesë mjafton një thirrje në API, pa nevojën që të mendoni për operimin e "harduerit". Dhe nuk mbeten justifikime përse një sistem kritik nuk është ndërtuar me besueshmëri duke përdorur teknologji klastri dhe rezervimi.

Do t'ju tregojmë se cilat zgjidhje kemi shqyrtuar për të siguruar besueshmërinë e bazave të të dhënave në shërbimet tona dhe çfarë kemi arritur. Përveç kësaj, do të ofrojmë një demo me përfundime të thella.

Legacy në arkitekturën e disponueshmërisë së lartë

Kjo është më mirë e dukshme në zhvillimin e sistemeve të ndryshme opensource. Zgjidhjet e vjetra ishin të detyruara të shtonin teknologjitë e disponueshmërisë së lartë për shkak të rritjes së kërkesës. Dhe cilësia e tyre ishte e ndryshme. Zgjidhjet e brezit të ri vendosin disponueshmërinë e lartë në bazë të arkitekturës së tyre. Për shembull, MongoDB pozicionon klasterin si opsionin kryesor të përdorimit. Klasteri shkallëzohet horizontalisht, që është një avantazh i fortë konkurrues i kësaj SGBD.

Të kthehemi te PostgreSQL. Ky është një nga projektet open source më të njohura dhe më të vjetra, me versionin e parë që u lançua në vitin 1995. Ekipi i projektit për një kohë të gjatë nuk e konsideroi disponueshmërinë e lartë si një detyrë që duhej të zgjidhej nga ana e sistemit. Prandaj, teknologjia e replikimit për krijimin e kopjeve të dhënave u bë pjesë e sistemit vetëm në versionin 8.2 në vitin 2006, por ajo ishte skenari i skedarit (log shipping). Në vitin 2010, në versionin 9.0 u prezantua replikimi në rrjedhë, i cili është baza për krijimin e klastereve të ndryshme. Kjo, në të vërtetë, i befason njerëzit që njohin PostgreSQL pas Enterprise SQL ose moderneve NoSQL - zgjidhja standarde nga komuniteti është thjesht një çift master-replica me replikim sinkron ose asinkron. Në të njëjtën kohë, në stok, kalimi i masterit bëhet manualisht, dhe çështja e kalimit të klientëve gjithashtu ofrohet për t'u zgjidhur vetë.

Si vendosëm të krijojmë një PostgreSQL të besueshëm dhe çfarë zgjodhëm për këtë

Megjithatë, PostgreSQL nuk do të ishte kaq popullor po të mos ishte numri i madh i projekteve dhe mjeteve që ndihmojnë në ndërtimin e një zgjidhjeje të qëndrueshme që nuk kërkon vëmendje të vazhdueshme. Në cloud Zgjidhjet Cloud të Mail.ru (MCS) që nga fillimi i DBaaS janë disponibilizuar serverë të veçantë PostgreSQL dhe grupe master-replikë me replikim asinkron.

Natyrisht, ne donim ta thjeshtonim jetën e gjithkujt dhe ta bëjmë të mundshëm një instalim PostgreSQL që mund të ishte baza e shërbimeve me kapacitet të lartë, pa pasur nevojë të vëzhgohej vazhdimisht dhe të zgjohej natën për ta aktivizuar. Në këtë segment ka zgjidhje të vjetra të provuara dhe një brez të rinj utilitarësh që përdorin arritjet më të fundit.

Sot, problemi i disponueshmërisë së lartë nuk është thjesht rezervimi (kjo është e qartë), por konsensusi — algoritmi për zgjedhjen e liderit (Leader election). Njëherë e një kohë, aksidentet e mëdha ndodhin jo për shkak të mungesës së serverëve, por për problemet me konsensusin: nuk është zgjedhur një lider i ri, janë shfaqur dy liderë në dataqendrat të ndryshme, etj. Një shembull është aksidenti në klasterin MySQL të Github — ata shkruan një postmortem të detajuar.

Baza matematikore në këtë çështje është shumë serioze. Nga njëra anë, ka teoremën CAP, e cila vendos kufizime teorike mbi mundësitë e ndërtimit të zgjidhjeve HA, ndërsa nga ana tjetër janë algoritmet e provuara matematikisht për definimin e konsensusit, siç janë Paxos dhe Raft. Në bazë të kësaj, ekzistojnë disa DCS (sisteme të decentralizuar të konsensusit) mjaft të njohura — Zookeeper, etcd, Consul. Prandaj, nëse sistemi i marrjes së vendimeve punon me ndonjë algoritëm të vet që është shkruar në mënyrë autonome, duhet ta trajtoni atë me kujdes të jashtëzakonshëm. Pas analizës së një sasie të madhe sistemesh, ne u ndalëm te Patroni — një sistem open-source, kryesisht i zhvilluar nga kompania Zalando.

Si një shkëputje lirikë, do të thoja se ne po ashtu shqyrtuam zgjidhjet multi-master, pra klasterët që mund të zgjerohen horizontalisht për shkrim. Megjithatë, për dy arsye kryesore vendosëm të mos krijojmë një klaster të tillë. Së pari, zgjidhjet e tilla kanë një kompleksitet të lartë dhe, për pasojë, më shumë pika të dobëta. Do të ishte e vështirë të krijohej një zgjidhje stabil për të gjitha rastet. Së dyti, në këtë rast PostgreSQL pushon së qeni i pastër (native), disa funksione do të ishin të paarritshme, dhe disa aplikacione do të hasnin defekte të fshehura gjatë funksionimit.

Patroni

Pra ndaj, si funksionon Patroni? Zhvilluesit nuk shpikën rrotën dhe ofruan të përdorin një nga zgjidhjet e njohura DCS. të gjitha çështjet me sinkronizimin e konfigurimeve, zgjedhjen e liderit dhe kuorumin i janë besuar atij. Ne zgjodhëm për këtë etcd.

Më pas, Patroni merret me aplikimin e duhur të të gjitha vendosjeve në PostgreSQL dhe konfigurimin e riprodhimit, si dhe ekzekutimin e komandave për switchover dhe failover (domethënë - kalimi normal dhe jo normal i masterit). Konkretisht në cloud-in MCS, mund të krijoni një klaster nga masteri, një replikë sinkronike dhe një ose disa replika asinkronike. Prania e replikës sinkronike siguron ruajtjen e të dhënave në të paktën 2 serverë, dhe pikërisht kjo replikë do të jetë kandidati kryesor për master.

Duke qenë se etcd vendoset në të njëjtit serverë, rekomandohet numri i serverëve të jetë 3 ose 5, për një vlerë optimale të kuorumit. Ky klaster është i shkallëzueshëm horizontalisht për lexim (për shkallëzimin në shkrim kam shkruar më sipër). Megjithatë, duhet të merret parasysh se replika asinkronike ka tendencë të mbetet prapa, veçanërisht nën ngarkesa të larta.

Përdorimi i replikave të tilla për lexim (hot standby) justifikohet për detyra raportimi ose analitike dhe ngarkon më pak serverin master.

Nëse dëshironi të krijoni një klaster të tillë vetë, do t'ju duhen:

  • të përgatitni 3 ose më shumë serverë, të konfigurojeni adresimin IP dhe rregullat e firewall-it mes tyre;
  • të instaloni paketat për shërbimet etcd, Patroni, PostgreSQL;
  • të konfiguroni klasterin etcd;
  • të konfiguroni shërbimin patroni për të punuar me PostgreSQL.

Pra, në total duhet të përgatitni saktësisht një duzinë skedash konfigurimi dhe të mos gaboni asnjëherë. Për këtë, është me vlerë të përdorni një mjet menaxhimi të konfigurimeve, si Ansible, për shembull. Megjithatë, këtu gjithsesi mungon një balancues TCP i disponueshëm me lartë. Krijimi i tij është një punë e veçantë.

Për ata që kanë nevojë për një klaster të gatshëm, por nuk duan të merakosen me të gjitha këto, ne kemi përpjekur të thjeshtojmë jetën dhe kemi krijuar një klaster të gatshëm në Patroni në cloud-in tonë, mund ta testoni falas. Përveç klasterit të vet, ne kemi krijuar:

  • Balancues TCP; në porte të ndryshme ai gjithmonë tregon në masterin aktual, replikën sinchronike ose asyncronike, përkatësisht;
  • API për kalimin e masterit aktiv të Patroni.

Ato mund të lidhen si përmes API-së së hapësirës MCS, ashtu edhe përmes konsolës në internet.

Demo

Për të provuar mundësitë e klashtës PostgreSQL në hapësirën MCS, le të shikojmë se si do të sillet një aplikacion i gjallë nëse ka probleme me DBMS.

Më poshtë është kodi i aplikacionit që do të regjistrojë ngjarje artificiale dhe do t'i raportojë ato në ekran. Në rast gabimesh, ajo do ta njoftojë këtë dhe do të vazhdojë punën në cikël, derisa ne ta ndalojmë atë me kombinimin Ctrl + C.

nga __future__ import print_function

nga datetime import datetime
nga random import randint
nga time import sleep
import psycopg2


def main():
    try:
        connection = psycopg2.connect(user = "admin",
                                      password = "P@ssw0rd",
                                      host = "89.208.87.38",
                                      port = "5432",
                                      database = "myproddb")

        cursor = connection.cursor()
        cursor.execute("SELECT version();")
        record = cursor.fetchone()
        print("Connection opened to", record[0])

        cursor.execute(
            "INSERT INTO log VALUES ({});".format(randint(1, 10000)))
        connection.commit()
        cursor.execute("SELECT COUNT(event_id) from log;")
        record = cursor.fetchone()
        print("Logged a value, overall count: {}".format(record[0]))
    except Exception as error:
        print ("Error while connecting to PostgreSQL", error)
    finally:
        if connection:
            cursor.close()
            connection.close()
            print("Connection closed")


if __name__ == '__main__':
    try:
        while True:
            try:
                print(datetime.now())
                main()
                sleep(3)
            except Exception as e:
                print("Caught error:n", e)
                sleep(1)
    except KeyboardInterrupt:
        print("exit")

Aplikacioni kërkon PostgreSQL për të funksionuar. Le të krijojmë një klaster në cloud MCS duke përdorur API. Në terminalin normal, ku variabli OS_TOKEN përmban tokenin për qasje në API (mund të merret me komandën openstack token issue), shkruajmë komandat:

Krijojmë klasterin:

cat < pgc10.json
{"cluster":{"name":"postgres10","allow_remote_access":true,"datastore":{"type":"postgresql","version":"10"},"databases":[{"name":"myproddb"}],"users":[{"databases":[{"name":"myproddb"}],"name":"admin","password":"P@ssw0rd"}],"instances":[{"key_name":"shared","availability_zone":"DP1","flavorRef":"d659fa16-c7fb-42cf-8a5e-9bcbe80a7538","nics":[{"net-id":"b91eafed-12b1-4a46-b000-3984c7e01599"}],"volume":{"size":50,"type":"DP1"}},{"key_name":"shared","availability_zone":"DP1","flavorRef":"d659fa16-c7fb-42cf-8a5e-9bcbe80a7538","nics":[{"net-id":"b91eafed-12b1-4a46-b000-3984c7e01599"}],"volume":{"size":50,"type":"DP1"}},{"key_name":"shared","availability_zone":"DP1","flavorRef":"d659fa16-c7fb-42cf-8a5e-9bcbe80a7538","nics":[{"net-id":"b91eafed-12b1-4a46-b000-3984c7e01599"}],"volume":{"size":50,"type":"DP1"}}]}}
EOF

curl -s -H "X-Auth-Token: $OS_TOKEN" 
-H 'Accept: application/json' 
-H 'Content-Type: application/json' 
-d @pgc10.json https://infra.mail.ru:8779/v1.0/ce2a41bbd1434013b85bdf0ba07c770f/clusters

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Kur klasteri të kalojë në statusin ACTIVE, të gjitha fushat do të marrin vlera të aktualizuara — klasteri është gati.

Në GUI:

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Le të përpiqemi të lidhemi dhe të krijojmë një tabelë:

psql -h 89.208.87.38 -U admin -d myproddb
Fjalëkalimi për përdoruesin admin:
psql (11.1, server 10.7)
Shkruani "help" për ndihmë.

myproddb=> KRIJONI TABELË log (event_id integer NOT NULL);
KRIJO TABELË
myproddb=> SHTO NË log VLERAT (1),(2),(3);
SHTO 0 3
myproddb=> ZGJIDH * NGA log;
 event_id
----------
        1
        2
        3
(3 rreshta)

myproddb=>

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Në aplikacion do të përfshijmë parametrat aktual për lidhjen me PostgreSQL. Ne do të tregojmë adresën e balancuesit TCP, duke eliminuar kësisoj nevojën për të kaluar manualisht në adresën e masterit. Do ta nisnim. Siç shihet, ngjarjet regjistrohen me sukses në bazën e të dhënave.

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Kalimi i planifikuar i masterit

Tani do të testojmë funksionimin e aplikacionit tonë gjatë kalimit të planifikuar të masterit:

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Po vëzhgojmë aplikacionin. Shikojmë se funksionimi i aplikacionit vërtet ndërpritet, por zgjat vetëm disa sekonda, në këtë rast maksimalisht 9.

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Rënia e serverit

Tani do të përpiqemi të simulojmë rënien e makinës virtuale, masterit aktual. Do të ishte e mundur thjesht ta fiknim makinën virtuale përmes ndërfaqes Horizon, por kjo do të ishte një fikje e zakonshme. Ky kalim do të përpunojë nga të gjitha shërbimet, përfshirë Patroni.

Na nevojitet një fikje e paparashikueshme. Prandaj, u kërkova administratorëve tanë që për qëllime testuese të fiknin makinën virtuale — masterin aktual — në mënyrë jo të zakonshme.

Si si ndërtuam një klasër të besueshëm PostgreSQL mbi Patroni

Në këtë të njëjtën kohë, aplikacioni ynë vazhdoi të funksionojë. Natyrisht, një kalim i tillë i papritur i masterit nuk mund të kalojë pa u vënë re.

2019-03-29 10:45:56.071234
Këtu u hap lidhja me PostgreSQL 10.7 në x86_64-pc-linux-gnu, e kompajluar nga gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
E regjistruar një vlerë, numri total: 453
Lidhja u mbyll
2019-03-29 10:45:59.205463
Këtu u hap lidhja me PostgreSQL 10.7 në x86_64-pc-linux-gnu, e kompajluar nga gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
E regjistruar një vlerë, numri total: 454

Lidhja u mbyll
2019-03-29 10:46:02.661440
Gabim gjatë lidhjes me serverin PostgreSQL mbylli lidhjen papritur
       Kjo ndoshta do të thotë se serveri u mbyll abnormalisht
       para ose gjatë përpunimit të kërkesës.

Gabimi i kapur:
 variabla lokale 'connection' i referuar para caktimit
……………………………………………………….. - këtu është një sasi gabimesh
2019-03-29 10:46:30.930445
Gabim gjatë lidhjes me serverin PostgreSQL mbylli lidhjen papritur
       Kjo ndoshta do të thotë se serveri u mbyll abnormalisht
       para ose gjatë përpunimit të kërkesës.

Gabimi i kapur:
 variabla lokale 'connection' i referuar para caktimit
2019-03-29 10:46:31.954399
Këtu u hap lidhja me PostgreSQL 10.7 në x86_64-pc-linux-gnu, e kompajluar nga gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
E regjistruar një vlerë, numri total: 455
Lidhja u mbyll
2019-03-29 10:46:35.409800
Këtu u hap lidhja me PostgreSQL 10.7 në x86_64-pc-linux-gnu, e kompajluar nga gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
E regjistruar një vlerë, numri total: 456
Lidhja u mbyll
^Cexit

Siç duket, aplikacioni ka arritur të vazhdojë punën për më pak se 30 sekonda. Po, ndoshta një numër i caktuar përdoruesish do të vërejnë problemet. Megjithatë, kjo është një prishje serioze e serverit, diçka që nuk ndodh shpesh. Në të njëjtën kohë, një person (administrator) ndoshta nuk do të kishte arritur të reagonte kaq shpejt, përveç nëse nuk ishte duke mbajtur konsolën gati me një skenar kalimi.

Përfundim

Mendoj se një kluster i tillë ofron një avantazh të jashtëzakonshëm për administratorët. Në thelb, prishjet serioze dhe dështimet e serverëve të DB nuk do të jenë të dukshme për aplikacionin dhe, në përputhje, për përdoruesin. Nuk do të nevojitej të riparoni diçka me ngut dhe të kaloni në konfigurata të përkohshme, serverë etj. Nëse kjo zgjidhje përdoret si një shërbim i gatshëm në cloud, atëherë nuk do të nevojitej të humbni kohë për përgatitjen e saj. Mund të merrni përgjegjësi për diçka më interesante.

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster