Publicat pe 7 februarie 2019

date

Introducere

Orice aplicație sau site web care vede o creștere semnificativă va trebui, în cele din urmă, să se extindă pentru a permite creșterea traficului. Pentru aplicațiile și site-urile bazate pe date, este esențial ca scalarea să se realizeze într-un mod care să asigure securitatea și integritatea datelor lor. Poate fi dificil să se prezică cât de popular va deveni un site web sau o aplicație sau cât va menține popularitatea respectivă, motiv pentru care unele organizații aleg o arhitectură de baze de date care le permite să își scaleze dinamic bazele de date.

În acest articol conceptual, vom discuta despre o astfel de arhitectură de baze de date: bazele de date fragmentate. Fragmentarea a primit multă atenție în ultimii ani, dar mulți nu au o înțelegere clară a ceea ce este sau a scenariilor în care ar putea avea sens să împărțim o bază de date. Vom trece peste ce este sharding-ul, unele dintre principalele sale avantaje și dezavantaje, precum și câteva metode comune de sharding.

Ce este Sharding?

Fragmentarea este un model de arhitectură a bazei de date legat de partiționarea orizontală - practica separării rândurilor unui tabel în mai multe tabele diferite, cunoscute sub numele de partiții. Fiecare partiție are aceeași schemă și coloane, dar și rânduri complet diferite. De asemenea, datele deținute în fiecare sunt unice și independente de datele deținute în alte partiții.

Poate fi util să ne gândim la partiționarea orizontală în ceea ce privește modul în care se referă la partiționarea verticală. Într-un tabel partiționat vertical, coloane întregi sunt separate și plasate în tabele noi, distincte. Datele păstrate într-o partiție verticală sunt independente de datele din toate celelalte și fiecare conține atât rânduri, cât și coloane distincte. Următoarea diagramă ilustrează modul în care un tabel ar putea fi partiționat atât pe orizontală, cât și pe verticală:

Fragmentarea implică divizarea datelor în două sau mai multe bucăți mai mici, numite cioburi logice. Cioburile logice sunt apoi distribuite pe noduri de baze de date separate, denumite cioburi fizice, care pot conține mai multe cioburi logice. În ciuda acestui fapt, datele deținute în toate fragmentele reprezintă în mod colectiv un întreg set de date logice.

Fragmentele bazei de date exemplifică o arhitectură fără nimic partajat. Aceasta înseamnă că cioburile sunt autonome; nu partajează niciuna dintre aceleași date sau resurse de calcul. În unele cazuri, totuși, poate avea sens să replicăm anumite tabele în fiecare fragment pentru a servi drept tabele de referință. De exemplu, să presupunem că există o bază de date pentru o aplicație care depinde de ratele de conversie fixe pentru măsurarea greutății. Replicând un tabel care conține datele necesare despre rata de conversie în fiecare fragment, ar contribui la asigurarea faptului că toate datele necesare pentru interogări sunt păstrate în fiecare fragment.

Adesea, sharding-ul este implementat la nivelul aplicației, ceea ce înseamnă că aplicația include un cod care definește ce shard să transmită citește și scrie. Cu toate acestea, unele sisteme de gestionare a bazelor de date au capabilități de partajare încorporate, permițându-vă să implementați partajarea direct la nivelul bazei de date.

Având în vedere această prezentare generală a fragmentării, să trecem în revistă unele dintre aspectele pozitive și negative asociate acestei arhitecturi de baze de date.

Avantajele fragmentării

Principalul apel al partajării unei baze de date este că aceasta poate ajuta la facilitarea redimensionării orizontale, cunoscută și sub denumirea de redimensionare. Scalarea orizontală este practica adăugării mai multor mașini într-o stivă existentă pentru a răspândi sarcina și a permite mai mult trafic și procesare mai rapidă. Acest lucru este adesea contrastat cu scalarea verticală, altfel cunoscută sub numele de scaling up, care implică actualizarea hardware-ului unui server existent, de obicei prin adăugarea mai multor RAM sau CPU.

Este relativ simplu să ai o bază de date relațională care rulează pe o singură mașină și să o mărești după cum este necesar prin actualizarea resurselor sale de calcul. În cele din urmă, însă, orice bază de date nedistribuită va fi limitată în ceea ce privește stocarea și puterea de calcul, astfel încât libertatea de a scala pe orizontală face ca configurarea dvs. să fie mult mai flexibilă.

Un alt motiv pentru care unii ar putea alege o arhitectură bazată pe baze de date este accelerarea timpilor de răspuns la interogare. Când trimiteți o interogare într-o bază de date care nu a fost împărțită, este posibil să fie nevoie să caute în fiecare rând din tabelul pe care îl interogați înainte de a găsi setul de rezultate pe care îl căutați. Pentru o aplicație cu o bază de date mare, monolitică, interogările pot deveni prohibitive. Prin împărțirea unui tabel în mai multe, totuși, interogările trebuie să depășească mai puține rânduri, iar seturile lor de rezultate sunt returnate mult mai rapid.

Fragmentarea poate ajuta, de asemenea, la îmbunătățirea fiabilității unei aplicații prin atenuarea impactului întreruperilor. Dacă aplicația sau site-ul dvs. web se bazează pe o bază de date neprelucrată, o întrerupere are potențialul de a face întreaga aplicație indisponibilă. Cu o bază de date fragmentată, totuși, o întrerupere poate afecta doar un singur fragment. Chiar dacă acest lucru ar putea face unele părți ale aplicației sau ale site-ului web indisponibile pentru unii utilizatori, impactul general ar fi totuși mai mic decât în ​​cazul în care întreaga bază de date se prăbușea.

Dezavantaje ale fragmentării

Deși partajarea unei baze de date poate face scalarea mai ușoară și poate îmbunătăți performanța, poate impune, de asemenea, anumite limitări. Aici, vom discuta despre unele dintre acestea și de ce ar putea fi motive pentru a evita împrăștierea cu totul.

Prima dificultate pe care o întâmpină oamenii cu sharding-ul este complexitatea absolută a implementării corespunzătoare a unei arhitecturi de baze de date sharded. Dacă este făcut incorect, există un risc semnificativ ca procesul de partajare să poată duce la pierderea datelor sau tabele corupte. Chiar și atunci când este realizat corect, este posibil ca fragmentarea să aibă un impact major asupra fluxurilor de lucru ale echipei dvs. În loc să acceseze și să gestioneze datele cu un singur punct de intrare, utilizatorii trebuie să gestioneze datele în mai multe locații de fragmentare, ceea ce ar putea fi perturbator pentru unele echipe.

O problemă pe care utilizatorii o întâmpină uneori după ce au împărțit o bază de date este că fragmentele devin în cele din urmă dezechilibrate. Ca exemplu, să presupunem că aveți o bază de date cu două cioburi separate, una pentru clienții ale căror nume de familie încep cu literele de la A la M și alta pentru cei ale căror nume încep cu literele de la N la Z. Cu toate acestea, aplicația dvs. servește o sumă exagerată a persoanelor ale căror nume de familie încep cu litera G. În consecință, fragmentul AM acumulează treptat mai multe date decât cel din Noua Zeelandă, ceea ce face ca aplicația să încetinească și să se blocheze pentru o parte semnificativă a utilizatorilor dvs. Fragmentul A-M a devenit ceea ce este cunoscut sub numele de hotspot de bază de date. În acest caz, orice beneficii ale partajării bazei de date sunt anulate de încetiniri și blocări. Baza de date ar trebui probabil reparată și reparată pentru a permite o distribuție mai uniformă a datelor.

Un alt dezavantaj major este că, odată ce o bază de date a fost împărțită, poate fi foarte dificil să o readuceți la arhitectura sa nepericuloasă. Orice copie de rezervă a bazei de date făcută înainte de a fi fragmentată nu va include date scrise de la partiționare. În consecință, reconstruirea arhitecturii originale neîmpărțite ar necesita fuzionarea noilor date partiționate cu copiile de rezervă vechi sau, alternativ, transformarea DB partiționată înapoi într-un singur DB, ambele ar fi costisitoare și eforturi consumatoare de timp.

Un dezavantaj final care trebuie luat în considerare este că partajarea nu este acceptată în mod nativ de fiecare motor de baze de date. De exemplu, PostgreSQL nu include partajarea automată ca o caracteristică, deși este posibilă partajarea manuală a unei baze de date PostgreSQL. Există o serie de furci Postgres care includ sharding automat, dar acestea se găsesc adesea în spatele ultimei versiuni PostgreSQL și nu au alte caracteristici. Unele tehnologii de baze de date specializate - cum ar fi MySQL Cluster sau anumite produse de baze de date ca serviciu precum MongoDB Atlas - includ partajarea automată ca o caracteristică, dar versiunile vanilate ale acestor sisteme de gestionare a bazelor de date nu. Din această cauză, divizarea necesită adesea o abordare „roll your own”. Aceasta înseamnă că documentația pentru partajare sau sfaturi pentru rezolvarea problemelor sunt adesea dificil de găsit.

Acestea sunt, bineînțeles, doar câteva aspecte generale de luat în considerare înainte de a împărți. Pot exista mult mai multe dezavantaje potențiale în partajarea unei baze de date, în funcție de cazul său de utilizare.

Acum, că am acoperit câteva dintre dezavantajele și avantajele sharding-ului, vom trece în revistă câțiva arhitecți diferiți pentru baze de date fragmentate.

Sharding Architecture

După ce ați decis să vă împărțiți baza de date, următorul lucru pe care trebuie să-l aflați este modul în care veți face acest lucru. Atunci când executați interogări sau distribuiți date primite către tabele sau baze de date fragmentate, este crucial ca acestea să ajungă la fragmentul corect. În caz contrar, ar putea rezulta pierderea datelor sau interogări dureroase. În această secțiune, vom trece în revistă câțiva arhitecți obișnuiți de partajare, fiecare dintre aceștia utilizând un proces ușor diferit pentru a distribui date între fragmente.

Fragmentare bazată pe cheie

Partajarea bazată pe cheie, cunoscută și sub numele de partajare bazată pe hash, implică utilizarea unei valori preluate din datele noi scrise - cum ar fi numărul de identificare al unui client, adresa IP a unei aplicații client, un cod poștal etc. - și conectarea la o funcție hash pentru a determina la ce fragment ar trebui să meargă datele. O funcție hash este o funcție care ia ca intrare o bucată de date (de exemplu, un e-mail al clientului) și generează o valoare discretă, cunoscută sub numele de valoare hash. În cazul fragmentării, valoarea hash este un ID de fragment folosit pentru a determina pe ce fragment se vor stoca datele primite. În total, procesul arată astfel:

Pentru a vă asigura că intrările sunt plasate în fragmente corecte și într-o manieră consecventă, valorile introduse în funcția hash ar trebui să provină din aceeași coloană. Această coloană este cunoscută sub numele de cheie shard. În termeni simpli, tastele shard sunt similare cu tastele primare prin faptul că ambele sunt coloane care sunt utilizate pentru a stabili un identificator unic pentru rânduri individuale. În linii mari, o cheie fragmentă ar trebui să fie statică, ceea ce înseamnă că nu ar trebui să conțină valori care s-ar putea schimba în timp. În caz contrar, ar crește cantitatea de muncă care intră în operațiuni de actualizare și ar putea încetini performanța.

În timp ce partajarea bazată pe cheie este o arhitectură de partajare destul de comună, poate face lucrurile dificile atunci când încercați să adăugați dinamic sau să eliminați servere suplimentare într-o bază de date. Pe măsură ce adăugați servere, fiecare va avea nevoie de o valoare hash corespunzătoare și multe dintre intrările dvs. existente, dacă nu toate, vor trebui remapate la noua lor valoare hash corectă și apoi migrate la serverul corespunzător. Pe măsură ce începeți să reechilibrați datele, nici funcțiile hash noi, nici cele vechi nu vor fi valabile. În consecință, serverul dvs. nu va putea scrie date noi în timpul migrării, iar aplicația dvs. ar putea fi supusă perioadelor de nefuncționare.

Apelul principal al acestei strategii este că poate fi utilizat pentru a distribui în mod uniform datele, astfel încât să prevină hotspoturile. De asemenea, deoarece distribuie datele algoritmic, nu este nevoie să mențineți o hartă a locului în care se află toate datele, așa cum este necesar cu alte strategii, cum ar fi distribuirea bazată pe intervale sau directoare.

Fragmentare bazată pe gamă

Partajarea bazată pe intervale implică partajarea datelor bazate pe intervale de o anumită valoare. Pentru a ilustra, să presupunem că aveți o bază de date care stochează informații despre toate produsele din catalogul unui comerciant cu amănuntul. Puteți crea câteva cioburi diferite și puteți distribui informațiile fiecărui produs în funcție de intervalul de preț în care se încadrează, astfel:

Principalul beneficiu al partajării bazate pe gamă este că este relativ simplu de implementat. Fiecare fragment conține un set diferit de date, dar toate au o schemă identică una cu cealaltă, precum și baza de date originală. Codul aplicației citește doar în ce domeniu se încadrează datele și le scrie în fragmentul corespunzător.

Pe de altă parte, partajarea bazată pe intervale nu protejează datele de la distribuirea inegală, ceea ce duce la hotspoturile de bază de date menționate anterior. Privind diagrama de exemplu, chiar dacă fiecare fragment conține o cantitate egală de date, șansele sunt că anumite produse vor primi mai multă atenție decât altele. Cărțile lor respective vor primi, la rândul lor, un număr disproporționat de citiri.

Sharding bazat pe director

Pentru a implementa partajarea bazată pe director, trebuie să creați și să mențineți un tabel de căutare care utilizează o cheie de fragment pentru a urmări ce fragment deține ce date. Pe scurt, un tabel de căutare este un tabel care conține un set static de informații despre unde pot fi găsite date specifice. Următoarea diagramă prezintă un exemplu simplist de distribuire pe bază de directoare:

Aici Zona de livrare coloana este definită ca o cheie shard. Datele din cheia fragmentului sunt scrise în tabelul de căutare împreună cu orice fragment în care trebuie scris fiecare rând respectiv. Acest lucru este similar cu fragmentarea bazată pe interval, dar în loc să se determine în ce interval se încadrează datele cheii de fragment, fiecare cheie este legată de propriul fragment specific. Sharding-ul bazat pe director este o alegere bună peste sharding-ul bazat pe interval în cazurile în care cheia shard are o cardinalitate redusă și nu are sens ca un shard să stocheze o gamă de chei. Rețineți că este, de asemenea, distinct de sharding bazat pe cheie, prin faptul că nu procesează cheia shard printr-o funcție hash; doar verifică cheia cu un tabel de căutare pentru a vedea unde trebuie scrise datele.

Principalul apel al partajării bazate pe director este flexibilitatea sa. Arhitecții de partajare bazate pe intervale vă limitează la specificarea intervalelor de valori, în timp ce cele bazate pe cheie vă limitează la utilizarea unei funcții hash fixe care, așa cum am menționat anterior, poate fi extrem de dificil de modificat ulterior. Partajarea bazată pe director, pe de altă parte, vă permite să utilizați orice sistem sau algoritm doriți să atribuiți intrări de date la fragmente și este relativ ușor să adăugați fragmente dinamice folosind această abordare.

În timp ce partajarea bazată pe director este cea mai flexibilă dintre metodele de partajare discutate aici, necesitatea conectării la tabelul de căutare înainte de fiecare interogare sau scriere poate avea un impact negativ asupra performanței unei aplicații. În plus, tabelul de căutare poate deveni un singur punct de eșec: dacă devine deteriorat sau eșuează în alt mod, poate afecta capacitatea cuiva de a scrie date noi sau de a accesa datele existente.

Ar trebui să mă Shard?

Indiferent dacă ar trebui sau nu să implementăm o arhitectură de bază de date fragmentată este aproape întotdeauna o chestiune de dezbatere. Unii văd shardingul ca un rezultat inevitabil pentru bazele de date care ating o anumită dimensiune, în timp ce alții îl văd ca pe o durere de cap care ar trebui evitată cu excepția cazului în care este absolut necesar, datorită complexității operaționale pe care sharding-ul o adaugă.

Datorită acestei complexități adăugate, partajarea se efectuează de obicei numai atunci când se tratează cantități foarte mari de date. Iată câteva scenarii obișnuite în care poate fi benefic să fragmentezi o bază de date:

  • Cantitatea de date a aplicației crește pentru a depăși capacitatea de stocare a unui singur nod de bază de date.
  • Volumul de scrieri sau citiri în baza de date depășește ceea ce poate gestiona un singur nod sau replicile sale de citire, rezultând timpi de răspuns sau expirări încetinite.
  • Lățimea de bandă a rețelei solicitată de aplicație depășește lățimea de bandă disponibilă pentru un singur nod de bază de date și orice replici citite, rezultând timpi de răspuns sau expirări încetinite.

Înainte de partajare, ar trebui să epuizați toate celelalte opțiuni pentru optimizarea bazei de date. Câteva optimizări pe care ați putea dori să le luați în considerare includ:

Rețineți că, dacă aplicația sau site-ul dvs. web depășește un anumit punct, niciuna dintre aceste strategii nu va fi suficientă pentru a îmbunătăți singure performanța. În astfel de cazuri, divizarea poate fi într-adevăr cea mai bună opțiune pentru dvs.

Concluzie

Fragmentarea poate fi o soluție excelentă pentru cei care doresc să își scaleze baza de date pe orizontală. Cu toate acestea, adaugă o mare complexitate și creează mai multe puncte potențiale de eșec pentru aplicația dvs. Fragmentarea poate fi necesară pentru unii, dar timpul și resursele necesare pentru a crea și menține o arhitectură fragmentată ar putea depăși beneficiile pentru alții.

Citind acest articol conceptual, ar trebui să aveți o înțelegere mai clară a avantajelor și dezavantajelor fragmentării. Mergând mai departe, puteți utiliza această perspectivă pentru a lua o decizie mai informată cu privire la faptul dacă o arhitectură de bază de date fragmentată este sau nu potrivită pentru aplicația dvs.