Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Scalabilità: lo Sharding

Usare MongoDB per configurare in Sharding diversi nodi, migliorando le prestazioni, la resistenza ai guasti e la scalabilità di un database NoSQL.
Usare MongoDB per configurare in Sharding diversi nodi, migliorando le prestazioni, la resistenza ai guasti e la scalabilità di un database NoSQL.
Link copiato negli appunti

MongoDB è noto per la sua capacità di contenere una gran mole di dati. Una delle caratteristiche più appetibili di questo DBMS è rappresentata dalla facilità con cui è possibile "scalare", in particolare per quel che riguarda la scalabilità orizzontale. Esistono infatti due tipi di scalabilità:

  • la scalabilità verticale si riferisce all’incremento delle prestazioni o delle capacità di storage di un sistema, potenziando un singolo nodo;
  • la scalabilità orizzontale invece si ottiene aumentando il numero di nodi.

Quindi, dal momento che MongoDB è orientato alla scalabilità orizzontale, ci stiamo fondamentalmente riferendo alla possibilità di realizzare un cluster di database MongoDB per permettere, da un lato, di aumentare le capacità di storage, dall'altro di aumentarne le prestazioni in termini di tempi di risposta. Per sharding si intende la tecnica per la creazione di un database distribuito (anche detto sharded cluster) in cui ogni nodo contiene una porzione del database.

Architettura di uno sharded cluster

In MongoDB per realizzare un cluster in sharding sono necessari tre componenti, almeno uno per tipo:

  • router mongos: si tratta di un nodo speciale che non contiene dati, ma funge da interfaccia alle applicazioni client. Infatti, le applicazioni esterne non devono preoccuparsi dell’architettura del sistema, ma possono solamente connettersi ad uno di questi nodi come se fosse un semplice database MongoDB. Tutte le query e le operazioni di scrittura vengono quindi inviate ai router, che le smistano al cluster. Come vedremo, per avviare un router si usa l’applicazione mongos, presente nel bundle di installazione di MongoDB.
  • shard: può essere o una istanza di MongoDB (mongod) oppure un intero Replica Set, che abbiamo visto nella lezione precedente. Ovviamente, in fase di test è più semplice usare un singolo nodo, ma in fase di realizzazione di un database di produzione è raccomandato l’uso di Replica Set: così facendo, in caso di un fallimento di un nodo si evitano perdite permanenti di dati.
  • config Server: si tratta di un’istanza di mongod che contiene informazioni sull’architettura del cluster. Il config server è molto importante perché rappresenta l'entità che "sa" come i dati sono distribuiti nel cluster, e quindi come reperirli o a quale nodo inviare le operazioni da effettuare. Un cluster può includere anche diversi config server, ed infatti, per le architetture di produzione, si raccomanda di utilizzarne almeno tre. Utilizzarne uno solo è infatti un pericolo, perché in caso di guasto tutto il cluster diventa inutilizzabile.

Per un’architettura di produzione sicura, le raccomandazioni sono:

  • utilizzare almeno un router mongos. L’aumento del numero di router è indicato quando ci sono molte letture e i router sono molto sovraccaricati;
  • almeno tre config server, installati in macchine diverse. Infatti, come già detto, un config server rappresenta un single point of failure, quindi è bene aumentarne la ridondanza.
  • almeno due shard, realizzati tramite Replica Set.

Avvio e configurazione di un cluster in sharding

Ora vediamo come realizzare un cluster. Ovviamente, per un ambiente di produzione si raccomanda l'uso di una sola macchina per ogni nodo del server. Tuttavia, soprattutto in fase di test, è utile e possibile avviarli tutti sulla stessa macchina: è sufficiente prestare attenzione a non usare le medesime porte, evidando errori.

Per prima cosa avviamo i config server:

> mongod --configsvr --dbpath mongoconfig --port 27033

Tramite l’opzione --configsvr abbiamo istruito mongod di avviarsi come config server. Le altre opzioni sono le consuete impostazioni: il percorso su disco dei file del database e la porta usata.

Per realizzare un cluster di test, possiamo avviare anche un solo config server. Se vogliamo avviarne di più, è sufficiente eseguire lo stesso comando sulle altre macchine.

Ora possiamo avviare il nostro primo router. Dobbiamo usare il programma mongos e, nella riga di comando, specificare l’indirizzo o gli indirizzi dei config server che abbiamo avviato, eventualmente separati da una virgola. La limitazione è che possiamo indicarne o tre o uno solo per ogni router:

> mongos --configdb configserver1:27033

Non ci resta che avviare i nostri shard. Andiamo quindi sulle rispettive macchine e avviamo altrettanti Replica Set, come abbiamo visto nella lezione precedente, oppure altrettante istanze di MongoDB, come faremo adesso (per semplicità):

> mongod --dbpath mongoconfig --port 27022

A questo punto abbiamo avviato tutti i nodi del nostro cluster, dobbiamo semplicemente configurarlo. Utilizzando la shell mongo, ci connettiamo al nostro server mongos. Se non ci troviamo sulla stessa macchina, dobbiamo specificare l’host (supponiamo sia mongocluster) e la porta (il default è 27017 per mongos):

> mongo --host mongocluster --port 27017

Nella consueta shell, ora dobbiamo configurare il cluster con gli shard che abbiamo avviato. Infatti, connettendoci a mongos, stiamo in realtà parlando con i config server che gestiscono effettivamente il cluster, ma che sono ancora inconsapevoli degli shard che sono stati avviati. Per questa operazione usiamo il metodo addShard dell’oggetto sh. Invochiamo il metodo per ogni shard che abbiamo avviato:

> sh.addShard("shard1:27022")

Dopo qualche secondo il cluster è configurato e pronto per essere usato. Possiamo connetterci tramite la shell mongo al router e usarlo come una normale istanza di MongoDB. Ma ciò non significa che lo sharding delle collezioni di oggetti avverrà automaticamente, perché dobbiamo ancora istruire MongoDB su quali collezioni vanno frammentate nei nodi e come devono essere frammentate.

Abilitazione dello sharding delle collezioni

Per prima cosa dobbiamo abilitare lo sharding sui singoli database, con il metodo enableSharding. Ad esempio:

> sh.enableSharding("bookstore")

Ora dobbiamo istruire il cluster sulla strategia di distribuzione delle collezione tra i nodi. La strategia viene definita in base alla shard key utilizzata. Una shard key è un campo indicizzato che deve essere presente in tutti i documenti di una collezione, e che stabilisce come essa debba essere suddivisa in parti (dette chunk). La shard key può essere definita in due modi:

  • basata su intervalli (range-based): questo tipo di indice partiziona la collezione in base al fatto che il valore della shard key sia presente in un intervallo di valori. In questo modo documenti con valori paragonabili nella shard key rimarranno nello stesso nodo del cluster. Lo svantaggio è che, se la collezione ha una preponderanza di valori in un certo intervallo della shard key, avremo un nodo molto più carico degli altri;
  • basata su hash (hash-based): la collezione viene suddivisa in base all'hash del valore di uno shard key. L’effetto è che se anche ci sono valori molto simili per una certa shard key, i rispettivi documenti saranno in nodi diversi, quindi il carico sarà più distribuito sul cluster. Però il recupero di documenti “vicini” causerà un maggior traffico di rete rispetto al caso di una shard key basata su intervalli.

La scelta di quali campi usare nella shard key è delicata, e va ponderata in base all’uso che faremo dell’applicazione.

Consideriamo ad esempio un e-commerce di libri e una enorme collezione di libri in vendita. Ovviamente ha senso mettere in sharding questa collezione perché è molto grande. Una collezione del genere potrebbe essere impostata in sharding in base al codice ISBN, e per suddividere equamente il carico sul cluster potremmo usare una shard key hash-based.

Innanzitutto creiamo l’indice sul codice ISBN, se non l’abbiamo già fatto. Questo è infatti un requisito imprescindibile:

> db.books.ensureIndex( { isbn: 1})

A questo punto dobbiamo solamente applicare lo sharding alla collezione, specificando la shard key:

> sh.shardCollection("bookstore.books", { isbn: "hashed" })

Indicando il campo come "hashed" abbiamo creato una shard key hash-based. Se avessimo voluto specificare una shard key basata su intervalli avremmo scritto:

> sh.shardCollection("bookstore.books", { isbn: 1 })

Ora la nostra collezione si trova in sharding nel nostro cluster. Ogni volta che inseriremo un elemento nella nostra collezione, il cluster deciderà in base alla shard key a quale chunk appartiene, e lo invierà allo shard del cluster responsabile di quel chunk. Il bello di tutto ciò è che tali meccanismi sono del tutto trasparenti: dal punto di vista dell'utilizzatore finale, infatti, non c'è alcuna differenza nello scambio di dati con un cluster o con una singola istanza di MongoDB.

Infine segnaliamo un metodo utile per conoscere la suddivisione della collezione, nonchè lo stato del cluster, tramite un report abbastanza dettagliato:

> sh.status()

Ti consigliamo anche