Danke @avanti, @MarkusWMalhberg – das Nachdenken, wie ich auf die Kommentare reagieren soll, hat mich in die richtige Richtung getrieben. Es hat ein bisschen gedauert, das zusammen zu bekommen, also werde ich ein bisschen ausführlich sein, um die Konfiguration zu erklären.
Übersicht
Wir konzentrieren uns auf die Benutzererfahrung und möchten eine Mongo-Datenbankkonfiguration erstellen, die es ermöglicht, dass Lese- und Schreibvorgänge am nächsten beim Benutzer erfolgen.
Annahmen
- Benutzer lesen und schreiben fast immer Dokumente in ihrer Region und haben nichts dagegen, wenn seltene Lesevorgänge in Daten anderer Regionen langsamer sind.
- Jedes Dokument enthält einen Schlüssel, der seine Region angibt (zur Vereinfachung/Klarheit)
Ein Großteil der Sharding-Dokumentation konzentriert sich auf HA/DR. Bei Benutzererfahrung und regionaler Konformität liegt der Fokus auf der Lokalität statt auf der Lastverteilung.
In diesem Beispiel werden HA/DR, Lesepräferenzen und Schreibprobleme vollständig ignoriert, aber diese müssen angegangen werden, wenn der POC ausgereift ist. Das Beispiel ignoriert diese zugunsten der Klarheit, um das Ziel zu erreichen:lokale Lese-/Schreibzugriffe.
Referenzen
- Betriebliche Segmentierung
- Shard-Tags verwalten
- ReplicaSet-Konfiguration
- Verschiedene Mongos-Konfigurationsdatenbankfehler
Tricks
Wir wissen es
- Wir wollen eine Anwendungsdatenbank, damit alle Daten verfügbar sind
- Wir möchten, dass Benutzer lokal lesen/schreiben können, also brauchen wir eine Datenbank in der Nähe jeder Benutzergruppe; wir brauchen ein Nachbildungsset
- Schreibvorgänge können nur auf primäre Replikatsatz-Knoten gemacht werden, um also primäre Knoten neben jeder Benutzergruppe zu erhalten, benötigen wir mehrere Replikate; ein fragmentierter Cluster
Innerhalb des standardmäßigen ReplicaSet- und Sharding-Wissens gibt es zwei Schlüssel zu dieser Konfiguration:
- Weisen Sie dem regional lokalen ReplicaSet-Knoten eine Priorität zu, um sicherzustellen, dass er primär wird.
- Verwenden Sie ortsbezogenes Shard-Key-Tagging, um sicherzustellen, dass Daten in lokale Shards geschrieben werden
Shard-Keys können alles sein:Uns geht es nur darum, dass Benutzer lokal lesen/schreiben können, im Gegensatz zu einer effektiven Lastverteilung.
Jede Sammlung muss geteilt werden, oder Schreibvorgänge gehen an Shard Null.
Gewünschte Konfiguration
Die Konfiguration
#!/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
Testen
Überprüfen Sie mit sh.status()
, ob unsere Konfiguration korrekt ist . Hinweis-Shards werden korrekt zugewiesen und Tags und regionale Shard-Schlüssel werden korrekt zugewiesen.
[[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
}
Stellen Sie sicher, dass Schreibvorgänge auf dem richtigen Shard und primären Shard ausgeführt werden. Erstellen Sie einen Datensatz in jeder Region
db.users.insert({region:1, name:"us east user"})
db.users.insert({region:2, name:"us west user"})
Sie können sich bei jedem Mitglied jedes Replikatsatzes anmelden und den östlichen Benutzer nur auf dem US-Ost-Shard und den westlichen Benutzer nur auf dem US-West-Shard sehen.