MongoDB è un database NoSQL che usa documenti di tipo JSON con schemi dinamici. Quando si lavora con i database, è sempre bene avere un piano di emergenza nel caso in cui uno dei server del database si guasti. È possibile ridurre le possibilità che ciò accada utilizzando uno strumento di gestione del vostro sito WordPress.

Ecco perché è utile avere molte copie dei dati. Questo riduce anche le latenze di lettura. Allo stesso tempo, può migliorare la scalabilità e la disponibilità del database. È qui che entra in gioco la replica, cioè la pratica di sincronizzare i dati tra più database.

In questo articolo analizzeremo alcuni aspetti della replicazione (replication) di MongoDB, le sue caratteristiche e il suo meccanismo di funzionamento.

Cos’È la Replicazione in MongoDB?

In MongoDB, i replica set eseguono la replicazione. Si tratta di un gruppo di server che mantengono lo stesso set di dati durante la replicazione. Potete anche usare la replicazione di MongoDB come parte del load balancing. In questo caso, potete distribuire le operazioni di scrittura e lettura su tutte le istanze, in base al caso d’uso.

Cos’È un Replica Set in MongoDB?

Ogni istanza di MongoDB che fa parte di un determinato replica set è un membro. Ogni replica set deve avere un membro primario e almeno un membro secondario.

Il membro primario è il punto di accesso principale per le transazioni con il replica set. È anche l’unico membro che può accettare operazioni di scrittura. Con la replicazione si copia innanzitutto l’oplog (registro delle operazioni) del primario. Successivamente, si ripetono le modifiche registrate sui rispettivi dataset dei secondari. Di conseguenza, ogni replica set può avere un solo membro primario alla volta. Diversi primari che ricevono operazioni di scrittura possono causare conflitti di dati.

Di solito, le applicazioni interrogano solo il membro primario per le operazioni di scrittura e lettura. Potete progettare la vostra configurazione per leggere da uno o più membri secondari. Il trasferimento asincrono dei dati può far sì che i nodi secondari leggano dati vecchi. Pertanto, questa soluzione non è ideale per tutti i casi d’uso.

Caratteristiche dei Replica Set

Il meccanismo di failover automatico distingue i replica set di MongoDB dalla concorrenza. In assenza di un primario, un’elezione automatica tra i nodi secondari sceglie un nuovo primario.

MongoDB Replica Set vs MongoDB Cluster

Un set di replica MongoDB crea diverse copie dello stesso insieme di dati tra i nodi del replica set. Lo scopo principale di un replica set è quello di:

  • Offrire una soluzione di backup integrata
  • Aumentare la disponibilità dei dati

Un cluster MongoDB è un gioco completamente diverso. Distribuisce i dati su più nodi attraverso una chiave shard. Questo processo frammenta i dati in tanti pezzi chiamati shard. Successivamente, copia ogni shard su un nodo diverso. Un cluster ha lo scopo di supportare grandi insiemi di dati e operazioni ad alto rendimento. Questo obiettivo viene raggiunto scalando orizzontalmente il carico di lavoro.

Ecco la differenza tra un replica set e un cluster, in parole povere:

  • Un cluster distribuisce il carico di lavoro. Inoltre, memorizza frammenti di dati (shard) su molti server.
  • Un replica set duplica completamente il set di dati.

MongoDB vi permette di combinare queste funzionalità creando un cluster sharded. In questo caso, potete replicare ogni shard su un server secondario. Questo permette a uno shard di offrire un’elevata ridondanza e disponibilità dei dati.

Mantenere e configurare un replica set può essere tecnicamente impegnativo e richiede molto tempo. E trovare il giusto servizio di hosting? È un altro paio di maniche. Con così tante opzioni a disposizione, è facile perdere ore a fare ricerche invece di dedicare tempo alla vostra attività.

Vi illustriamo uno strumento che fa tutto questo e molto di più, in modo che possiate tornare a dedicarvi con tutte le energie al vostro servizio/prodotto.

La soluzione di Application Hosting di Kinsta, di cui si fidano oltre 55.000 sviluppatrici e sviluppatori, può essere utilizzata in soli 3 semplici passi. Se vi sembra troppo bello per essere vero, ecco altri vantaggi dell’utilizzo di Kinsta:

  • Migliori prestazioni grazie alle connessioni interne di Kinsta: dimenticate i vostri problemi con i database condivisi. Passate a database dedicati con connessioni interne che non hanno limiti di numero di query o di righe. Kinsta è più veloce, più sicuro e non vi addebiterà la larghezza di banda/traffico interno.
  • Un set di funzionalità su misura per chi sviluppa: scalate la vostra applicazione sulla solida piattaforma che supporta Gmail, YouTube e Google Search. Abbiate fiducia, siete davvero in buone mani.
  • Velocità ineguagliabili con un data center di vostra scelta: Scegliete la regione più adatta a voi e ai vostri clienti. Con più di 25 data center tra cui scegliere, gli oltre 260+ PoP di Kinsta garantiscono la massima velocità e una presenza globale del vostro sito web.

Provate oggi stesso e gratuitamente la soluzione di hosting per applicazioni di Kinsta!

Come Funziona la Replicazione in MongoDB?

In MongoDB, si inviano operazioni di scrittura al server (nodo) primario. Il server primario assegna le operazioni ai server secondari, replicando i dati.

Un diagramma di flusso di come funziona la replicazione in MongoDB, per 3 nodi (1 primario, 2 secondari)
Illustrazione del processo di replica in MongoDB (Fonte: MongoDB)

Tre Tipi di Nodi MongoDB

Dei tre tipi di nodi MongoDB, due sono già stati presentati in precedenza: i nodi primari e i nodi secondari. Il terzo tipo di nodo MongoDB che si rivela utile durante la replica è l’arbiter. Il nodo arbiter non ha una copia del set di dati e non può diventare primario. Detto questo, l’arbiter partecipa alle elezioni del primario.

Abbiamo già detto cosa succede quando il nodo primario va in tilt, ma cosa succede se i nodi secondari vanno in tilt? In questo caso, il nodo primario diventa secondario e il database diventa irraggiungibile.

Elezione dei Membri

Le elezioni possono avvenire nei seguenti scenari:

  • Inizializzazione di un set di repliche
  • Perdita di connettività con il nodo primario (che può essere rilevata dagli heartbeat)
  • Manutenzione di un replica set con i metodi rs.reconfig o stepDown
  • Aggiunta di un nuovo nodo a un replica set esistente

Un replica set può avere fino a 50 membri, ma solo 7 o meno possono votare in qualsiasi elezione.

Il tempo medio prima che un cluster elegga un nuovo primario non dovrebbe superare i 12 secondi. L’algoritmo di elezione cercherà di avere a disposizione il secondario con la priorità più alta. Allo stesso tempo, i membri con un valore di priorità pari a 0 non possono diventare primari e non partecipano alle elezioni.

Diagramma che illustra un nodo secondario che diventa primario in MongoDB dopo le elezioni.
Nodo secondario che diventa primario (Fonte: Medium)

Il Write Concern

Per quanto riguarda la durabilità, le operazioni di scrittura hanno una struttura che copia i dati in un numero specifico di nodi. È anche possibile offrire un feedback al cliente. Questa struttura è nota anche come “write concern”. Ha dei membri che trasportano i dati e che devono riconoscere un problema di scrittura prima che l’operazione abbia successo. In genere, i replica set hanno un valore di 1 come write concern. Pertanto, solo il primario deve confermare la scrittura prima di restituire il riconoscimento di write concern.

Potete anche aumentare il numero di membri necessari a riconoscere l’operazione di scrittura. Non c’è un limite massimo al numero di membri che potete avere. Tuttavia, se il numero è elevato, dovrete fare i conti con una latenza elevata. Questo perché il client deve attendere il riconoscimento da parte di tutti i membri. Inoltre, potete impostare l’interesse di scrittura della “maggioranza”, che calcola più della metà dei membri dopo aver ricevuto il loro riconoscimento.

Preferenze di Lettura

Per le operazioni di lettura, potete indicare la preferenza di lettura che descrive come il database indirizza la query ai membri del replica set. In genere, il nodo primario riceve le operazioni di lettura, ma il cliente può indicare una preferenza di lettura per inviare le operazioni di lettura ai nodi secondari. Ecco le opzioni per la preferenza di lettura:

  • primaryPreferred: di solito le operazioni di lettura provengono dal nodo primario, ma se questo non è disponibile i dati vengono prelevati dai nodi secondari.
  • primary: tutte le operazioni di lettura provengono dal nodo primario.
  • secondary: tutte le operazioni di lettura vengono eseguite dai nodi secondari.
  • nearest: in questo caso, le richieste di lettura vengono instradate verso il nodo più vicino raggiungibile, che può essere individuato eseguendo il comando ping. L’esito delle operazioni di lettura può provenire da qualsiasi membro del replica set, indipendentemente dal fatto che sia primario o secondario.
  • secondaryPreferred: In questo caso, la maggior parte delle operazioni di lettura proviene dai nodi secondari, ma se nessuno di essi è disponibile, i dati vengono prelevati dal nodo primario.

Sincronizzazione dei Dati del Replication Set

Per mantenere copie aggiornate del set di dati condiviso, i membri secondari di un replica set replicano o sincronizzano i dati degli altri membri.

MongoDB sfrutta due forme di sincronizzazione dei dati: sincronizzazione iniziale per riempire i nuovi membri con l’intero set di dati; replicazione per eseguire modifiche continue al set di dati completo.

Sincronizzazione Iniziale

Durante la sincronizzazione iniziale, un nodo secondario esegue il comando init sync per sincronizzare tutti i dati dal nodo primario a un altro nodo secondario che contiene i dati più recenti. Pertanto, il nodo secondario sfrutta costantemente la funzione tailable cursor per interrogare le voci oplog più recenti all’interno della raccolta local.oplog.rs del nodo primario e applica le operazioni all’interno di queste voci oplog.

A partire da MongoDB 5.2, le sincronizzazioni iniziali possono essere basate su copie di file o logiche.

Sincronizzazione Logica

Quando eseguite una sincronizzazione logica, MongoDB:

  1. Sviluppa tutti gli indici delle collezioni mentre i documenti vengono copiati per ogni collezione.
  2. Duplica tutti i database ad eccezione del database locale. mongod esegue la scansione di ogni raccolta in tutti i database di origine e inserisce tutti i dati nei duplicati di queste raccolte.
  3. Esegue tutte le modifiche sul set di dati. Sfruttando l’oplog dell’origine, mongod aggiorna il suo set di dati per rappresentare lo stato attuale del replica set.
  4. Estrae i nuovi record oplog aggiunti durante la copia dei dati. Assicuratevi che il membro di destinazione disponga di spazio su disco sufficiente all’interno del database locale per memorizzare provvisoriamente questi record oplog per la durata di questa fase di copia dei dati.

Al termine della sincronizzazione iniziale, il membro passa da STARTUP2 a SECONDARY .

Sincronizzazione Iniziale Basata sulla Copia dei File

Questa procedura può essere eseguita solo se usate MongoDB Enterprise. Questo processo esegue la sincronizzazione iniziale duplicando e spostando i file sul file system. In alcuni casi, questo metodo di sincronizzazione potrebbe essere più veloce della sincronizzazione iniziale logica. Tenete presente che la sincronizzazione iniziale basata sulla copia dei file potrebbe portare a conteggi imprecisi se eseguite il metodo count() senza un predicato di query.

Tuttavia, anche questo metodo ha le sue limitazioni:

  • Durante una sincronizzazione iniziale basata sulla copia di file, non potete scrivere sul database locale del membro che viene sincronizzato. Inoltre, non potete eseguire un backup sul membro a cui si sta sincronizzando o sul membro da cui si sta sincronizzando.
  • Quando si usa il motore di archiviazione crittografato, MongoDB usa la chiave di origine per crittografare la destinazione.
  • Potete eseguire una sincronizzazione iniziale solo da un membro alla volta.

Replicazione

I membri secondari replicano i dati in modo coerente dopo la sincronizzazione iniziale. I membri secondari duplicheranno l’oplog della loro sincronizzazione dalla sorgente ed eseguiranno queste operazioni in un processo asincrono.

I membri secondari sono in grado di modificare automaticamente la loro sincronizzazione dall’origine, se necessario, in base alle variazioni del tempo di ping e dello stato della replicazione degli altri membri.

Replicazione in Streaming

A partire da MongoDB 4.4, la sincronizzazione dalle fonti invia un flusso continuo di voci oplog alle loro secondarie di sincronizzazione. La replicazione in streaming riduce il ritardo della replicazione nelle reti ad alto carico e ad alta latenza. Può anche:

  • Ridurre il rischio di perdere le operazioni di scrittura con w:1 a causa di un failover primario.
  • Ridurre lo stallo per le letture dai secondari.
  • Ridurre la latenza delle operazioni di scrittura con w:“majority” e w:>1. In breve, qualsiasi problema di scrittura che richiede l’attesa della replicazione.
Replicazione Multithread

MongoDB è solito scrivere le operazioni in batch attraverso più thread per migliorare la concorrenza. MongoDB raggruppa i batch in base all’id del documento e applica ogni gruppo di operazioni con un thread diverso.

MongoDB esegue sempre le operazioni di scrittura su un dato documento nel suo ordine di scrittura originale. Questo è cambiato in MongoDB 4.0.

A partire da MongoDB 4.0, le operazioni di lettura che hanno come obiettivo i secondari e sono configurate con un livello di write concern di “majority” o “local” ora leggeranno da un’istantanea WiredTiger dei dati se la lettura avviene su un secondario in cui vengono applicati i batch di replicazione. La lettura da un’istantanea garantisce una visione coerente dei dati e permette di leggere contemporaneamente alla replicazione in corso senza bisogno di un blocco.

Pertanto, le letture secondarie che necessitano di questi livelli di concern non devono più attendere l’applicazione dei batch di replicazione e possono essere gestite man mano che vengono ricevute.

Come Creare un Replica Set in MongoDB

Come detto in precedenza, MongoDB gestisce la replicazione attraverso i replica set. Nelle prossime sezioni vi illustreremo alcuni metodi che potete usare per creare un replica set adatto al vostro caso d’uso.

Metodo 1: Creare un Nuovo Replica Set MongoDB su Ubuntu

Prima di iniziare, dovete assicurarvi di avere almeno tre server con Ubuntu 20.04 e MongoDB installato su ogni server.

Per configurare un replica set, è essenziale fornire un indirizzo a cui ogni membro del replica set possa essere raggiunto dagli altri membri del set. In questo caso, i membri del set sono tre. Anche se possiamo usare gli indirizzi IP, non è consigliabile perché gli indirizzi potrebbero cambiare inaspettatamente. Un’alternativa migliore può essere quella di usare i nomi di host DNS logici quando si configurano i replica set.

Possiamo farlo configurando il sottodominio per ogni membro della replicazione. Anche se questo può essere l’ideale per un ambiente di produzione, in questa sezione verrà illustrato come configurare la risoluzione DNS modificando i rispettivi file hosts di ogni server. Questo file ci permette di assegnare nomi di host leggibili a indirizzi IP numerici. In questo modo, se il vostro indirizzo IP dovesse cambiare, non dovrete fare altro che aggiornare i file hosts dei tre server piuttosto che riconfigurare il replica set da zero!

Per lo più, hosts è memorizzato nella directory /etc/. Ripetete i comandi seguenti per ognuno dei vostri tre server:

sudo nano /etc/hosts

Nel comando qui sopra, stiamo usando nano come editor di testo, ma potete usare l’editor di testo che preferite. Dopo le prime righe che configurano il localhost, aggiungete una voce per ogni membro del replica set. Queste voci sono costituite da un indirizzo IP seguito da un nome leggibile a vostra scelta. Potete chiamarli come preferite, ma assicuratevi di essere descrittivi in modo da poter distinguere ogni membro. Per questo tutorial, useremo i seguenti nomi di host:

  • mongo0.replset.member
  • mongo1.replset.member
  • mongo2.replset.member

Con questi nomi di host, i file /etc/hosts avranno un aspetto simile alle seguenti righe evidenziate:

Istantanea dei file /etc/hosts contenenti gli hostname insieme all'indirizzo IP.
Illustrazione degli hostname

Salvate e chiudete il file.

Dopo aver configurato la risoluzione DNS per il replica set, dobbiamo aggiornare le regole del firewall per permettere ai due server di comunicare tra loro. Eseguite il seguente comando ufw su mongo0 per consentire a mongo1 di accedere alla porta 27017 di mongo0:

sudo ufw allow from mongo1_server_ip to any port 27017

Al posto del parametro mongo1_server_ip, inserite l’indirizzo IP effettivo del server mongo1. Inoltre, se avete aggiornato l’istanza di Mongo su questo server per usare una porta diversa da quella predefinita, assicuratevi di cambiare la 27017 per riflettere la porta utilizzata dall’istanza di MongoDB.

Ora aggiungete un’altra regola del firewall per dare a mongo2 l’accesso alla stessa porta:

sudo ufw allow from mongo2_server_ip to any port 27017

Al posto del parametro mongo2_server_ip, inserite l’indirizzo IP effettivo del vostro server mongo2. Quindi, aggiornate le regole del firewall per gli altri due server. Eseguite i seguenti comandi sul server mongo1, assicurandovi di cambiare gli indirizzi IP al posto del parametro server_ip per riflettere quelli di mongo0 e mongo2, rispettivamente:

sudo ufw allow from mongo0_server_ip to any port 27017
sudo ufw allow from mongo2_server_ip to any port 27017

Infine, eseguite questi due comandi su mongo2. Anche in questo caso, verificate di inserire gli indirizzi IP corretti per ogni server:

sudo ufw allow from mongo0_server_ip to any port 27017
sudo ufw allow from mongo1_server_ip to any port 27017

Il passo successivo è aggiornare il file di configurazione di ogni istanza di MongoDB per consentire le connessioni esterne. Per permettere ciò, dovete modificare il file di configurazione di ogni server per riflettere l’indirizzo IP e indicare il replica set. Sebbene possiate usare qualsiasi editor di testo, noi useremo ancora una volta l’editor di testo nano. Apportiamo le seguenti modifiche a ciascun file mongod.conf.

Su mongo0:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo0.replset.member# replica set
replication:
replSetName: "rs0"

Su mongo1:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo1.replset.member
replication:
replSetName: "rs0"

Su mongo2:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo2.replset.member
replication:
replSetName: "rs0"
sudo systemctl restart mongod

In questo modo avete abilitato la replica per ogni istanza MongoDB del server.

Ora potete inizializzare il replica set utilizzando il metodo rs.initiate(). Questo metodo deve essere eseguito solo su una singola istanza MongoDB del replica set. Verificate che il nome e il membro del replica set corrispondano alle configurazioni effettuate in precedenza in ciascun file di configurazione.

rs.initiate(
  {
    _id: "rs0",
    members: [
      { _id: 0, host: "mongo0.replset.member" },
      { _id: 1, host: "mongo1.replset.member" },
      { _id: 2, host: "mongo2.replset.member" }
    ]
  }
)

Se il metodo restituisce “ok”: 1 nell’output, significa che il replica set è stato avviato correttamente. Ecco un esempio di come dovrebbe apparire l’output:

 "ok": 1,
  "$clusterTime": {
    "clusterTime": Timestamp(1612389071, 1),
    "signature": {
      "hash": BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
      "keyId": NumberLong(0)
    }
  },
  "operationTime": Timestamp(1612389071, 1)
}

Spegnere il Server MongoDB

Potete spegnere un server MongoDB con il metodo db.shutdownServer(). Di seguito è riportata la sintassi dello stesso. Sia force che timeoutsecs sono parametri opzionali.

db.shutdownServer({
  force: <boolean>,
  timeoutSecs: <int>
})

Questo metodo può fallire se il membro del mongod replica set esegue alcune operazioni come la creazione di indici. Per interrompere le operazioni e forzare il membro a spegnersi, potete inserire il parametro booleano force a true.

Riavviare MongoDB con –replSet

Per ripristinare la configurazione, verificate che tutti i nodi del vostro replica set siano fermi. Quindi cancellate il database locale di ogni nodo. Riavviate il database usando il flag –replSet ed eseguite rs.initiate() su una sola istanza di MongoDB per il replica set.

mongod --replSet "rs0"

rs.initiate() può accettare un documento opzionale di configurazione del replica set, ovvero:

  • L’opzione Replication.replSetName o —replSet per specificare il nome del replica set nel campo _id.
  • L’array dei membri, che contiene un documento per ogni membro del replica set.

Il metodo rs.initiate() attiva un’elezione ed elegge uno dei membri come primario.

Aggiungere Membri al Replica Set

Per aggiungere membri all’insieme, avviate le istanze di mongod su diversi computer. Quindi, avviate un client mongo e usate il comando rs.add().

Il comando rs.add() ha la seguente sintassi di base:

rs.add(HOST_NAME:PORT)

Per esempio,

Supponiamo che mongo1 sia la vostra istanza di Mongo e che sia in ascolto sulla porta 27017. Usate il comando del client Mongo rs.add() per aggiungere questa istanza al replica set.

rs.add("mongo1:27017")

Solo se siete connessi al nodo primario potete aggiungere un’istanza mongod al replica set. Per verificare se siete connessi al nodo primario, usate il comando db.isMaster().

Rimuovere gli Utenti

Per rimuovere un membro, possiamo usare rs.remove()

Per farlo, innanzitutto spegnete l’istanza di mongod che volete rimuovere usando il metodo db.shutdownServer() di cui abbiamo parlato sopra.

Quindi, connettetevi al primario corrente del replica set. Per determinare il primario corrente, usate db.hello() mentre siete connessi a un qualsiasi membro del replica set. Una volta determinato il primario, eseguite uno dei seguenti comandi:

rs.remove("mongodb-node-04:27017")
rs.remove("mongodb-node-04")
Istantanea dell'output dopo aver eseguito il comando rs.remove().
L’immagine qui sopra mostra che il nodo è stato rimosso correttamente dal replica set. (Fonte immagine: Bmc)

Se il replica set deve eleggere un nuovo primario, MongoDB potrebbe disconnettere brevemente la shell. In questo caso, si riconnetterà automaticamente. Inoltre, potrebbe visualizzare un errore DBClientCursor::init call() failed anche se il comando ha successo.

Metodo 2: Configurare un Replica Set MongoDB per la Distribuzione e i Test

In generale, potete configurare i replica set per i test sia con RBAC abilitato che disabilitato. In questo metodo, configureremo i replica set con il controllo di accesso disabilitato per distribuirli in un ambiente di test.

Per prima cosa, create le directory per tutte le istanze che fanno parte del replica set tramite il seguente comando:

mkdir -p /srv/mongodb/replicaset0-0  /srv/mongodb/replicaset0-1 /srv/mongodb/replicaset0-2

Questo comando creerà le directory per tre istanze MongoDB: replicaset0-0, replicaset0-1 e replicaset0-2. Ora avviate le istanze MongoDB per ognuna di esse utilizzando la seguente serie di comandi:

Per il server 1:

mongod --replSet replicaset --port 27017 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Per il Server 2:

mongod --replSet replicaset --port 27018 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Per il Server 3:

mongod --replSet replicaset --port 27019 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Il parametro –oplogSize si usa per evitare che la macchina venga sovraccaricata durante la fase di test. Aiuta a ridurre la quantità di spazio su disco consumato da ciascun disco.

A questo punto, connettetevi a una delle istanze utilizzando la shell di Mongo con il numero di porta indicato di seguito.

mongo --port 27017

Possiamo usare il comando rs.initiate() per avviare il processo di replicazione. Dovrete sostituire il parametro hostname con il nome del vostro sistema.

rs conf = {

  _id: "replicaset0",

  members: [

	{  _id: 0,  host: "<hostname>:27017},

	{  _id: 1,  host: "<hostname>:27018"},

	{  _id: 2,  host: "<hostname>:27019"}

   ] }

Ora potete passare il file dell’oggetto di configurazione come parametro del comando initiate e usarlo come segue:

rs.initiate(rsconf)

Ed ecco fatto! Avete creato con successo un replica set MongoDB per scopi di sviluppo e di test.

Metodo 3: Trasformare un’Istanza Standalone in un Replica Set MongoDB

MongoDB permette agli utenti di trasformare le proprie istanze standalone in replica set. Mentre le istanze standalone sono utilizzate soprattutto per la fase di test e sviluppo, i replica set fanno parte dell’ambiente di produzione.

Per iniziare, chiudiamo la nostra istanza mongod con il seguente comando:

db.adminCommand({"shutdown":"1"})

Riavviate la vostro istanza usando il parametro –repelSet nel comando per specificare il replica set che state per utilizzare:

mongod --port 27017 – dbpath /var/lib/mongodb  --replSet replicaSet1 --bind_ip localhost,<hostname(s)|ip address(es)>

Dovete specificare il nome del vostro server insieme all’indirizzo univoco nel comando.

Connettete la shell con la vostra istanza MongoDB e usate il comando initiate per avviare il processo di replicazione e convertire l’istanza in un replica set. Potete eseguire tutte le operazioni di base come l’aggiunta o la rimozione di un’istanza utilizzando i seguenti comandi:

rs.add(“<host_name:port>”)
rs.remove(“host-name”)

Inoltre, potete controllare lo stato del vostro replica set MongoDB con i comandi rs.status() e rs.conf().

Metodo 4: MongoDB Atlas – Un’Alternativa Più Semplice

La replica e lo sharding possono lavorare insieme per formare un cluster chiamato sharded. L’installazione e la configurazione possono richiedere molto tempo, anche se sono semplici, quindi MongoDB Atlas è un’alternativa migliore rispetto ai metodi menzionati in precedenza.

Automatizza i replica set, rendendo il processo facile da implementare. Può distribuire replica set sharded a livello globale con pochi clic, consentendo il disaster recovery, una gestione più semplice, la localizzazione dei dati e le distribuzioni multiregionali.

In MongoDB Atlas dobbiamo creare dei cluster, che possono essere un replica set o un cluster sharded. Per un particolare progetto, il numero di nodi in un cluster in altre regioni è limitato a un totale di 40.

Questo esclude i cluster gratuiti o condivisi e le regioni del cloud di Google che comunicano tra loro. Il numero totale di nodi tra due regioni deve rispettare questo vincolo. Per esempio, se c’è un progetto in cui:

  • La regione A ha 15 nodi.
  • La regione B ha 25 nodi
  • La regione C ha 10 nodi

Possiamo assegnare solo altri 5 nodi alla regione C in quanto,

  1. Regione A+ Regione B = 40; rispetta il vincolo di 40 come numero massimo di nodi consentito.
  2. Regione B+ Regione C = 25+10+5 (nodi aggiuntivi assegnati a C) = 40; soddisfa il vincolo di 40 come numero massimo di nodi consentito.
  3. Regione A+ Regione C =15+10+5 (Nodi aggiuntivi assegnati a C) = 30; soddisfa il vincolo di 40 come numero massimo di nodi consentito.

Se assegnassimo altri 10 nodi alla regione C, facendo sì che la regione C abbia 20 nodi, allora la regione B + la regione C = 45 nodi. Questo supererebbe il vincolo dato, quindi non potrete creare un cluster multiregione.

Quando create un cluster, Atlas crea un contenitore di rete nel progetto per il cloud provider, se non era presente in precedenza. Per creare un cluster di replica set in MongoDB Atlas, eseguite il seguente comando nella CLI di Atlas:

atlas clusters create [name] [options]

Assicuratevi di dare un nome descrittivo al cluster, poiché non può essere modificato dopo la creazione del cluster. L’argomento può contenere lettere ASCII, numeri e trattini.

Ci sono diverse opzioni disponibili per la creazione di cluster in MongoDB in base alle vostro esigenze. Per esempio, se volete un backup continuo nel cloud per il vostro cluster, impostate --backup su true.

Gestire il Ritardo di Replicazione

Il ritardo di replicazione può essere piuttosto fastidioso. Si tratta di un ritardo tra un’operazione sul primario e l’applicazione di tale operazione dall’oplog al secondario. Se la vostra azienda ha a che fare con set di dati di grandi dimensioni, il ritardo è previsto entro una certa soglia. Tuttavia, a volte anche fattori esterni possono contribuire ad aumentare il ritardo. Per beneficiare di una replica aggiornata, verificate che:

  1. Il traffico di rete sia instradato con una larghezza di banda stabile e sufficiente. La latenza della rete gioca un ruolo fondamentale nell’influenzare la replica e se la rete non è sufficiente a soddisfare le esigenze del processo di replica, si verificheranno ritardi nella replica dei dati in tutto il replica set.
  2. La velocità del disco è sufficiente. Se il file system e il dispositivo su disco del secondario non sono in grado di riversare i dati su disco con la stessa velocità del primario, il secondario avrà difficoltà a tenere il passo. Di conseguenza, i nodi secondari elaborano le query di scrittura più lentamente del nodo primario. Questo è un problema comune nella maggior parte dei sistemi multi-tenant, comprese le istanze virtualizzate e le implementazioni su larga scala.
  3. Si richiede un riconoscimento di scrittura dopo un intervallo di tempo per dare la possibilità ai secondari di mettersi al passo con il primario, soprattutto quando si vuole eseguire un’operazione di carico massivo o di acquisizione di dati che richiede un gran numero di scritture sul primario. Le secondarie non saranno in grado di leggere l’oplog abbastanza velocemente per tenere il passo con le modifiche, soprattutto in caso di problemi di scrittura non riconosciuti.
  4. Identifica le attività in background in esecuzione. Alcune attività come i cron job, gli aggiornamenti del server e i controlli di sicurezza potrebbero avere effetti inaspettati sulla rete o sull’utilizzo del disco, causando ritardi nel processo di replicazione.

Se non avete la certezza che la vostra applicazione abbia un ritardo nella replicazione, non preoccupatevi: nella prossima sezione vediamo le strategie di risoluzione dei problemi!

Risoluzione dei Problemi dei Replica Set MongoDB

Avete configurato con successo i vostri replica set, ma avete notato che i dati non sono coerenti tra i server. Si tratta di un problema molto preoccupante per le aziende di grandi dimensioni, tuttavia, grazie a rapidi metodi di risoluzione dei problemi, è possibile trovare la causa o addirittura correggere il problema! Di seguito sono riportate alcune strategie comuni per la risoluzione dei problemi delle implementazioni dei replica set che potrebbero tornarvi utili:

Controllare lo Stato del Replica Set

Possiamo controllare lo stato attuale del replica set e lo stato di ogni membro eseguendo il seguente comando in una sessione mongosh connessa al primario del replica set.

 rs.status()

Controllare il Ritardo della Replicazione

Come già detto in precedenza, il ritardo di replicazione può essere un problema serio perché rende i membri “in ritardo” non idonei a diventare rapidamente primari e aumenta la possibilità che le operazioni di lettura distribuite siano incoerenti. Possiamo verificare la lunghezza attuale del registro di replicazione usando il seguente comando:

rs.printSecondaryReplicationInfo()

Questo restituisce il valore syncedTo che è l’ora in cui l’ultima voce oplog è stata scritta sul secondario per ogni membro. Ecco un esempio per dimostrarlo:

source: m1.example.net:27017
	syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT)
	0 secs (0 hrs) behind the primary
source: m2.example.net:27017
	syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT)
	0 secs (0 hrs) behind the primary

Un membro in ritardo può essere visualizzato con 0 secondi di ritardo rispetto al primario quando il periodo di inattività sul primario è maggiore del valore members[n].secondaryDelaySecs.

Verifica le Connessioni tra Tutti i Membri

Ogni membro di un replica set deve essere in grado di connettersi con ogni altro membro. Verificate sempre le connessioni in entrambe le direzioni. Spesso le configurazioni dei firewall o le tipologie di rete impediscono la normale e necessaria connettività e possono bloccare la replicazione.

Per esempio, supponiamo che l’istanza di mongod si leghi sia a localhost che all’hostname ‘ExampleHostname’, associato all’indirizzo IP 198.41.110.1:

mongod --bind_ip localhost, ExampleHostname

Per connettersi a questa istanza, i client remoti devono specificare l’hostname o l’indirizzo IP:

mongosh --host ExampleHostname
mongosh --host 198.41.110.1

Se un replica set è composto da tre membri, m1, m2 e m3, e usa la porta predefinita 27017, dovete testare la connessione come segue:

Su m1:

mongosh --host m2 --port 27017
mongosh --host m3 --port 27017

Su m2:

mongosh --host m1 --port 27017
mongosh --host m3 --port 27017

Su m3:

mongosh --host m1 --port 27017
mongosh --host m2 --port 27017

Se una connessione in qualsiasi direzione fallisce, dovete controllare la configurazione del vostro firewall e riconfigurarlo per consentire le connessioni.

Garantire Comunicazioni Sicure con l’Autenticazione dei Keyfile

Per impostazione predefinita, l’autenticazione keyfile in MongoDB si basa sul meccanismo di autenticazione salted challenge response (SCRAM). A tal fine, MongoDB deve leggere e convalidare le credenziali fornite dall’utente che includono una combinazione di nome utente, password e database di autenticazione di cui è a conoscenza la specifica istanza di MongoDB. Questo è l’esatto meccanismo utilizzato per autenticare gli utenti che forniscono una password quando si collegano al database.

Quando abilitate l’autenticazione in MongoDB, il controllo dell’accesso basato sui ruoli (RBAC) viene automaticamente abilitato per il replica set e all’utente vengono assegnati uno o più ruoli che determinano il suo accesso alle risorse del database. Quando il RBAC è abilitato, significa che solo l’utente Mongo autenticato e valido con i privilegi appropriati potrà accedere alle risorse del sistema.

Il keyfile agisce come una password condivisa per ogni membro del cluster. Questo permette a ogni istanza di Mongo nel replica set di utilizzare il contenuto del keyfile come password condivisa per l’autenticazione degli altri membri dell’installazione.

Solo le istanze mongod con il keyfile corretto possono unirsi al replica set. La lunghezza di una chiave deve essere compresa tra 6 e 1024 caratteri e può contenere solo caratteri dell’insieme base64. Tenete presente che MongoDB elimina gli spazi bianchi durante la lettura delle chiavi.

Potete generare un keyfile seguendo diversi metodi. In questo tutorial, usiamo openssl per generare una stringa complessa di 1024 caratteri casuali da usare come password condivisa. Usate poi chmod per modificare i permessi dei file in modo da fornire i permessi di lettura solo al proprietario del file. Evitate di memorizzare il keyfile su supporti di archiviazione che possono essere facilmente scollegati dall’hardware che ospita le istanze di mongod, come per esempio una chiavetta USB o un dispositivo di archiviazione collegato alla rete. Di seguito è riportato il comando per generare un keyfile:

openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>

Successivamente, copiate il keyfile in ogni membro del replica set. Verificate che l’utente che gestisce le istanze mongod sia il proprietario del file e possa accedere al keyfile. Dopo aver fatto quanto sopra, spegnete tutti i membri del replica set a partire dai secondari. Una volta che tutti i secondari sono offline, potete procedere con lo spegnimento dei primari. È fondamentale seguire questo ordine per evitare potenziali rollback. Ora chiudete l’istanza di mongod eseguendo il seguente comando:

use admin
db.shutdownServer()

Dopo l’esecuzione del comando, tutti i membri del replica set saranno offline. Ora riavviate ogni membro del replica set con il controllo degli accessi abilitato.

Per ogni membro del replica set, avviate l’istanza di mongod con l’impostazione del file di configurazione security.keyFile o con l’opzione della riga di comando --keyFile.

Se usate un file di configurazione, impostate

  • security.keyFile al percorso del file chiave e
  • replication.replSetName il nome del replica set.
security:
  keyFile: <path-to-keyfile>
replication:
  replSetName: <replicaSetName>
net:
   bindIp: localhost,<hostname(s)|ip address(es)>

Avviate l’istanza di mongod usando il file di configurazione:

mongod --config <path-to-config-file>

Se state utilizzando le opzioni della riga di comando, avviate l’istanza mongod con le seguenti opzioni:

  • –keyFile impostato sul percorso del keyfile e
  • –replSet impostato sul nome del replica set.
mongod --keyFile <path-to-keyfile> --replSet <replicaSetName> --bind_ip localhost,<hostname(s)|ip address(es)>

Potete includere altre opzioni se necessarie per la vostra configurazione. Per esempio, se volete che i client remoti si connettano alla vostra installazione client o se i membri dell’installazione client sono eseguiti su host diversi, specificate il parametro –bind_ip. Per maggiori informazioni, leggete la pagina di documentazione Localhost Binding Compatibility Changes.

Successivamente, connettetevi a un membro del replica set tramite l’interfaccia localhost. Dovete eseguire mongosh sullo stesso computer fisico dell’istanza di mongod. Questa interfaccia è disponibile solo quando non sono stati creati utenti per la distribuzione e si chiude automaticamente dopo la creazione del primo utente.

Avviamo quindi il replica set. Da mongosh, eseguite il metodo rs.initiate():

rs.initiate(
  {
	_id: "myReplSet",
	members: [
  	{ _id: 0, host: "mongo1:27017" },
  	{ _id: 1, host: "mongo2:27017" },
  	{ _id: 2, host: "mongo3:27017" }
	]
  }
)

Come già detto, questo metodo elegge uno dei membri come membro primario del replica set. Per individuare il membro primario, usate rs.status(). Collegatevi al membro primario prima di continuare.

Ora create l’utente amministratore. Potete aggiungere un utente usando il metodo db.createUser(). Assicuratevi che l’utente abbia almeno il ruolo userAdminAnyDatabase nel database degli amministratori.

L’esempio seguente crea l’utente “batman” con il ruolo userAdminAnyDatabase sul database dell’amministratore:

admin = db.getSiblingDB("admin")
admin.createUser(
  {
	user: "batman",
	pwd: passwordPrompt(), // or cleartext password
	roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

Quando vi viene richiesto, inserite la password creata in precedenza.

Successivamente, dovete autenticarvi come utente amministratore. Per farlo, usate db.auth() per autenticarvi. Per esempio:

db.getSiblingDB(“admin”).auth(“batman”, passwordPrompt()) // o password in chiaro

In alternativa, potete connettere una nuova istanza di mongosh al membro primario del replica set usando i parametri -u <username>, -p <password> e --authenticationDatabase.

mongosh -u "batman" -p  --authenticationDatabase "admin"

Anche se non specificate la password nel campo della riga di comando -p, mongosh richiede la password.

Infine, create l’amministratore del cluster. Il ruolo clusterAdmin consente l’accesso alle operazioni di replicazione, come la configurazione del replica set.

Creiamo un utente amministratore del cluster e assegniamo il ruolo clusterAdmin nel database admin:

db.getSiblingDB("admin").createUser(
  {
	"user": "robin",
	"pwd": passwordPrompt(), 	// or cleartext password
	roles: [ { "role" : "clusterAdmin", "db" : "admin" } ]
  }
)

Inserite la password quando vi viene richiesto.

Se lo desiderate, potete creare altri utenti per consentire ai client di interagire con il replica set.

E voilà! Avete abilitato correttamente l’autenticazione del keyfile!

Riepilogo

La replicazione è un requisito essenziale quando si parla di database, soprattutto quando le aziende diventano sempre più grandi. Migliora notevolmente le prestazioni, la sicurezza dei dati e la disponibilità del sistema. A proposito di prestazioni, è fondamentale per il vostro database WordPress monitorare i problemi di performance e correggerli in tempo, per esempio con Kinsta APM, Jetpack e Freshping per citarne alcuni.

La replicazione aiuta a garantire la protezione dei dati su più server ed evita che i vostri server subiscano pesanti downtime (o peggio ancora che perdano del tutto i vostri dati). In questo articolo abbiamo illustrato la creazione di un replica set e alcuni consigli per la risoluzione dei problemi, oltre all’importanza della replicazione. Voi usate la replicazione di MongoDB per la vostra attività e vi è risultata utile? Fatecelo sapere nella sezione commenti qui sotto!

Jeremy Holcombe Kinsta

Content & Marketing Editor at Kinsta, WordPress Web Developer, and Content Writer. Outside of all things WordPress, I enjoy the beach, golf, and movies. I also have tall people problems ;).