
Tänapäeval on teenuste kõrge kättesaadavus vajalik alati ja igal pool, mitte ainult suurtes kallites projektides. Ajutiselt mittefunktsionaalsed saidid sõnumiga „Vabandame, teostatakse tehnilisi töid“ esinevad veel, kuid tavaliselt tekitavad need vaid heakskiitvat naeratust. Lisame siia elu pilvedes, kus täiendava serveri käivitamiseks on vajalik vaid üks API kutse, ning ei pea üldse muretsema „rauaga“ tegelemise pärast. Ja enam ei ole õigustusi, miks kriitiline süsteem ei olnud usaldusväärselt tehtud klustertehnoloogiate ja varundamise kasutamisega.
Me räägime, milliseid lahendusi kaalusin oma teenustes andmebaaside usaldusväärsuse tagamiseks ja kuhu oleme jõudnud. Pluss demoes kaugemaid järeldusi.
Legacy kõrge kättesaadavuse arhitektuuris
Seda on veel paremini näha erinevate opensource-süsteemide arengus. Vanad lahendused pidid kõrge kättesaadavuse tehnoloogiaid lisama, kui nõudlus suurenes. Ja nende kvaliteet oli erinev. Uue põlvkonna lahendused panevad kõrge kättesaadavuse oma arhitektuuri aluseks. Näiteks positsioneerib MongoDB klastrit kui peamise kasutusvariandi. Klaster on horisontaalselt skaleeritav, mis on selle andmebaasi tugev konkurentsieelis.
Naaseme PostgreSQL juurde. See on üks vanimaid populaarseid opensource projekte, mille esimene väljaanne ilmus 90ndate aastate keskel. Projekti meeskond ei pidanud pikka aega kõrget kättesaadavust süsteemi poolt lahendatavaks ülesandeks. Seega sai replikatsiooni tehnoloogia andmete koopiate loomiseks sisse ehitatud alles versioonis 8.2 2006. aastal, kuid see oli failipõhine (log shipping). 2010. aastal ilmus versioonis 9.0 voogesituse replikatsioon, mis on aluseks erinevate klastrite loomisele. See üllatab inimesi, kes tutvuvad PostgreSQL-ga pärast Enterprise SQL-i või kaasaegset NoSQL-i — kogukonna standardlahendus on lihtsalt paar master-replica koos sünkroonse või asünkroonse replikatsiooniga. Samal ajal toimub master'i üleviimine käsitsi ja klientide üleviimise küsimus pakutakse samuti ise lahendada.
Kuidas me otsustasime luua usaldusväärse PostgreSQL-i ja mida me selleks valisime
Siiski ei oleks PostgreSQL nii populaarne, kui ei oleks tohutult projekte ja tööriistu, mis aitavad luua tõrgeteta lahendusi, mis ei vaja pidevat tähelepanu. Pilves (MCS) on alates DBaaS-i käivitamisest saadaval olnud üksik PostgreSQL serverid ja paar meistri-replikat asünkroonse replikatsiooniga.
Loomulikult soovisime elu kõigile lihtsustada ja teha kergesti kättesaadav PostgreSQL install kasutamiseks, mis võiks olla aluseks kõrgelt kättesaadavatele teenustele, mille eest ei peaks pidevalt jälgima ega öösel üle minema. Selles valdkonnas on nii vanad ning tõestatud lahendused kui ka uus põlvkond tööriistu, mis kasutavad uusimaid arenguid.
Täna seisneb kõrgema kättesaadavuse probleem mitte varundamises (see on iseenesestmõistetav), vaid konsensuses — liidri valimise algoritmis (Leader election). Suured avariid tekivad kõige sagedamini mitte serverite puudumise tõttu, vaid konsensuse probleemide tõttu: uus liider ei saanud valitud, kaks liidrit ilmusid erinevatesse andmekeskustesse jne. Näide — MySQL kluster Githubis — nad kirjutasid .
Selles küsimuses on matemaatiline alus väga tõsine. Ühest küljest on olemas , mis seab teoreetilisi piiranguid HA-lahenduste loomise võimalustele, ja teiselt poolt — matemaatiliselt tõestatud konsensuse määramise algoritmid, nagu ja . Selle alusel on olemas üsna populaarsed DCS-d (detsentraliseeritud konsensuse süsteemid) — Zookeeper, etcd, Consul. Seetõttu, kui otsustusprotsess töötab sellel põhineval algoritmil, mis on kirjutatud iseseisvalt, tuleb sellele äärmiselt ettevaatlikult läheneda. Pärast tohutu hulga süsteemide analüüsi valisime Patroni — avatud lähtekoodiga süsteemi, mida arendab peamiselt ettevõte Zalando.
Mugavuse nimel ütlen, et oleme kaalunud ka multi-master lahendusi, st klastreid, mida saab horisontaalselt skaleerida kirjutamiseks. Kuid kahes peamises põhjusel otsustasime sellist klastri mitte luua. Esiteks, sellised lahendused on keerulised ja seetõttu on neid rohkem haavatavaid kohti. On raske luua stabiilset lahendust kõigi olukordade jaoks. Teiseks, sellisel juhul lõpetab PostgreSQL olemise puhas (native), mõned funktsioonid ei ole kergesti kättesaadavad ja mõnedel rakendustel võivad töös esineda varjatud vead.
Patronit
Nii et kuidas Patroni töötab? Arendajad ei hakanud ratast leidma ja soovitasid kasutada alusena ühte tõestatud DCS-lahendust. Kogu konfiguratsiooni sünkroniseerimise, liidri valiku ja kvoorumi küsimused antakse tema hoolde. Me valisime selleks etcd.
Seejärel tegeleb Patroni PostgreSQL-i kõigi seadete õige rakendamise ja replikatsiooni seadistamisega, samuti käskude täitmisega switchover ja failover (st tavapärane ja ebatavaliselt kapriisne liikumine). Konkreetsetes MCS pilves saab luua klastri, mis koosneb peamisest serverist, sünkroonsest replikast ja ühest või mitmest asünkroonsest replikast. Sünkroonne replik tagab andmete säilitamise vähemalt 2 serveris ja just see replik on peamine "kandidaat masteriks".
Kuna etcd paigaldatakse samadele serveritele, on soovitatav serverite arv 3 või 5, et saavutada optimaalse kvoorumi väärtus. Selline klastri skaleeritakse horisontaalselt lugemiseks (kirjutamise skaleerimise kohta kirjutasin varem). Tuleb siiski arvesse võtta, et asünkroonsed replikad kalduvad jääma maha, eriti suurte koormuste korral.
Selliste lugemisreplikate (hot standby) kasutamine on põhjuslik aruandlus- või analüüsitööde jaoks ja vähendab peamise serveri koormust.
Kui soovite sellist klastrit teha iseseisvalt, siis on teil vaja:
- valmistada ette 3 või enam serverit, seadistada IP-aadressid ja tulemüürireeglid nende vahel;
- installeerida paketid teenuste jaoks etcd, Patroni, PostgreSQL;
- seadistada etcd klastri;
- seadistada patroni teenus PostgreSQL-i jaoks.
Kokkuvõttes tuleb õigesti koostada kümme konfiguratsioonifaili ja mitte kuskil eksida. Selleks on kindlasti mõistlik kasutada konfiguratsiooni haldamise tööriista, näiteks Ansible. Sellegipoolest puudub siinkohal kõrgkättesaadav TCP-koormuse jagaja. Selle loomine on eraldi ülesanne.
Neile, kellele on vajalik valmis klaster, kuid kes ei soovi sellega ise süüvida, oleme püüdnud elu lihtsustada ja teinud ülesseadmise samas Patroni klastri oma pilves, mida saab tasuta katsetada. Lisaks ise klastrile oleme loonud:
- TCP-koormuse jagaja; erinevatelt portidelt osutab see alati praegusele peamisterverile, sünkroonsele või asünkroonsele koopiale vastavalt;
- API aktiivse peamisterveri vahetamiseks Patronis.
Nendele on võimalik pääseda ligi nii MCS pilve API kaudu kui ka veebikonsoli kaudu.
Demo
PostgreSQL klastri võimaluste testimiseks MCS pilves vaatame, kuidas käitub elav rakendus andmebaasi probleemide korral.
Järgnevalt on esitatud rakenduse kood, mis logib kunstlikke sündmusi ja teatab sellest ekraanil. Vigade korral teatab see neist ja jätkab toimimist tsüklis, kuni me selle ei peata kombinatsiooniga 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")
Rakendusele on vajalik PostgreSQL. Loome klastri MCS pilves, kasutades API-d. Tavalises terminalis, kus OS_TOKEN muutujas on API juurde pääsemiseks vajalik token (mida saab saada käsuga openstack token issue), kirjutame käsud:
Loomeme klastri:
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

Kui klaster jõuab staatusele ACTIVE, saavad kõik väljad ajakohased väärtused — klaster on valmis.
GUI-s:

Proovime ühendust luua ja tabelit luua:
psql -h 89.208.87.38 -U admin -d myproddb
Kasutaja admin parool:
psql (11.1, server 10.7)
Tippige "help", et saada abi.
myproddb=> CREATE TABLE log (event_id integer NOT NULL);
LOODUD TABEL
myproddb=> INSERT INTO log VALUES (1),(2),(3);
INSERT 0 3
myproddb=> SELECT * FROM log;
event_id
----------
1
2
3
(3 rida)
myproddb=>

Rakenduses määrame õiged seaded PostgreSQL-iga ühendamiseks. Määrame TCP-balasorija aadressi, mis elimineerib vajaduse käsitsi vahetada meistriserveri aadressile. Käivitame selle. Nagu näha, logitakse sündmused edukalt andmebaasi.

Planeeritud meistrivahetus
Nüüd testime meie rakenduse tööd planeeritud meistrivahetusel:

Jälgime rakendust. Näeme, et rakenduse töö tõepoolest katkevad, kuid see kestab vaid paar sekundit, antud juhul maksimaalselt 9.

Masina kokkuvarisemine
Nüüd proovime simuleerida virtuaalse masina kokkuvarisemist, praegust meistrit. Saaksime lihtsalt välja lülitada virtuaalse masina Horizon'i liidesest, kuid see oleks tavaline väljalülitamine. Sellist vahetust töötlevad kõik teenused, sealhulgas Patroni.
Kuid me vajame ettearvamatut väljalülitamist. Seetõttu palusin meie administraatoritel katsetamiseks välja lülitada virtuaalse masina — praeguse meistri — ebanormaalsel viisil.

Sellel ajal töötas meie rakendus edasi. Loomulikult ei saa selline hädaolukorra meistrivahetus märkamatuks jääda.
2019-03-29 10:45:56.071234
Ühendus avati PostgreSQL 10.7-le x86_64-pc-linux-gnu, kompileeritud gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logitud väärtus, koguarv: 453
Ühendus suleti
2019-03-29 10:45:59.205463
Ühendus avati PostgreSQL 10.7-le x86_64-pc-linux-gnu, kompileeritud gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logitud väärtus, koguarv: 454
Ühendus suleti
2019-03-29 10:46:02.661440
Viga PostgreSQL serveriga ühendamisel, ühendus suleti ootamatult
See tõenäoliselt tähendab, et server katkestas ebanormaalselt
enne või töötlemise ajal.
Tuvastatud viga:
kohalik muutujat 'connection' kasutatakse enne määramist
……………………………………………………….. - siin on mõni viga
2019-03-29 10:46:30.930445
Viga PostgreSQL serveriga ühendamisel, ühendus suleti ootamatult
See tõenäoliselt tähendab, et server katkestas ebanormaalselt
enne või töötlemise ajal.
Tuvastatud viga:
kohalik muutujat 'connection' kasutatakse enne määramist
2019-03-29 10:46:31.954399
Ühendus avati PostgreSQL 10.7-le x86_64-pc-linux-gnu, kompileeritud gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logitud väärtus, koguarv: 455
Ühendus suleti
2019-03-29 10:46:35.409800
Ühendus avati PostgreSQL 10.7-le x86_64-pc-linux-gnu, kompileeritud gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
Logitud väärtus, koguarv: 456
Ühendus suleti
^Cexit
Nagu näha, suutis rakendus jätkata oma tööd vähem kui 30 sekundiga. Jah, mõned teenuse kasutajad märkavad probleeme. Kuid see on tõsine serveri rike, mis ei juhtu sageli. Samas ei jõua inimene (administraator) tõenäoliselt nii kiiresti reageerida, kui ta ei istu juba konsoolis valmis skriipti üleminekuks.
Kokkuvõte
Minu arust annab selline klaster administraatoritele tohutu eelise. Sisuliselt ei ole tõsise rikke ja andmebaasiserverite rikke mõju rakendusele ja seega kasutajatele märgata. Ei pea asju kiirusel parandama ja vahetama ajutiste konfiguratsioonide, serverite jne peale. Ja kui seda lahendust kasutada pilves valmis teenusena, siis ei pea selle ettevalmistamiseks aega kulutama. Saavutatakse midagi huvitavat.
Allikas: habr.com
