Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Oghje, alta dispunibilità di servizii hè necessaria sempre è in ogni locu, micca solu in grandi prughjetti caru. I siti temporaneamente indisponibili cù u missaghju "Scusate, u mantenimentu hè in corso" sò sempre cumuni, ma di solitu causanu un surrisu condescending. Aghjunghjemu à sta vita in i nuvuli, quandu per lancià un servitore supplementu avete bisognu solu una chjama à l'API, è ùn avete micca bisognu di pensà à l'operazione "hardware". È ùn ci hè più scusa perchè un sistema criticu ùn hè statu custruitu in modu affidabile usendu tecnulugia di cluster è redundancy.

Vi diceremu quali suluzioni avemu cunsideratu per assicurà l'affidabilità di e basa di dati in i nostri servizii è ciò chì avemu vinutu. In più una demo cù cunclusioni à longu andà.

Legacy in High Availability Architecture

Questu hè ancu megliu vistu in u cuntestu di u sviluppu di diversi sistemi opensource. E soluzioni legacy sò state custrette à aghjunghje tecnulugii d'alta dispunibilità cum'è a dumanda aumentava. È a so qualità variava. Soluzioni di a prossima generazione ponenu una alta dispunibilità in u core di a so architettura. Per esempiu, MongoDB pone u clustering cum'è u so casu d'usu primariu. U cluster scales horizontally, chì hè un forte vantaghju cumpetitivu di stu DBMS.

Riturnemu à PostgreSQL. Questu hè unu di i più antichi prughjetti opensource populari, a prima liberazione di quale hè accadutu in l'annu 95 di u seculu passatu. Per un bellu pezzu, a squadra di u prugettu ùn hà micca cunsideratu alta dispunibilità per esse un prublema chì deve esse trattatu da u sistema. Dunque, a tecnulugia di replicazione per a creazione di copie di dati hè stata integrata solu in a versione 8.2 in u 2006, ma hè stata basata in u schedariu (trasportu di log). In u 2010, a versione 9.0 hà introduttu a replicazione in streaming, è hè a basa per creà una larga varietà di clusters. Questu, in fattu, hè assai surprisante à e persone chì anu familiarizatu cù PostgreSQL dopu à Enterprise SQL o NoSQL mudernu - a suluzione standard da a cumunità hè solu un paru maestru-replica cù replicazione sincrona o asincrona. À u listessu tempu, in stock, u cambiamentu di u maestru hè fattu manualmente, è u prublema di cambià i clienti hè ancu prupostu per esse risolta indipindente.

Cumu avemu decisu di fà PostgreSQL affidabile è ciò chì avemu sceltu per questu

In ogni casu, PostgreSQL ùn saria micca diventatu cusì populari s'ellu ùn ci era micca un gran numaru di prughjetti è arnesi chì aiutanu à custruisce una suluzione tolerante à i difetti chì ùn necessitanu micca attenzione constante. In u nuvulu Mail.ru Soluzioni Cloud (MCS) servitori PostgreSQL unichi è coppie master-replica cù replicazione asincrona sò dispunibuli da u lanciu di DBaaS.

Naturalmente, vulemu fà a vita più faciule per tutti è rende dispunibule una installazione PostgreSQL chì puderia serve cum'è a basa per i servizii altamente dispunibili, senza avè da monitorà constantemente è svegliate di notte per fà u cambiamentu. In questu segmentu ci sò vechji suluzioni pruvati è una generazione di novi utilità chì utilizanu l'ultimi sviluppi.

Oghje, u prublema di l'alta dispunibilità ùn hè micca nantu à a redundanza (chì ùn hè micca dettu), ma in u cunsensu - l'algoritmu di l'elezzione Leader. A maiò spessu, l'accidenti maiò ùn sò micca per una mancanza di servitori, ma per prublemi cù cunsensu: un novu capu ùn hè micca statu sceltu, dui capi sò apparsu in diversi centri di dati, etc. Esempiu - un accidente in un cluster Github MySQL - anu scrittu post mortem dettagliata.

A basa matematica in questa materia hè assai seriu. Da una banda, ci hè Teorema CAP, chì impone restrizioni teorichi nantu à e pussibilità di custruisce suluzioni HA, per un'altra banda, algoritmi pruvati matematicamente per a determinazione di cunsensu, cum'è Paxos и Raft. Nant'à sta basa, ci sò abbastanza populari DCS (sistemi di cunsensu descentralizati) - Zookeeper, etcd, Consul. Per quessa, se u sistema di decisione opera nantu à qualchì tipu d'algoritmu, scrittu indipindente, duvete trattà cun estrema prudenza. Dopu avè analizatu un gran numaru di sistemi, avemu stallatu nantu à Patroni, un sistema opensource sviluppatu principalmente da Zalando.

Cum'è una digressione lirica, diceraghju chì avemu ancu cunsideratu suluzioni multi-maestri, vale à dì, clusters chì ponu esse scalati horizontalmente per a registrazione. In ogni casu, per dui mutivi principali anu decisu di ùn creà micca un tali cluster. Prima, tali suluzioni anu una alta cumplessità è, per quessa, più vulnerabili. Serà difficiule di fà una suluzione stabile per tutti i casi. Siconda, in questu casu, PostgreSQL cessà di esse puri (nativu), alcune funzioni ùn saranu micca dispunibili, è alcune applicazioni ponu avè bug nascosti durante l'operazione.

Patroni

Allora cumu travaglia Patroni ? I sviluppatori ùn anu micca reinventatu a rota è pruposti à utilizà una di e soluzioni DCS pruvati cum'è a basa. Tutti i prublemi cù a sincronizazione di e cunfigurazioni, l'elezzione di un capu è u quorum sò lasciati à ellu. Avemu sceltu etcd per questu.

In seguitu, Patroni tratta di l'applicazione curretta di tutti i paràmetri di PostgreSQL è di e paràmetri di replicazione, è ancu di l'esekzione di cumandamenti nantu à u switchover è failover (vale à dì, u cambiamentu regulare è di emergenza di u maestru). Specificamenti in u nuvulu MCS, pudete creà un cluster di un maestru, una replica sincrona è una o più rèpliche asincrone. A prisenza di una replica sincrona assicura a sicurità di e dati in almenu 2 servitori, è hè sta replica chì serà u principale "candidatu maestru".

Siccomu etcd hè implementatu nantu à i stessi servitori, u numeru cunsigliatu di servitori hè 3 o 5 per quorum ottimali. Un tali cluster scales horizontally for reading (aghju scrittu annantu à scaling for writing above). Tuttavia, sia cuscenti chì e rèpliche asincrone sò propensi à lag, soprattuttu sottu carichi elevati.

L'usu di tali repliche di lettura (hot standby) hè ghjustificatu per rapportu o compiti analitici è allevia a carica nantu à u servitore maestru.

Se vulete fà un tali cluster, avete bisognu:

  • preparanu 3 o più servitori, cunfigurà l'indirizzu IP è e regule di firewall trà elli;
  • installà pacchetti per etcd, Patroni, servizii PostgreSQL;
  • cunfigurà u cluster etcd;
  • cunfigurà u serviziu patroni per travaglià cù PostgreSQL.

Hè, in tuttu, avete bisognu di cumpone currettamente una decina di schedarii di cunfigurazione è ùn sbaglià in ogni locu. Per questu, avete bisognu di utilizà un strumentu di gestione di cunfigurazione, cum'è Ansible, per esempiu. Tuttavia, ùn ci hè ancu un equilibratore TCP altamente dispunibule. Fà hè un travagliu separatu.

Per quelli chì anu bisognu di un cluster ready-made, ma ùn vulete micca tinker with all this, avemu pruvatu à simplificà a vita è hà fattu un cluster ready-made in Patroni in u nostru nuvulu, pudete pruvà per liberu. In più di u cluster stessu, avemu fattu:

  • TCP balancer; nant'à i porti diffirenti punta sempre à u maestru attuale, replica sincrona o asincrona, rispettivamente;
  • API per cambià u patrone Patroni attivu.

Pò esse accessu via l'API di nuvola MCS è a cunsola web.

Demo

Per pruvà e capacità di un cluster PostgreSQL in u nuvulu MCS, vedemu cumu si comporta una applicazione live in casu di prublemi cù u DBMS.

Quì sottu hè u codice per una applicazione chì logarà l'avvenimenti artificiali è u rapportu à u screnu. In casu d'errore, hà da rapportà questu è cuntinuà u so travagliu in un ciclu finu à chì l'arrestemu cù a combinazione 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")

L'applicazione richiede PostgreSQL per travaglià. Creemu un cluster in u cloud MCS utilizendu l'API. In un terminal regulare, induve a variàbile OS_TOKEN cuntene un token per accede à l'API (pò esse acquistatu cù u cumandimu openstack token issue), scriveremu i seguenti cumandamenti:

Crea un 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

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Quandu u cluster passa à u statu ACTIVE, tutti i campi riceveranu valori attuali - u cluster hè prontu.

In GUI:

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Pruvemu di cunnette è creà una tavola:

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=>

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

In l'applicazione indicheremu i paràmetri attuali per cunnette à PostgreSQL. Specificaremu l'indirizzu di u balancer TCP, eliminendu cusì a necessità di cambià manualmente à l'indirizzu maestru. Lanciamu. Comu pudete vede, l'avvenimenti sò cunnessi cù successu in a basa di dati.

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Cambiamentu maestru pianificatu

Avà pruvemu u funziunamentu di a nostra applicazione durante un cambiamentu maestru pianificatu:

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Seguimu l'applicazione. Avemu vistu chì l'applicazione hè veramente interrotta, ma ci vole solu uni pochi di seconde, in questu casu particulare, un massimu di 9.

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

Incidente di vittura

Avà pruvemu à simule u crash di una macchina virtuale, u maestru attuale. Puderete solu disattivà a macchina virtuale attraversu l'interfaccia Horizon, ma questu seria un chjusu regulare. Un tali cambiamentu serà trattatu da tutti i servizii, cumpresu Patroni.

Avemu bisognu di un arrestu imprevisible. Dunque, aghju dumandatu à i nostri amministratori di chjude a macchina virtuale - u maestru attuale - in modu micca standard per scopi di teste.

Cumu avemu custruitu un cluster PostgreSQL affidabile nantu à Patroni

À u listessu tempu, a nostra applicazione cuntinuava à travaglià. Naturalmente, un tali cambiamentu d'urgenza di u maestru ùn pò passà inosservatu.

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

Comu pudete vede, l'applicazione hà sappiutu cuntinuà à travaglià in menu di 30 seconde. Iè, un certu nùmeru d'utilizatori di serviziu avarà u tempu di nutà i prublemi. Tuttavia, questu hè un fallimentu seriu di u servitore; questu ùn succede micca assai spessu. In questu casu, una persona (amministratore) ùn avia micca avutu u tempu di reagisce cusì rapidamente, salvu ch'ellu ùn era assittatu in a cunsola pronta cù un script di cambiamentu.

cunchiusioni

Mi pare chì un tali cluster furnisce un vantaghju tremendu per l'amministratori. In fatti, i guasti seri è i fallimenti di i servitori di basa di dati ùn saranu micca noti à l'applicazione è, per quessa, à l'utilizatori. Ùn avete micca bisognu di riparà nunda in fretta è cambià à cunfigurazioni tempuranee, servitori, etc. È se una tale suluzione hè aduprata cum'è un serviziu prontu in u nuvulu, allora ùn avete micca bisognu di perdi tempu per preparà. Serà pussibule di fà qualcosa di più interessante.

Source: www.habr.com

Cumprate un hosting affidabile per i siti cù prutezzione DDoS, servitori VPS VDS 🔥 Cumprate un hosting di siti web affidabile cù prutezzione DDoS, servitori VPS VDS | ProHoster