Database sharding – Cand si cum implementam

shards_drawingAsa cum va spuneam intr-un articol anterior, am initiat un proiect ce va necesita resurse mai mari ca de obicei si, implicit, o planificare atenta.
Una din marile probleme ale aplicatiei pe care ma apuc sa o construiesc este aceea a marimii bazei de date si, in consecinta, a vitezei de acces la aceasta, si din aceasta cauza am ales sa ma orientez catre o solutie de database sharding.

In general, astfel de solutii trebui sa fie adoptate/planificate devreme pentru ca scalingul in timp sa se faca usor si fara rescrieri de cod chiar daca in prima perioada de viata a aplicatiei nu se va folosi sistemul la reala lui valoare.

Ce inseamna database sharding?
A decomposition of a database into multiple smaller units that can handle requests individually; A breaking into shards; A shard is a method of horizontal partitioning in a database or search engine.

Ce inseamna database sharding dincolo de aceste definitii si cum ne poate ajuta in viata reala in exploatarea unei aplicatii?

In momentul in care proiectam o aplicatie trebuie sa ne gandim si la momentul in care aceasta va creste, considerand ca are potential de crestere.
Aceasta crestere se traduce, in general, prin accesari mai multe ale aplicatiei care inseamna consum mai mare de resurse. Desi in zilele noastre hardware-ul nu mai costa mult si pe masura ce trece timpul preturile scad exista totusi situatii in care investitia in hardware mai puternic nu ajuta aplicatia.
La un moment dat investitiile in hardware devin din ce in ce mai scumpe pentru o crestere a performantei aplicatiei din ce in ce mai mica.

Unde apar cel mai des probleme?

  • la serverul web apar probleme la accesul la fisiere si la procesarea requesturilor: acestea se rezolva prin introducerea de noi servere web si balansarea requesturilor care vin catre acestea; exista solutii accesibile pentru rezolvarea acestei probleme, atat hardware cat si software
  • la accesul la baza de date: problemele apar atat la scrierea in baza de date cat si la citire; la un moment dat chiar si o arhitectura cu replicare (master – slave) poate fi ineficienta pentru ca probleme apar datorita tabelelor foarte mari, cu foarte multe inregistrari si ale index-ilor care ajung la dimensiuni mari.

Cum ne ajuta database sharding in aceasta situatie?

Mergand pe o astfel de arhitectura vom distribui logic o baza de date pe mai multe servere. Structura ramane in esenta aceeasi (voi reveni asupra acestui subiect) dar pe fiecare server vom avea baze de date mai mici, cu mai putine inregistrari si care vor fi mult mai rapide decat o baza de date unica.

Mergand pe principiul “learning by example” hai sa traducem ce am spus pana acum printr-un exemplu.

Sa consideram ca avem o aplicatie in care avem utilizatori si mesaje trimise intre acestia. Cum am aplica database sharding in aceata situatia?

Consideram ca in prima faza avem nevoie de 2 servere de baze de date. Structura tabelelor ramane aceeasi in ambele baze de date, singura diferenta ar fi ca pe serverul Alpha vom stoca toti userii al caror id este impar iar pe serverul Beta vom stoca userii al caror id este par.
Pe fiecare dintre servere vom stoca si mesajele care tin de userii respectiv, si anume: pe serverul Alpha vom stoca mesajele trimise si primite de userii cu id impar iar pe serverul Beta vom stoca mesajele trimise si primite de userii cu id par.

Da, ati observat bine, apare o dublare a mesajelor stocate in baza de date dar facand aceasta dublare ne asiguram ca toate informatiile pentru un user vor fi stocate pe shard-ul (serverul, in cazul acesta) pe care este stocat userul.

Acesta este un exemplu simplist care adreseaza o problema simpla.
Pentru situatii mai complexe exista si alte solutii pe care le vom adresa in continuare.

Ramanand inca un pic la acest exemplu: cum lucram din punctul de vedere al aplicatiei cu o astfel de arhitectura a bazei de date?
Simplu: orice request de conectare la baza de date va contine si id-ul userului iar in layerul care se ocupa de conectarea la baza de date va trebui sa decidem la care server ne conectam in functie de id-ul de user trimis.

Moving on:  Tipuri de implementari de database sharding

choicesSunt mai multe moduri in care putem implementa database sharding, in functie de necesitatile aplicatiei pe care o proiectam.
Fiecare modalitate de implementare pentru database sharding are dezavantajele si avantajele sale, noua ne revine insa rolul de a alege cea mai buna solutie pentru necesitatile proiectului nostru.

  1. Partitionare pe verticala
    In aceasta situatie informatiile sunt impartite pe mai multe servere, entitati din baza de date pe diferite servere (una sau mai multe entitati pe un shard). Exemplu: userii merg pe un server, mesajele pe alt server, referintele la pozele salvate de acestia pe alt server.
    Referinta la sharduri in aceasta situatie se face in functie de entitatea accesata (vrem mesaje -> luam de pe shard 1, vrem imagini -> luam de pe shard 5) iar identificatorul unic pe toate shardurile trebuie sa fie user id-ul in aceasta situatie.
    Un astfel de set-up este bun doar in anumite situatii, este relativ usor de implementat, dar nu poate face fata la cresteri mari pe un anume tip de date. Exemplu: sa zicem ca numarul de useri are o crestere care nu pune probleme dar pot exista peak-uri de trafic care pot duce la cresteri ne-previzionate ale numarului de imagini. In aceasta situatie sistemul acesta nu ar face fata la o astfel de crestere.
  2. Partitionare in functie de intervale
    Acest sistem este destul de bun pentru aplicatii financiare, de exemplu, si presupune salvarea datelor pe un shard in functie de anumite intervale ce pot fi definite.
    Exemplu: salvam clienti si contracte pe un shard iar datele de facturare le salvam in functie de an: pentru 2008 pe shard A, pentru 2009 pe shard B, etc.
    O astfel de solutie poate fi folosita atunci cand incarcarea pe un shard poate fi previzionata.
  3. Partitionare in functie de ID
    In aceasta situatie copiem pe fiecare shard aceeasi structura de baza de date si definim o entitate principala a aplicatiei, de exemplu userul.
    Consideram ca avem n sharduri si scriem / citim informatii din shard-uri in functie de id-ul userului in modul urmator: pentru user id de forma n+1 folosim shardul 1, pentru user id de forma n+2 folosim shardul 2, pentru user id de forma n+n folosim shard-ul n.
    O astfel de solutie este buna atunci cand putem aproxima inca de la inceput de cate shard-uri vom avea nevoie. Un alt avantaj este si faptul ca toate cele n sharduri vor fi incarcate in mod egal la inceput.
    Problemele care apar sunt legate de lipsa de balansare care poate aparea intre sharduri in timp si de greutatea cu care poate fi marit numarul de sharduri daca apare aceasta necesitate.
  4. Partitionare bazata pe director de relatii ID  – tip resursa – shard
    Ganditi-va la un sistem in care la fiecare request catre baza de date trimitem suplimentar si un identificator al entitatii pe care dorim sa o accesam si id-ul acesteia. Traducerea de la id si tip resursa la shard-ul ce trebuie accesat se face folosind un sistem gen dictionar / director care contine toate aceste referinte.
    In felul acesta avem un director central care contine regulile de traducere si n sharduri pe care avem informatii.
    Un astfel de sistem este alegerea cea mai buna pentru situatia in care nu putem face previziuni de crestere. Acest sistem ne ajuta si in situatia in care suntem nevoiti sa facem balansari intre sharduri (sa mutam entitati intregi de pe un shard pe altul sau sa divizam o entitate).

Cam acestea sunt tipurile de sharding care se pot implementa si, asa cum spuneam, alegerea va apartine in functie de particularitatile fiecarui proiect.

Cand sa NU folosim database sharding

Sunt situatii in care nu este nevoie sa folosim database sharding, sunt si alte solutii pe care le putem folosi pana sa ajungem la sharding.
Putem folosi cache de sql, sql proxy, putem chiar rula anumite query-uri in memorie folosind, de exemplu, memcache. Sau putem folosi hardware mai bun.

Un astfel de exemplu este cel al echipei de la 37signals. Mai multe detalii aici.

Inainte de incheiere

In researchul pe care l-am facut am gasit o prezentare foarte interesanta a celor de la NETLOG. Vedeti mai jos embedul de pe slideshare.

Daca ti-a placut acest articol citeste si:

  1. No comments yet.

  1. October 21st, 2009