Con il termine replica set chaining in mongodb si intende la possibilità di fare in modo che i nodi secondari possano sincronizzarsi da altri secondari e non sempre e solo dal primario, come accadeva nelle versioni precedenti alla 2.2.
Il motivo dell'abilitazione di default del replica set chaining è quello di evitare un sovraccarico di richieste al nodo primario, infatti al momento (versione 3.2) di default il comportamento prevede che ogni nodo si sincronizzi automaticamente con quello più vicino a livello di ping.
Vediamo ora come è possibile modificare la sincronia da un membro all'altro in una replica set.
Possiamo accedere alla console con il comando
mongo --nodb
Quindi istanziare l'oggetto ReplSetTest
var test=new ReplSetTest({name:"prova",nodes:3});
Quindi facciamo partire la replica con il comando
test.startSet();
Ora inizializziamo l'ambiente con il comando
test.initiate();
Di default i 3 server sono stati fatti partire sulle porte 30001 30002 e 30003.
Se ci connettiamo alla 30001 nel mio caso vedo che si tratta del primary, l'output del comando rs.status() è il seguente:
prova:PRIMARY> rs.status();
{
"set" : "prova",
"date" : ISODate("2016-03-05T16:21:07.306Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "csciandrone-HP-Pavilion-Notebook:31000",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 355,
"optime" : Timestamp(1457194861, 2),
"optimeDate" : ISODate("2016-03-05T16:21:01Z"),
"electionTime" : Timestamp(1457194638, 1),
"electionDate" : ISODate("2016-03-05T16:17:18Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "csciandrone-HP-Pavilion-Notebook:31001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 232,
"optime" : Timestamp(1457194861, 2),
"optimeDate" : ISODate("2016-03-05T16:21:01Z"),
"lastHeartbeat" : ISODate("2016-03-05T16:21:06.963Z"),
"lastHeartbeatRecv" : ISODate("2016-03-05T16:21:06.970Z"),
"pingMs" : 0,
"syncingTo" : "csciandrone-HP-Pavilion-Notebook:31000",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "csciandrone-HP-Pavilion-Notebook:31002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 232,
"optime" : Timestamp(1457194861, 2),
"optimeDate" : ISODate("2016-03-05T16:21:01Z"),
"lastHeartbeat" : ISODate("2016-03-05T16:21:06.963Z"),
"lastHeartbeatRecv" : ISODate("2016-03-05T16:21:06.966Z"),
"pingMs" : 0,
"syncingTo" : "csciandrone-HP-Pavilion-Notebook:31000",
"configVersion" : 1
}
],
"ok" : 1
}
Ho visto che questa situazione si verifica solo dopo aver inserito almeno un record sul primario, altrimenti la proprietà syncingTo indicava che non era ancora possibile sincronizzarsi ad alcun nodo.
Possiamo vedere quindi che entrambi i secondari si sincronizzano dal primario.
Per cambiare questo comportamento dobbiamo connetterci ad un secondario
Verifichiamo la configurazione della replica set, in particolare che il chaining sia correttamente abilitato come previsto da default:
prova:SECONDARY> var status=rs.conf();
prova:SECONDARY> status
{
"_id" : "prova",
"version" : 1,
"members" : [
{
"_id" : 0,
"host" : "csciandrone-HP-Pavilion-Notebook:31000",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 1,
"host" : "csciandrone-HP-Pavilion-Notebook:31001",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 2,
"host" : "csciandrone-HP-Pavilion-Notebook:31002",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatTimeoutSecs" : 10,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
}
}
}
Come possiamo vedere la proprietà chainingAllowed è settata a true.
Ora vediamo come cambiare la sincronizzazione:
prova:SECONDARY> rs.syncFrom("csciandrone-HP-Pavilion-Notebook:31001")
{
"syncFromRequested" : "csciandrone-HP-Pavilion-Notebook:31001",
"prevSyncTarget" : "csciandrone-HP-Pavilion-Notebook:31000",
"ok" : 1
}
Quindi facendo rs.status() possiamo verificare che adesso il secondario sulla porta 31002 si sincronizza con quello presente sulla porta 31001.
Per disabilitare il chaining possiamo connetterci ad esempio sul primario e salvare (come visto prima) in una variabile il risultato di rs.conf() .
var conf=rs.conf();
Quindi digitare il comando
conf.settings.chainingAllowed=false;
rs.reconfig(conf);
Ovviamente la modifica sarà operativa solo per il prosieguo delle configurazioni, le modifiche già effettuate come la nostra resteranno attive.