MongoDB 4.0

MongoDB e' un moderno database documentale NoSQL che al tempo stesso offre le piu' avanzate funzionalita' di replica dati e di ricerca in parallelo.

MongoDB e' uno dei piu' diffusi DB NoSQL grazie alla sua velocita', alla flessibilita, alla semplicita' di installazione ed utilizzo.
MongoDB e' un software Open Source distribuito con licenza GNU (Engine) ed Apache (per i driver). E' disponibile una versione Enterprise che fornisce funzionalita' ulteriori (eg. data encryption, auditing).

Questo documento presenta gli aspetti principali di MongoDB 4.0 [NdE 2Q18]: Installazione, Utilizzo, Amministrazione, (Replica Set, Shard Cluster), ... Varie ed eventuali,
Per le versioni precedenti e per un'introduzione generale e' possibile consultare il documento Introduzione a MongoDB.

Installazione

MongoDB e' disponibile per tutti i sistemi x64 UNIX-based, sulle piattaforme MS-Windows, su Mac OS X [NdA anche con Homebrew] e su Docker. MongoDB puo' anche essere utilizzato in Cloud: MongoDB Atlas e' l'ambiente DB fully managed e MongoDB Stitch consente di creare applicazioni serverless entrambe sono forniti direttamente da MongoDB Inc. Tutti i dettagli si trovano sul sito ufficiale.

Nel seguito vediamo l'installazione su CentOS 7 della versione Community. Una volta impostato il repository /etc/yum.repos.d/mongodb-org-4.0.repo con:

[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc

basta lanciare il comando:

# yum install mongodb-org

In questo modo vengono installati il demone (mongod) che gestisce il DB, la shell di accesso (mongo), il demone per il routing (mongos) ed i tool di gestione (eg. mongotop, mongodump) della versione Community.

Gia' fatto! MongoDB si puo' gia' utilizzare, pero' un minimo di configurazione e' opportuna.

Sul sistema operativo le configurazioni piu' importanti sono: chown, ulimit, NTP, tcp_keepalive_time, vm.swappiness, hugepages, ... [cfr. documentazione ufficiale].

Il file di configurazione di MongoDB e' /etc/mongod.conf. Tra i parametri piu' comunemente utilizzati: storage.dbPath, net.bindIp, security.authorization, ... ad esempio:

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

storage:
  dbPath: /data/mongo
  journal:
    enabled: true
#  engine:
#  wiredTiger:

processManagement:
  fork: true  
  pidFilePath: /var/run/mongodb/mongod.pid 
  timeZoneInfo: /usr/share/zoneinfo

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1
#  bindIp: 0.0.0.0,::

security:
  authorization: enabled
#   keyFile: 

#operationProfiling:
#replication:
#  replSetName: "repl0"
#sharding:

## Enterprise-Only Options
#auditLog:
#snmp:

Per far rileggere il file di configurazione... basta riavviare il servizio!

Utilizzo

Il primo utilizzo di MongoDB e' dalla sua shell di comandi: mongo. Da linea di comando si possono eseguire tutte le operazioni:

$ mongo > use test > db.myCollection.insertOne( ... { ... ename: "SCOTT", ... sal: 3000 ... } ... ) > db.myCollection.find() > db.myCollection.deleteMany() > db.myCollection.drop() ...

Per quelli piu' giovani di me, non abituati alla command line, sono disponibili diverse GUI di semplice utilizzo. Le GUI disponibili sono moltissime, le piu' utili, a mio avviso, sono: MongoDB Compass, NoSQLBooster, Studio 3T, ... Molte GUI hanno versioni Free ed Enterprise con funzionalita' crescenti [NdA la mia preferita era Robomongo, divenuta Robo 3T ma al momento non e' ancora non disponibile su MongoDB 4.0].

MongoDB puo' essere utilizzato da vari linguaggi. Naturalmente questa e' la modalita' di accesso principale per chi sviluppa applicazioni! Sono disponibili driver per i piu' importanti linguaggi di programmazione (eg C, C++, C#, Java, Perl, PHP, Python, Node.js, Ruby, ...).

Amministrazione

Su MongoDB per default l'autenticazione non e' abilitata (parametro --auth al lancio del comando mongod o opzione security.authorization: enabled in /etc/mongod.conf). Ovviamente per un'installazione di produzione e' necessario abilitarla! Abilitando l'autenticazione va definito almeno un utente "amministratore" che possa poi autorizzare tutti gli altri utenti. Il privilegio minimo e' userAdminAnyDatabase.
Le utenze sono definite per database, le utenze del database admin possono agire su tutti i database. L'algoritmo per la generazione della password e' SHA256(MD5(utente:mongo:password)) senza salt. La security checklist riporta tutte le informazioni utili per un'installazione sicura di produzione.
Con i comandi seguenti vengono definiti utenti con privilegi, o meglio cui vengono assegnati ruoli differenti:

use admin db.createUser( { user: "admin", pwd: "abc123", roles: [ { role: "root", db: "admin" } ] } ) db.createUser( { user: "App1Owner", pwd: "xxx", roles: [ { role: "dbOwner", db: "application1" } ] } ) db.grantRolesToUser( "App1_rw", [ { role: "readWrite", db: "application1" } ] ) db.grantRolesToUser( "backup", [ { role: "backup" } ] )

Con un'installazione su CentOS 7 vengono automaticamente predisposti ed abilitati gli script di start/stop dei servizi. Ad esempio per avviare MongoDB:
 systemctl start mongod

La gestione dello spazio e l'ottimizzazione dell'IO sono fondamentali per MongoDB. L'utilizzo corretto di indici consente di ottenere le prestazioni ottimali. La dimensione degli indici (cfr. db.collection.totalIndexSize()) e del working set non deve superare la quantita di RAM disponibile.

Sono possibili due tipologie di backup: fisico o logico. Il backup fisico si effettua a database spento e deve comprendere tutti i datafile. In alternativa e' possibile utilizzare uno snapshot completo del File System.
Il backup logico si effettua con l'utility mongodump (il restore con l'utility mongorestore). L'utility mongoexport effettua un backup in formato JSON o CSV ma non va utilizzato come strumento di backup.

Su /var/log/mongodb/mongod.log (per default) e' riportato il log di MongoDB. I livelli previsti sono: F Fatal, E Error, W Warning, I Informational (impostato con 0), D Debug (impostato con valori da 1-5). L'impostazione si effettua con il comando db.setLogLevel(<level> [, <component>]) e puo' essere differente per ogni componente. Per conoscere il livello impostato il comando e' db.adminCommand({getParameter: 1, logLevel: 1});
Nello stesso file vengono anche riportati i messaggi relativi al profiling. Il profiling e' particolarmente pesante percio' per default e' disabilitato. L'impostazione si effettua con il comando db.setProfilingLevel(<level> [, <slow_ms>]) ed il controllo con db.getProfilingLevel() e db.getProfilingStatus().

Vediamo alcuni comandi utili per l'amministrazione:

load("myJScript.js")

host = db.serverStatus().host;
prompt = function() {
             return db+"@"+host+" > ";
         }

db._adminCommand("listDatabases").databases.forEach(function (d) {
   mdb = db.getSiblingDB(d.name);
   printjson(mdb.stats());
})

db._adminCommand("listDatabases").databases.forEach(function (d) {
   mdb = db.getSiblingDB(d.name);
   mdb.getCollectionNames().forEach(function(c) {
      s = mdb[c].stats();
      printjson(s);
   })
})

db.system.users.find().pretty()

var ops = db.currentOp({
    active: true,
    //waitingForLock : true,
    //secs_running : { $gt : 3 }, 
    //$ownOps:true,
    //$all:true, 
    //ns : /^db\.collection/
});
(ops.inprog || ops)

Da ultimo... e' importante sottolineare che MongoDB fornisce un'ampia serie di funzionalita' di sicurezza [NdA per cui in qualche caso e' richiesta la versione Enterprise]: encryption at-rest, network encryption, strong authentication, auditing, ... Il carattere introduttivo di questa paginetta non ci consente di presentarle in dettaglio.

Replica

La distribuzione e la replica dei dati su piu' server e' una caratteristica fondamentale dei database NoSQL per supportare i BigData.
MongoDB dispone di due tecniche per la distribuzione dei dati: i Replica Set e lo Sharding.

Piu' database MongoDB possono essere sincronizzati tra loro in modo molto semplice. I database vengono aggiornati tra loro con una replicazione peer-to-peer incrementale implementata nativamente nell'engine.
L'alta affidabilita' (HA) in MongoDB e' basata sui Replica Set (RS): un gruppo di nodi in cui il primario riceve le scritture e gli altri nodi le applicano. In caso di caduta di un nodo i replica set si allineano automaticamente e, se necessario, eleggono un nuovo primario. E' sempre opportuno utilizzare un numero dispari di nodi di Replica Set; se necessario e' possibile configurare un nodo Arbiter che non gestisce dati e quindi ha requisisti molto ridotti.
Per l'attivazione delle replica e' opportuno che sia stata attivata l'Internal Authentication, in modo che i nodi possano tra loro riconoscersi. Si possono utilizzare Keyfiles o certificati x.509 (meglio se emessi da una Certification Authority).
Ecco i semplici comandi per configurare un Replica Set di 3 nodi e controllare lo stato:

rs.initiate( { _id : "rs-cc", members: [ { _id: 0, host: "mongodb1.xenialab.it:27017" }, { _id: 1, host: "mongodb2.xenialab.it:27017" }, { _id: 2, host: "mongodb3.xenialab.it:27017" } ] }) rs.conf() rs.status()

La replica e' trasparente dal punto di vista della programmazione. La stringa di connessione riporta tipicamente tutti i nodi:porte presenti nel replica set ed e' il driver che indirizza verso il nodo corretto. Le applicazioni accedono via driver in scrittura verso il primary ma possono gestire le letture con modalita' differenti.
Per la scrittura e' possibile indicare il Write Concern, ovvero quanti nodi debbono aver confermato la scrittura; il default e' w: 1 (ovvero basta il primary) ma puo' essere indicato un numero superiore o "majority". Per la lettura e' possibile indicare verso quali nodi effettuarla (Read Preference Modes): primary, primaryPreferred, secondary, secondaryPreferred, nearest. Con rs.slaveOk() o db.getMongo().setSlaveOk() si conferma che la propria sessione puo' effettuare letture eventualmente consistenti su un nodo secondario.
Le transazioni multi-document [NdA nuova funzionalita' della versione 4.0] che effettuano letture debbono utilizzare la modalita' primary. Tutte le operazioni sulla stessa transazione vengono indirizzate sullo stesso membro.

Sharding

Per gestire basi dati di grandi dimensioni MongoDB permette di distribuire i dati tra nodi differenti applicando un partizionamento tra i nodi: lo sharding. La configurazione di un Sharded Cluster richiede diversi componenti: i routers (mongos), un config server, gli shard ed i relativi replica set.
In una configurazione minimale e' presente un processo mongos cui si interfacciano le applicazioni e che si occupa del routing delle richieste ai nodi corretti. La configurazione degli shard e' invece mantenuta dal MongoDB config cui e' assegnato questo unico database. Infine i diversi shard su cui sono partizionati i dati sono database MongoDB standalone o Replica Set.
Le collection poste in shard vengono divise in chunk a seconda del valore della chiave ed memorizzate su nodi diversi. Ad occuparsi della migrazione dei chunck e' il processo balancer che puo' essere attivato da ciascun nodo mongos.
Se l'architettura dello shard delle collection presenta qualche complessita' al contrario la loro gestione e' invece molto semplice. Prima va abitato lo sharding, quindi puo' essere effettuato il partizionamento di una collection per chiave (MongoDB supporta il range partitioning, l'hash partitioning e supporta il tag aware sharding):

db.runCommand( { enableSharding: agenda } ) sh.shardCollection( "mydb.agenda", { nome: "hashed" } )

Lo sharding introduce un elevato di scalabilita' orizzontale senza introdurre complessita' dal punto di vista applicativo. Dal punto di vista applicativo non vi sono differenze nell'uso di collection in shard: l'unico requisito e' quello di collegarsi ai processi di routing mongos anziche' ai nodi mongod.
La chiave di sharding va scelta con attenzione perche' una scelta errata ha impatti prestazionali significativi e non puo' essere modificata senza ricostruire la collection.

Le tecniche di replica e di shard dei dati in MongoDB non sono alternative anzi si completano tra loro. Tipicamente anche per una piccola installazione di produzione si utilizzano i Replica Set per garantire la Durability dei dati.
Lo sharding e' invece rivolto alle installazioni piu' significative anche con decine o centinaia di server dedicati e tipicamente si appoggia sulla replica nel senso che uno shard e' tipicamente mantenuto da un replica set.

Varie ed eventuali

MongoDB logo

Esistono diverse categorie di database NoSQL: MongoDB viene definito un database NoSQL documentale, ma in realta' e' spesso utilizzato su tutte le tipologie di dati. MongoDB e' molto veloce: a scapito delle proprieta' ACID (Atomicity, Consistency, Isolation, Durability) utilizza il paradigma BASE (Basically Available, Soft state, Eventual consistency), memorizza i dati in formato BSON/JSON, e' scalabile in modo nativo su piu' nodi e non fornisce un'interfaccia SQL. Dal punto di vista del teorema di CAP (Consistency, Availability, Partition tolerance) MongoDB e' considerato un database CP [NdA nella classificazione PACELC, piu' precisa, MongoDB e' P+C, E+C]. MongoDB si e' rapidamente imposto sul mercato, diventando uno tra i piu' usati database non relazionali: e' infatti considerato il piu' diffuso database NoSQL, non solo come database documentale ma su tutte le catogorie.

MongoDB e' stato sviluppato inizialmente (2007) da 10gen come un componente PaaS e' stato trasformato in un progetto Open Source (2009) con un supporto e servizi di Enterprise.
Le versioni pari di MongoDB corrispondono a quelle di produzione mentre quelle dispari sono di sviluppo ed presentano nuove funzionalita'. L'attuale versione produzione [2Q18] e' la 4.0. Nonostante l'introduzione recente di MongoDB le sue versioni presentano variazioni significative (eg. algoritmo di write, replica set, multi-document transactions, authentication, ...) ed e' quindi fortemente consigliato utilizzare l'ultima versione rilasciata. La storia delle versioni e' riassunta in questo documento:

Version
Status
Features
Last release
Date (from)
Date (to)
Notes
4.0 Production Multi-document Transactions, new string and conversion opertators for Aggregation, configurable rollbackTimeLimitSecs, ...
Deprecation: MMAPv1 Storage Engine. Desupport: MONGODB-CR authentication, pv0 replica protocol, Master-Slave Replication, TLS 1.0
4.0.62018-06
3.6 Production Default bind on localhost, more Expressive $lookup, ...
Deprecation: MONGODB-CR authentication. Desupport: HTTP REST API
3.6.92017-11
3.4 Production Membership Awareness; zoned sharding; linearizable read concerns, views, and collation; decimal 128 datatype; many new Aggregation Stages and Operators. 3.4.182016-112019-06
3.2 Production WiredTiger as default storage engine, replica set for config server, replication check enhancements, additional CRUD methods in mongo, document validation. Compass GUI. (3.2.1 2016-01) Fixes 3.2.222015-122018-09
3.0ProductionPluggable Engine Stores, WiredTiger storage engine support (document level locks, compression), SHA-1 authentication, replica set up to 50 members, support for collection-level locking in MMAPv1, better explain, ... 3.0.152015-032018-02
2.6ProductionNew writer protocol, bulk operations, Text search enabled by default, query intersection, ... 2.6.122014-042016-10
2.4ProductionV8 JavaScript Engine, Hashed indexes, better geospatial support, database-level locks instead of global locks, ... 2.4.142013-032016-03
2.2ProductionLock yielding, Reader-writers lock at database level (instead of mongod level). 2.2.72012-082014-02
2.0Production 2.0.92011-102013-03
1.8Production 1.8.52011-032012-09
1.6Production 1.6.5-post2010-082012-02
1.4ProductionOfficial RPM 1.4.52010-032012-09
1.2Production 1.22009-122011-06
1.0ProductionFrom PaaS by 10gen to Open Source 1.02009-022010-08

Per una documentazione piu' dettagliata si rimanda al sito ufficiale di MongoDB ed in particolare al manuale.


Titolo: MongoDB 4.0
Livello: Medio (2/5)
Data: 31 Ottobre 2018
Versione: 1.0.1 - 14 Febbraio 2019 ❤️ San Valentino
Autore: mail [AT] meo.bogliolo.name