
Danas je visoka dostupnost usluga potrebna uvijek i svugdje, ne samo u velikim skupim projektima. Privremeno nedostupne stranice sa porukom „Izvinite, održavanje je u toku“ i dalje se susreću, ali obično izazivaju snishodljiv osmijeh. Dodajmo tome i život u oblacima, kada je potreban samo jedan poziv API-ju za pokretanje dodatnog servera, a ne treba razmišljati o "gvozdenom" radu. I više nema nikakvog opravdanja zašto kritični sistem nije napravljen pouzdano koristeći klaster tehnologije i redundantnost.
Reći ćemo vam koja rješenja smo razmatrali kako bismo osigurali pouzdanost baza podataka u našim servisima i do čega smo došli. Plus demo sa dalekosežnim zaključcima.
Naslijeđe u arhitekturi visoke dostupnosti
To se još bolje vidi u kontekstu razvoja različitih sistema otvorenog koda. Naslijeđena rješenja morala su dodati tehnologije visoke dostupnosti kako se potražnja povećavala. I njihov kvalitet je bio različit. Rešenja nove generacije stavljaju visoku dostupnost u srž svoje arhitekture. Na primjer, MongoDB pozicionira klaster kao svoj glavni slučaj upotrebe. Klaster se skalira horizontalno, što je jaka konkurentska prednost ovog DBMS-a.
Vratimo se na PostgreSQL. Ovo je jedan od najstarijih popularnih open source projekata, čije se prvo izdanje dogodilo 95. godine prošlog stoljeća. Projektni tim dugo vremena nije smatrao visoku dostupnost zadatkom koji sistem treba riješiti. Stoga je tehnologija replikacije za kreiranje kopija podataka ugrađena tek u verziju 8.2 2006. godine, ali je to bila datoteka (log shipping). 2010. godine, streaming replikacija se pojavila u verziji 9.0 i predstavlja osnovu za kreiranje širokog spektra klastera. Ovo je, u stvari, veoma iznenađujuće za ljude koji se upoznaju sa PostgreSQL-om nakon Enterprise SQL-a ili modernog NoSQL-a - standardno rešenje iz zajednice je jednostavno par master-replika sa sinhronom ili asinhronom replikacijom. Istovremeno, u odvodu, master se prebacuje ručno, a pitanje prebacivanja klijenata se također predlaže za samostalno rješavanje.
Kako smo odlučili da napravimo pouzdan PostgreSQL i šta smo za to odabrali
Međutim, PostgreSQL ne bi postao toliko popularan da nije bilo ogromnog broja projekata i alata koji pomažu u izgradnji rješenja otpornog na greške koje ne zahtijeva stalnu pažnju. U oblaku (MCS) od lansiranja DBaaS-a, dostupni su pojedinačni PostgreSQL serveri i parovi master-replika sa asinhronom replikacijom.
Naravno, željeli smo da olakšamo život svima i učinimo dostupnom PostgreSQL instalaciju koja bi mogla poslužiti kao osnova za visoko dostupne usluge koje ne bi morale stalno pratiti i buditi se noću da bi se prebacile. U ovom segmentu postoje kako stara provjerena rješenja, tako i generacija novih uslužnih programa koji koriste najnovija dostignuća.
Danas problem visoke dostupnosti ne počiva na rezervaciji (ovo se podrazumijeva), već na konsenzusu – algoritmu za izbor lidera (Leader selection). Najčešće se velike nezgode ne dešavaju zbog nedostatka servera, već zbog problema sa konsenzusom: novi lider nije izašao, dva lidera su se pojavila u različitim data centrima itd. Primjer je pad na Github MySQL klasteru - napisali su .
Matematička osnova u ovom pitanju je veoma ozbiljna. S jedne strane, tu , što nameće teorijska ograničenja mogućnostima konstruisanja HA rješenja, s druge strane, matematički dokazani algoritmi za određivanje konsenzusa, kao npr. и . Na osnovu toga postoje prilično popularni DCS (decentralizovani konsenzusni sistemi) - Zookeeper, etcd, Consul. Stoga, ako sistem odlučivanja radi na nekom svom algoritmu, samostalno napisanom, treba biti izuzetno oprezan. Nakon analize velikog broja sistema, odlučili smo se za Patroni, sistem otvorenog koda koji je uglavnom razvio Zalando.
Kao lirsku digresiju, reći ću da smo razmatrali i multi-master rješenja, odnosno klastere koji se mogu horizontalno skalirati za snimanje. Međutim, iz dva glavna razloga, odlučili smo da ne pravimo takav klaster. Prvo, takva rješenja imaju visoku složenost i, shodno tome, više ranjivosti. Biće teško napraviti stabilno rješenje za sve slučajeve. Drugo, u ovom slučaju PostgreSQL prestaje biti čist (native), neke funkcije će biti nedostupne, neke aplikacije mogu imati skrivene greške tokom rada.
Patroni
Pa kako Patroni funkcionira? Programeri nisu ponovo izmislili točak i predložili su korištenje jednog od dokazanih DCS rješenja kao osnove. Njemu su na milost i nemilost data sva pitanja oko sinhronizacije konfiguracija, izbora vođe i kvoruma. Za ovo smo odabrali etcd.
Zatim, Patroni se bavi pravilnom primenom svih PostgreSQL podešavanja i podešavanja replikacije, kao i izvršavanjem komandi za prebacivanje i prelazak na grešku (odnosno, redovno i nenormalno prebacivanje mastera). Konkretno, u MCS oblaku možete kreirati klaster od mastera, sinhrone replike i jedne ili više asinhronih replika. Prisustvo sinhrone replike osigurava sigurnost podataka na najmanje 2 servera, a upravo će ta replika biti glavni „master kandidat“.
Pošto je etcd raspoređen na istim serverima, preporučuje se 3 ili 5 servera za optimalni kvorum. Takav klaster skalira horizontalno za čitanje (o skaliranju za pisanje sam pisao gore). Međutim, imajte na umu da asinhrone replike imaju tendenciju da zaostaju, posebno pod velikim opterećenjima.
Upotreba ovakvih replika za čitanje (hot standby) je opravdana za zadatke izvještavanja ili analize i rasterećenje glavnog servera.
Ako želite sami napraviti takav klaster, trebat će vam:
- pripremite 3 ili više servera, konfigurišite IP adresiranje i pravila zaštitnog zida između njih;
- instalirati pakete za etcd, Patroni, PostgreSQL usluge;
- postaviti etcd klaster;
- konfigurirajte patroni servis za rad sa PostgreSQL.
To jest, ukupno morate pravilno sastaviti desetak konfiguracijskih datoteka i nigdje ne pogriješiti. Da biste to učinili, svakako biste trebali koristiti alat za upravljanje konfiguracijom, kao što je Ansible, na primjer. Međutim, još uvijek ne postoji visoko dostupan TCP balanser. Izrada je poseban posao.
Za one kojima je potreban gotov klaster, ali ne žele da čačkaju po svemu ovome, pokušali smo da pojednostavimo život i napravili smo gotov klaster na Patroni u našem oblaku, možete ga besplatno testirati. Pored samog klastera, uradili smo:
- TCP balancer; na različitim portovima, uvijek ukazuje na trenutni master, sinkronu ili asinkronu repliku, respektivno;
- API za prebacivanje aktivnog Patroni mastera.
Mogu se podklasirati i kroz MCS cloud API i web konzolu.
Demo
Da bismo testirali mogućnosti PostgreSQL klastera u MCS oblaku, hajde da vidimo kako se ponaša živa aplikacija u slučaju problema sa DBMS-om.
Slijedi kod aplikacije koji će evidentirati umjetne događaje i prijaviti ih na ekran. U slučaju greške, to će prijaviti i nastaviti svoj rad u petlji dok ga ne zaustavimo kombinacijom Ctrl + C.
from __future__ import print_function
from datetime import datetime
from random import randint
from 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")
Aplikaciji je potreban PostgreSQL da bi radila. Kreirajmo klaster u MCS oblaku koristeći API. U običnom terminalu, gdje varijabla OS_TOKEN sadrži token za pristup API-ju (može se dobiti naredbom openstack token issue), upisaćemo naredbe:
Kreirajte klaster:
cat <<EОF > 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

Kada se klaster prebaci u status ACTIVE, sva polja će dobiti trenutne vrijednosti - klaster je spreman.
U GUI:

Pokušajmo se povezati i kreirati tabelu:
psql -h 89.208.87.38 -U admin -d myproddb
Password for user admin:
psql (11.1, server 10.7)
Type "help" for help.
myproddb=> CREATE TABLE log (event_id integer NOT NULL);
CREATE TABLE
myproddb=> INSERT INTO log VALUES (1),(2),(3);
INSERT 0 3
myproddb=> SELECT * FROM log;
event_id
----------
1
2
3
(3 rows)
myproddb=>

U aplikaciji ćemo odrediti trenutne postavke za povezivanje na PostgreSQL. Navest ćemo adresu TCP balansera, čime se eliminira potreba za ručnim prebacivanjem na adresu mastera. Hajde da ga pokrenemo. Kao što vidite, događaji su uspješno evidentirani u bazi podataka.

Planirano glavno prebacivanje
Sada testirajmo rad naše aplikacije tokom planiranog prebacivanja glavnog:

Pratimo aplikaciju. Vidimo da je aplikacija zaista prekinuta, ali traje svega nekoliko sekundi, u ovom konkretnom slučaju maksimalno 9.

auto crash
Pokušajmo sada simulirati pad virtuelne mašine, trenutnog mastera. Bilo bi moguće jednostavno isključiti virtuelnu mašinu preko Horizon interfejsa, samo što će to biti redovno gašenje. Takav prekidač će obraditi sve usluge, uključujući Patroni.
Treba nam nepredvidivo zatvaranje. Stoga sam zamolio naše administratore u svrhu testiranja da isključe virtuelnu mašinu - trenutni master - na nenormalan način.

U isto vrijeme, naša aplikacija je nastavila s radom. Naravno, takvo hitno prebacivanje mastera ne može proći nezapaženo.
2019-03-29 10:45:56.071234
Connection opened to PostgreSQL 10.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logged a value, overall count: 453
Connection closed
2019-03-29 10:45:59.205463
Connection opened to PostgreSQL 10.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logged a value, overall count: 454
Connection closed
2019-03-29 10:46:02.661440
Error while connecting to PostgreSQL server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
Caught error:
local variable 'connection' referenced before assignment
……………………………………………………….. - здесь какое-то количество ошибок
2019-03-29 10:46:30.930445
Error while connecting to PostgreSQL server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
Caught error:
local variable 'connection' referenced before assignment
2019-03-29 10:46:31.954399
Connection opened to PostgreSQL 10.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logged a value, overall count: 455
Connection closed
2019-03-29 10:46:35.409800
Connection opened to PostgreSQL 10.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logged a value, overall count: 456
Connection closed
^Cexit
Kao što vidite, aplikacija je uspjela nastaviti svoj rad za manje od 30 sekundi. Da, određeni broj korisnika usluga će imati vremena da uoči probleme. Međutim, ovo je ozbiljan kvar servera, to se ne dešava tako često. U isto vrijeme, osoba (administrator) teško da bi imala vremena da reaguje tako brzo, osim da nije sjedila u konzoli spremno sa skriptom za prebacivanje.
zaključak
Čini mi se da takav klaster pruža ogromnu prednost za administratore. Zapravo, ozbiljni kvarovi i kvarovi servera baze podataka neće biti primjetni za aplikaciju, a samim tim i za korisnika. Ne morate nešto popravljati u žurbi i prelaziti na privremene konfiguracije, servere itd. A ako se takvo rješenje koristi kao gotova usluga u oblaku, onda neće biti potrebno trošiti vrijeme na njegovu pripremu. Možete uraditi nešto zanimljivije.
izvor: www.habr.com
