
Tegenwoordig is een hoge beschikbaarheid van diensten altijd en overal vereist, en niet alleen bij grote, dure projecten. Tijdelijk niet beschikbare sites met de melding “Sorry, er wordt onderhoud gepleegd” komen nog steeds vaak voor, maar veroorzaken meestal een neerbuigende glimlach. Laten we aan dit leven in de cloud toevoegen: wanneer u een extra server wilt lanceren, heeft u slechts één aanroep naar de API nodig en hoeft u niet na te denken over de werking van de "hardware". En er zijn geen excuses meer waarom een cruciaal systeem niet op betrouwbare wijze is gebouwd met behulp van clustertechnologieën en redundantie.
We vertellen u welke oplossingen we hebben overwogen om de betrouwbaarheid van databases in onze diensten te garanderen en waar we op uit zijn gekomen. Plus een demo met verregaande conclusies.
Erfenis in architectuur met hoge beschikbaarheid
Dit wordt nog beter gezien in de context van de ontwikkeling van verschillende opensourcesystemen. Oudere oplossingen werden gedwongen technologieën met hoge beschikbaarheid toe te voegen naarmate de vraag toenam. En hun kwaliteit varieerde. Bij oplossingen van de volgende generatie vormt hoge beschikbaarheid de kern van hun architectuur. MongoDB positioneert clustering bijvoorbeeld als zijn primaire gebruiksscenario. Het cluster schaalt horizontaal, wat een sterk concurrentievoordeel is van dit DBMS.
Laten we terugkeren naar PostgreSQL. Dit is een van de oudste populaire opensource-projecten, waarvan de eerste release plaatsvond in het 95e jaar van de vorige eeuw. Lange tijd beschouwde het projectteam hoge beschikbaarheid niet als een probleem dat door het systeem moest worden aangepakt. Daarom werd de replicatietechnologie voor het maken van kopieën van gegevens pas in versie 8.2 in 2006 ingebouwd, maar deze was gebaseerd op bestanden (verzending van logbestanden). In 2010 introduceerde versie 9.0 streamingreplicatie, en dit vormt de basis voor het creëren van een grote verscheidenheid aan clusters. Dit is in feite zeer verrassend voor mensen die na Enterprise SQL of moderne NoSQL kennis maken met PostgreSQL - de standaardoplossing uit de gemeenschap is eenvoudigweg een master-replica-paar met synchrone of asynchrone replicatie. Tegelijkertijd wordt op voorraad het wisselen van de master handmatig gedaan en wordt ook voorgesteld om het probleem van het wisselen van klant onafhankelijk op te lossen.
Hoe we besloten om betrouwbare PostgreSQL te maken en wat we hiervoor kozen
PostgreSQL zou echter niet zo populair zijn geworden als er niet een groot aantal projecten en tools waren die helpen bij het bouwen van een fouttolerante oplossing die geen constante aandacht vereist. In de wolk (MCS) enkele PostgreSQL-servers en master-replica-paren met asynchrone replicatie zijn beschikbaar sinds de lancering van DBaaS.
Uiteraard wilden we het leven voor iedereen gemakkelijker maken en een PostgreSQL-installatie beschikbaar stellen die als basis zou kunnen dienen voor zeer beschikbare services, zonder voortdurend te moeten monitoren en 's nachts wakker te moeten worden om de overstap te maken. In dit segment zijn er zowel oude bewezen oplossingen als een generatie nieuwe nutsvoorzieningen die gebruik maken van de nieuwste ontwikkelingen.
Tegenwoordig berust het probleem van hoge beschikbaarheid niet op redundantie (dat spreekt voor zich), maar op consensus: het Leader-verkiezingsalgoritme. Meestal gebeuren grote ongelukken niet vanwege een gebrek aan servers, maar vanwege problemen met de consensus: er is geen nieuwe leider gekozen, er zijn twee leiders verschenen in verschillende datacenters, enz. Voorbeeld - een ongeluk op een Github MySQL-cluster - schreven ze .
De wiskundige basis in deze kwestie is zeer serieus. Aan de ene kant is dat zo , dat theoretische beperkingen oplegt aan de mogelijkheden om HA-oplossingen te construeren, aan de andere kant wiskundig bewezen algoritmen voor het bepalen van consensus, zoals и . Op basis hiervan zijn er behoorlijk populaire DCS (gedecentraliseerde consensussystemen) - Zookeeper, etcd, Consul. Daarom, als het besluitvormingssysteem werkt op een soort algoritme dat onafhankelijk is geschreven, moet je er met uiterste voorzichtigheid mee omgaan. Na een groot aantal systemen te hebben geanalyseerd, zijn we uitgekomen op Patroni, een opensourcesysteem dat voornamelijk door Zalando is ontwikkeld.
Als lyrische uitweiding wil ik zeggen dat we ook multi-masteroplossingen hebben overwogen, dat wil zeggen clusters die horizontaal kunnen worden geschaald voor opname. Om twee belangrijke redenen besloten ze echter om zo’n cluster niet op te richten. Ten eerste hebben dergelijke oplossingen een hoge complexiteit en dienovereenkomstig meer kwetsbaarheden. Het zal lastig zijn om voor alle gevallen een stabiele oplossing te vinden. Ten tweede is PostgreSQL in dit geval niet langer puur (native), zullen sommige functies niet beschikbaar zijn en kunnen sommige applicaties tijdens de werking verborgen bugs bevatten.
patroon
Hoe werkt Patroni? De ontwikkelaars hebben het wiel niet opnieuw uitgevonden en stelden voor om één van de beproefde DCS-oplossingen als basis te gebruiken. Alle kwesties met betrekking tot de synchronisatie van configuraties, de verkiezing van een leider en het quorum worden aan hem overgelaten. Wij hebben hiervoor voor etcd gekozen.
Vervolgens zorgt Patroni voor de juiste toepassing van alle instellingen op PostgreSQL en replicatie-instellingen, evenals de uitvoering van opdrachten bij omschakeling en failover (dat wil zeggen, reguliere en noodschakeling van de master). Specifiek in de MCS-cloud kunt u een cluster aanmaken van een master, een synchrone replica en één of meerdere asynchrone replica's. De aanwezigheid van een synchrone replica garandeert de veiligheid van gegevens op minimaal 2 servers, en het is deze replica die de belangrijkste “masterkandidaat” zal zijn.
Omdat etcd op dezelfde servers wordt geïmplementeerd, is het aanbevolen aantal servers 3 of 5 voor een optimaal quorum. Zo'n cluster schaalt horizontaal om te lezen (ik schreef hierboven over schalen om te schrijven). Houd er echter rekening mee dat asynchrone replica's gevoelig zijn voor vertraging, vooral onder hoge belasting.
Het gebruik van dergelijke leesreplica's (hot standby) is gerechtvaardigd voor rapportage- of analysetaken en verlicht de belasting van de masterserver.
Als je zelf zo'n cluster wilt maken, heb je het volgende nodig:
- bereid 3 of meer servers voor, configureer IP-adressering en firewallregels ertussen;
- pakketten installeren voor etcd, Patroni, PostgreSQL-services;
- etcd-cluster configureren;
- configureer de patroni-service om met PostgreSQL te werken.
Dat wil zeggen dat u in totaal een tiental configuratiebestanden correct moet samenstellen en nergens een fout moet maken. Hiervoor moet je zeker een configuratiemanagementtool gebruiken, zoals bijvoorbeeld Ansible. Er is echter nog steeds geen TCP-balancer met hoge beschikbaarheid. Het maken ervan is een vak apart.
Voor degenen die een kant-en-klaar cluster nodig hebben, maar niet aan dit alles willen sleutelen, hebben we geprobeerd het leven te vereenvoudigen en een kant-en-klaar cluster op Patroni in onze cloud gemaakt, je kunt het gratis testen. Naast het cluster zelf hebben we het volgende gedaan:
- TCP-balancer; op verschillende poorten verwijst het altijd naar respectievelijk de huidige master, synchrone of asynchrone replica;
- API voor het wisselen van actieve Patroni-master.
Ze zijn toegankelijk via de MCS cloud API en de webconsole.
Демо
Om de mogelijkheden van een PostgreSQL-cluster in de MCS-cloud te testen, gaan we kijken hoe een live-applicatie zich gedraagt in geval van problemen met het DBMS.
Hieronder staat de code voor een applicatie die kunstmatige gebeurtenissen registreert en op het scherm rapporteert. In geval van fouten zal het dit melden en zijn werk in een lus voortzetten totdat we het stoppen met de combinatie 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")
De applicatie vereist dat PostgreSQL werkt. Laten we een cluster in de MCS-cloud maken met behulp van de API. In een gewone terminal, waar de variabele OS_TOKEN een token bevat voor toegang tot de API (kan worden verkregen met de opdracht openstack token issue), typen we de volgende opdrachten:
Maak een cluster:
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

Wanneer het cluster overschakelt naar de status ACTIEF, krijgen alle velden huidige waarden - het cluster is gereed.
In GUI:

Laten we proberen verbinding te maken en een tabel te maken:
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=>

In de applicatie geven we de huidige instellingen aan voor het verbinden met PostgreSQL. We zullen het adres van de TCP-balancer specificeren, waardoor het niet meer nodig is om handmatig naar het masteradres over te schakelen. Laten we het lanceren. Zoals u kunt zien, zijn de gebeurtenissen met succes in de database geregistreerd.

Geplande hoofdomschakeling
Laten we nu de werking van onze applicatie testen tijdens een geplande hoofdschakelaar:

Wij monitoren de aanvraag. We zien dat de applicatie inderdaad wordt onderbroken, maar dit duurt slechts enkele seconden, in dit specifieke geval maximaal 9.

Auto ongeluk
Laten we nu proberen de crash van een virtuele machine, de huidige master, te simuleren. U kunt de virtuele machine eenvoudigweg uitschakelen via de Horizon-interface, maar dit zou een normale afsluiting zijn. Een dergelijke overstap wordt door alle diensten verwerkt, inclusief Patroni.
We hebben een onvoorspelbare shutdown nodig. Daarom heb ik onze beheerders gevraagd om de virtuele machine - de huidige master - op een niet-standaard manier af te sluiten voor testdoeleinden.

Tegelijkertijd bleef onze applicatie werken. Een dergelijke noodschakeling van de master kan uiteraard niet onopgemerkt blijven.
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
Zoals u kunt zien, kon de applicatie in minder dan 30 seconden verder werken. Ja, een bepaald aantal servicegebruikers zal tijd hebben om problemen op te merken. Dit is echter een ernstige serverstoring; dit komt niet vaak voor. In dit geval zou een persoon (beheerder) nauwelijks de tijd hebben gehad om zo snel te reageren, tenzij hij in de console in de aanslag zat met een schakelscript.
Uitgang
Het lijkt mij dat een dergelijk cluster een enorm voordeel biedt voor beheerders. In feite zullen ernstige storingen en storingen van databaseservers niet merkbaar zijn voor de applicatie en dus ook voor de gebruiker. U hoeft niets overhaast te repareren en over te schakelen naar tijdelijke configuraties, servers, enz. En als een dergelijke oplossing als kant-en-klare dienst in de cloud wordt gebruikt, hoeft u geen tijd te verspillen aan de voorbereiding ervan. Het zal mogelijk zijn om iets interessanters te doen.
Bron: www.habr.com
