Grazie @avanti, @MarkusWMalhberg - riflettere su come rispondere ai commenti mi ha spinto nella giusta direzione. Ci è voluto un po' per mettere insieme, quindi sarò un po' prolisso nello spiegare la configurazione.
Panoramica
Concentrandoci sull'esperienza dell'utente, vogliamo creare una configurazione del database Mongo che consenta che le letture e le scritture avvengano più vicino all'utente.
Presupposti
- Gli utenti leggono e scrivono quasi sempre documenti nella loro regione e non importa se le letture poco frequenti sui dati di altre regioni sono più lente.
- Ogni documento contiene una chiave che ne indica la regione (per semplicità/chiarezza)
Gran parte della documentazione sullo sharding si concentra su HA/DR. Con l'esperienza utente e la conformità regionale, l'attenzione si concentra sulla località anziché sulla distribuzione del carico.
Questo esempio ignorerà completamente HA/DR, leggerà le preferenze e scriverà problemi, ma questi devono essere affrontati se il POC è maturo. L'esempio li ignora a favore della chiarezza che soddisfa l'obiettivo:letture/scritture locali.
Riferimenti
- Segmentazione operativa
- Gestione dei tag shard
- Configurazione ReplicaSet
- Diversi errori db di configurazione di mongos
Trucchi
Lo sappiamo
- Vogliamo un database dell'applicazione in modo che tutti i dati siano disponibili
- Vogliamo che gli utenti leggano/scrivano localmente, quindi abbiamo bisogno di un database vicino a ciascun gruppo di utenti; abbiamo bisogno di un set di repliche
- Le scritture possono essere eseguite solo sui nodi del set di repliche primarie, quindi, per ottenere i nodi primari accanto a ciascun gruppo di utenti, abbiamo bisogno di repliche multiple; un cluster partizionato
All'interno della conoscenza standard di ReplicaSet e Sharding, ci sono 2 chiavi per questa configurazione:
- Assegna una priorità al nodo ReplicaSet locale a livello regionale per assicurarti che diventi primario.
- Utilizzare il tagging delle chiavi shard con rilevamento della posizione per garantire che i dati vengano scritti negli shard locali
Le chiavi parziali possono essere qualsiasi cosa:ci preoccupiamo solo che gli utenti siano in grado di leggere/scrivere localmente in contrasto con un'efficace condivisione del carico.
Ogni raccolta dovrà essere frammentata, altrimenti le scritture andranno allo shard zero.
Configurazione desiderata
La configurazione
#!/usr/bin/env bash
echo ">>> Clean up processes and files from previous runs"
echo ">>> killAll mongod mongos"
killall mongod mongos
echo ">>> Remove db files and logs"
rm -rf data
rm -rf log
# Create the common log directory
mkdir log
echo ">>> Start replica set for shard US-East"
mkdir -p data/shard-US-East/rsMemberEast data/shard-US-East/rsMemberWest
mongod --replSet shard-US-East --logpath "log/shard-US-East-rsMemberEast.log" --dbpath data/shard-US-East/rsMemberEast --port 37017 --fork --shardsvr --smallfiles
mongod --replSet shard-US-East --logpath "log/shard-US-East-rsMemberWest.log" --dbpath data/shard-US-East/rsMemberWest --port 37018 --fork --shardsvr --smallfiles
echo ">>> Sleep 15s to allow US-East replica set to start"
sleep 15
# The US-East replica set member is assigned priority 2 so that it becomes primary
echo ">>> Configure replica set for shard US-East"
mongo --port 37017 << 'EOF'
config = { _id: "shard-US-East", members:[
{ _id : 0, host : "localhost:37017", priority: 2 },
{ _id : 1, host : "localhost:37018" }]};
rs.initiate(config)
EOF
echo ">>> Start replica set for shard-US-West"
mkdir -p data/shard-US-West/rsMemberEast data/shard-US-West/rsMemberWest
mongod --replSet shard-US-West --logpath "log/shard-US-West-rsMemberEast.log" --dbpath data/shard-US-West/rsMemberEast --port 47017 --fork --shardsvr --smallfiles
mongod --replSet shard-US-West --logpath "log/shard-US-West-rsMemberWest.log" --dbpath data/shard-US-West/rsMemberWest --port 47018 --fork --shardsvr --smallfiles
echo ">>> Sleep 15s to allow US-West replica set to start"
sleep 15
# The US-West replica set member is assigned priority 2 so that it becomes primary
echo ">>> Configure replica set for shard-US-West"
mongo --port 47017 << 'EOF'
config = { _id: "shard-US-West", members:[
{ _id : 0, host : "localhost:47017" },
{ _id : 1, host : "localhost:47018", priority: 2 }]};
rs.initiate(config)
EOF
# Shard config servers: should be 3 and all must be up to deploy a shard cluster
# These are the mongos backing store for routing information
echo ">>> Start config servers"
mkdir -p data/config/config-us-east data/config/config-us-west data/config/config-redundant
mongod --logpath "log/cfg-us-east.log" --dbpath data/config/config-us-east --port 57040 --fork --configsvr --smallfiles
mongod --logpath "log/cfg-us-west.log" --dbpath data/config/config-us-west --port 57041 --fork --configsvr --smallfiles
mongod --logpath "log/cfg-redundant.log" --dbpath data/config/config-redundant --port 57042 --fork --configsvr --smallfiles
echo ">>> Sleep 5 to allow config servers to start and stabilize"
sleep 5
# All mongos's must point at the same config server, a coordinator dispatches writes to each
echo ">>> Start mongos"
mongos --logpath "log/mongos-us-east.log" --configdb localhost:57040,localhost:57041,localhost:57042 --port 27017 --fork
mongos --logpath "log/mongos-us-west.log" --configdb localhost:57040,localhost:57041,localhost:57042 --port 27018 --fork
echo ">>> Wait 60 seconds for the replica sets to stabilize"
sleep 60
# Enable sharding on the 'sales' database and 'sales.users' collection
# Every collection in 'sales' must be sharded or the writes will go to shard 0
# Add a shard tag so we can associate shard keys with the tag (region)
# Shard tag range main and max cannot be the same so we use a region id for US-East = 1
# and US-West = 2. sh.addTagRange() is inclusive of minKey and exclusive of maxKey.
# We only need to configure one mongos - config will be propogated to all mongos through
# the config server
echo ">>> Add shards to mongos"
mongo --port 27017 <<'EOF'
db.adminCommand( { addshard : "shard-US-East/"+"localhost:37017" } );
db.adminCommand( { addshard : "shard-US-West/"+"localhost:47017" } );
db.adminCommand({enableSharding: "sales"})
db.adminCommand({shardCollection: "sales.users", key: {region:1}});
sh.addShardTag("shard-US-East", "US-East")
sh.addShardTag("shard-US-West", "US-West")
sh.addTagRange("sales.users", { region: 1 }, { region: 2 }, "US-East")
sh.addTagRange("sales.users", { region: 2 }, { region: 3 }, "US-West")
EOF
Test
Verifica che la nostra configurazione sia corretta con sh.status()
. Gli shard delle note sono assegnati correttamente, i tag e le chiavi shard regionali sono assegnati correttamente.
[[email protected] RegionalSharding 14:38:50]$ mongo --port 27017 sales
...
rakshasa(mongos-3.0.5)[mongos] sales> sh.status()
sharding version: {
"_id": 1,
"minCompatibleVersion": 5,
"currentVersion": 6,
"clusterId": ObjectId("55fdddc5746e30dc3651cda4")
}
shards:
{ "_id": "shard-US-East", "host": "shard-US-East/localhost:37017,localhost:37018", "tags": [ "US-East" ] }
{ "_id": "shard-US-West", "host": "shard-US-West/localhost:47017,localhost:47018", "tags": [ "US-West" ] }
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
1 : Success
databases:
{ "_id": "admin", "partitioned": false, "primary": "config" }
{ "_id": "test", "partitioned": false, "primary": "shard-US-East" }
{ "_id": "sales", "partitioned": true, "primary": "shard-US-East" }
sales.users
shard key: { "region": 1 }
chunks:
shard-US-East: 2
shard-US-West: 1
{ "region": { "$minKey" : 1 } } -> { "region": 1 } on: shard-US-East Timestamp(2, 1)
{ "region": 1 } -> { "region": 2 } on: shard-US-East Timestamp(1, 3)
{ "region": 2 } -> { "region": { "$maxKey" : 1 } } on: shard-US-West Timestamp(2, 0)
tag: US-East {
"region": 1
} -> {
"region": 2
}
tag: US-West {
"region": 2
} -> {
"region": 3
}
Verifica che le scritture vengano eseguite sullo shard e sul primario corretti. Crea un record in ciascuna regione
db.users.insert({region:1, name:"us east user"})
db.users.insert({region:2, name:"us west user"})
Puoi accedere a ciascun membro di ogni set di repliche e vedere l'utente est solo sullo shard Stati Uniti orientali e l'utente ovest solo sullo shard Stati Uniti occidentali.