Introduzione

Ogni applicazione che utilizza un database deve pensare a come gestire un aumento delle richieste e dellโ€™utilizzo di questa ultima senza comprometterne lโ€™usabilitร .

Rendere scalabile lโ€™applicazione non deve compromettere la sicurezza e lโ€™integritร  dei dati.

Un ulteriore requisito importante รจ sviluppare lโ€™architettura di un database in un modo che sia scalabile dinamicamente in base alle richieste.

Per riuscire ad ottenere tutto questo esistono gli shared database, che รจ il partizionamento orizzontale di questi ultimi.

In questo articolo vedremo quando e come effettuare lo sharding e soprattutto in che casi questo puรฒ essere necessario.

Cosa รจ lo sharding?

Lo sharding รจ il partizionamento orizzontale di un database che consiste nel separare le righe di una tabella in righe di molte tabelle differenti, chiamate partizioni.

Ogni partizione ha lo stesso schema della tabella originale, ma con righe differenti; ogni sotto-tabella quindi ha dati differenti.

Nel partizionamento verticale invece sono le colonne ad essere separate, quindi ogni partizione ha sia differenti righe che colonne.

Physical shards e logical shards

Lo sharding prevede quindi di dividere i dati presenti in una tabella in due o piรน chunks chiamati logical shard. Questi ultimi sono distribuiti in nodi fisici differenti, chiamati physical shards,

Ogni physical shard puรฒ contenere piรน logical shard.

Lo sharding di un database rispecchia la shared-nothing architecture, nel senso che ogni shard รจ autonomo, non ha bisogno potenzialmente di un nodo centrale per funzionare in quanto possiede giร  tutte le colonne; lโ€™unica differenza รจ solo nel sottoinsieme delle righe.

Qualora risulti necessario alcune tabelle di gestione dellโ€™applicazione possono risiedere in ogni physical shards.

Implementazione

Spesso lo sharding รจ implementato a livello applicativo, per cui รจ direttamente lโ€™applicazione che decide a quale shard inviare e ricevere dati.

Esistono anche alcuni DBMS che hanno delle funzionalitร  di sharding integrate per cui รจ possibile implementarlo direttamente a livello database nascondendo la logica al livello applicativo.

Benefici dello sharding

Scaling up e out

Il miglior beneficio dello sharding รจ che puรฒ facilitare lโ€™horizontal scaling, chiamato anche scaling out.

Lโ€™horizontal scaling รจ la pratica di aggiungere piรน macchine (nodi della rete) in modo da suddividere il carico e poter quindi supportare maggior traffico con una velocitร  maggiore.

Questo รจ in contrasto con il vertical scaling (scaling up) per cui non si aumentano i nodi ma si migliora lโ€™hardware dei nodi esistenti aggiungendo RAM o CPU.

Lo scaling up รจ molto piรน semplice da implementare: basta aggiornare la CPU o la RAM del server e sono a posto. Questa perรฒ non รจ aumentabile allโ€™infinito per cui ad un certo momento non รจ piรน sufficiente ed รจ necessario implementare qualche tecnica di scaling out.

Velocitร  delle query

Quando ho un database monolitico con milioni di righe, le query possono risultare incredibilmente lente in quanto devono sempre far passare tutti i record presenti.

Dividendo il database in piรน parti, le query devono controllare meno righe per volta risultando quindi piรน veloci.

Sicurezza

Un ulteriore vantaggio dello sharding รจ dal punto di vista della sicurezza: avere tutto il database su un unico nodo porta ad avere un single-point-of-failure: caduto quello lโ€™intero sistema si ferma.

La divisione in nodi permette di avere un sistema che comunque regge (anche se con meno dati) in caso di fallimento di un nodo: lโ€™applicazione potrร  quindi non essere disponibile solo per alcuni utenti ma non per tutti.

Svantaggi dello sharding

Implementazione

Il primo problema dello sharding รจ la maggiore difficoltร  nellโ€™implementazione: รจ molto piรน semplice avere dati corrotti o persi in caso di errori in questa ultima.

A livello applicativo si aggiunge inoltre la complessitร  di dover reperire dati da piรน punti distinti, quindi in ogni momento รจ necessario sapere a che shard chiedere il determinato dato.

Bilanciamento degli shard

Un ulteriore problema รจ il bilanciamento degli shard: la logica con cui un dato viene messo nello shard A invece che B รจ estremamente importante in quanto devo evitare di avere uno sbilanciamento nella dimensione degli shard per cui molti piรน dati vengono inviati allo shard A invece che B.

Un database con molti dati puรฒ portare a tutti i problemi tipici della mancanza di sharding indicati sopra e viene detto database hotspot.

Difficoltร  nel ritorno ad una architettura monolitica

Una volta che un database รจ stato diviso puรฒ essere molto difficile tornare ad una architettura monolitica.

Inoltre cโ€™รจ da capire come gestire i backup della versione shared.

Eโ€™ sicuramente una operazione fattibile ma molto difficile e costosa in termini di tempo.

Non tutti i database lo supportano nativamente

Non tutti i DBMS supportano nativamente lo sharding ma รจ necessario implementare tutta la logica a mano.

Per esempio PostgreSQL non supporta lo sharding, che viene supportato solo da alcuni fork che perรฒ non sono ufficiali e magari non sono aggiornati allโ€™ultimissima versione.

Tipicamente รจ necessario procedere per versioni di DBMS pensate per lo sharding come, per esempio, MySQL Cluster o MongoDB Atlas, mentre le versioni standard non lo supportano.

Architetture per lo sharding

Una volta deciso di effettuare lo sharding รจ necessario scegliere lโ€™architettura migliore per la propria applicazione.

Key Based Sharding

Nel Key based sharding (chiamato anche hash based sharding) รจ necessario scegliere una colonna della tabella da partizionare (tipicamente che contiene dati che non cambiano nel tempo) e calcolare lโ€™hash di ognuno di questi dati.

Lโ€™hash sarร  sempre diverso ma potrei aggiungere la seguente logica: se ho tre shard lo shard da utilizzare sarร  quello indicante dal risultato dellโ€™hash modulo 3.

In questo modo posso avere solo tre valori in uscita, 0, 1 e 2: questo valore sarร  la mia shard key e indicherร  che shard utilizzare.

Il vantaggio principale di questa tecnica รจ che evita i database hotspost in quanto ogni riga ha la stessa probabilitร  di essere inserita in uno dei miei n shard.

Un altro vantaggio รจ che la localizzazione del dato negli shard รจ definito algoritmicamente, per cui รจ sempre possibile sapere ogni riga in che nodo si trova.

Lo svantaggio รจ che, qualora volessi aggiungere un nodo, rischio di dover ricalcolare tutti i valori di hash in quanto, seguendo lโ€™esempio sopra, ora ho un modulo 4 e non un modulo 3.

Durante la migrazione ne la vecchia ne la nuova funzione di hash funzionerร  correttamente e questo puรฒ portare a dei periodi di down.

Range based sharding

Con questa modalitร  viene scelto il nodo in base al fatto che il valore di una determinata colonna appartenga o meno ad un determinato range.

Per esempio se ho la colonna โ€œEtร โ€ posso mettere le persone con meno di 30 anni nello shard A, le persone tra 30 e 60 nello shard B e le altre nello shard C.

Il vantaggio principale รจ che estremamente semplice da implementare; il problema รจ che cโ€™รจ il rischio che i dati non siano distribuiti equamente tra i vari shard.

Directory Based Sharding

In questo caso รจ necessario creare una lookup table che mappa una shard key allo shard che contiene i dati.

Di fatto questa รจ una tabella statica che indica dove uno specifico dato puรฒ essere trovato.

Il vantaggio principale di questo approccio รจ la flessibilitร : nel range based sharding รจ necessario definire a priori i range, nel key based sharding la funzione di hash e la modifica di questi parametri puรฒ essere complessa.

Nel directory based sharding invece aggiungere o togliere shard รจ molto semplice, alla fine basta modifica in che modo i dati vengono inseriti nella lookup table.

Il problema รจ che prima di effettuare ogni query รจ necessario chiedere in che shard farla tramite la lookup table e questo puรฒ peggiorare le performance del sistema.

Quando fare sharding?

Se e quando fare sharding รจ complesso: aggiunge un livello di complessitร  non da poco alla gestione dei dati e puรฒ portare a parecchi mal di testa.

Eโ€™ importante non aggiungere complicazioni a applicazioni che non ne hanno alcun bisogno, come dicono i programmatori seguire sempre il metodo KISS.

Eโ€™ necessario procedere con lo sharding quando si ha a che fare che enormi quantitร  di dati o in generale quando:

  • Lโ€™ammontare dei dati dellโ€™applicazione supera la capacitร  di memoria di un singolo nodo
  • Il numero di letture e scritture di un database super quelle che puรฒ gestire un singolo nodo
  • La banda richiesta supera la banda massima supportata da un nodo

In ogni caso prima di procedere con lo sharding รจ necessario effettuare tutte le possibili ottimizzazioni come:

  • Lavorare con un database remoto che non risiede nello stesso server dellโ€™applicazione;
  • Implementare il caching dei dati che sono stati richiesti da poco tempo;
  • Implementare una o piรน repliche in sola lettura (le scritture vanno sempre sul server principale mentre le letture vengono effettuare dalle repliche). In questo modo posso suddividere il carico dalla stessa macchina senza effettuare sharding o partizionamenti;
  • Migliorare lโ€™hardware del server

Conclusione

Lo sharding รจ una ottima soluzione per scalare un database orizzontalmente in modo flessibile ma porta ad un aumento di complessitร  non indifferente.

I vantaggi che posso avere possono essere superati dal maggiore tempo richiesto nella gestione dellโ€™architettura distribuita.

Prima di procedere รจ quindi importante avere ben chiara la propria situazione in modo da fare scelte oculate e non affrettate.