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.