MongoDB sharding the simple way
Here, I will discuss how to create mongo shard in the single machine (locally) for dev environment. My OS is Linux Mint and MongoDB version is 4+.
Install MongoDB:
I downloaded mongodb tar files and extracted it to the /opt/mongo/.
Create database directory:
$mkdir -p /opt/mongo_db/shard_db
I like /opt directory very much, if you do not like create your database directory in /opt, please create it in your desire location. I dislike pointless argument.
To create shard you must have a plan to organize your shard clusters. In this example, I will create 3 shard each shard will have 2 replicate sets and 1 config server with 2 replicate sets and 1 mongos to connect shard cluster via config server
1) Shard servers/clusters
1.1) Create sdb directory inside the shard_db/ directory:
$mkdir sdb
1.2) Inside sdb/ directory we are going to create 6 directories as I mentioned earlier that I am going to create 3 shard with 2 replica sets:
Shard1:
$mkdir s1r1
$mkdir s1r2
Shard2:
$mkdir s2r1
$mkdir s2r2
Shard3:
$mkdir s3r1
$mkdir s3r1
1.3) Create mongo directory in the /etc directory and the following config files:
1.3.1: At first we will create keyfile which will enforce the authentication of the databases among the replica set. It is the minimum effort to enforce the security which acts as API key. It is required in our case because we will have user and password for our database. In the production environment, SSL certificate should be used instead of keyfile.
$openssl rand -base64 10 > keyfile
$chmod 600 keyfile
Otherwise, later you will receive: "permissions on /etc/mongo/keyfile are too open" error.
1.3.2: Now, we will create three config file for shards. The config file is YAML format:
Shard1: shard1_srv_mongod.conf
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
sharding:
clusterRole: shardsvr
replication:
replSetName: sReplicaSet1
net:
bindIp: localhost
authorization: enabled
keyFile: /etc/mongo/keyfile
sharding:
clusterRole: shardsvr
replication:
replSetName: sReplicaSet2
net:
bindIp: localhost
authorization: enabled
keyFile: /etc/mongo/keyfile
sharding:
clusterRole: shardsvr
replication:
replSetName: sReplicaSet3
net:
bindIp: localhost
1.4) Each shard are independent which means they does not know each other. Only config server has the meta data to communicate among sharded servers. We are going to create root user for each shard:
1.4.1: $mongod --dbpath /opt/mongo_db/shard_db/sdb/s1r1 --port 27019
1.4.2: $mongo --port 27019 (in another terminal)
Create root user and password.
>use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
1.4.3: $mongod --dbpath /opt/mongo_db/shard_db/sdb/s2r1 --port 27021
>use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
1.4.4: $mongod --dbpath /opt/mongo_db/shard_db/sdb/s3r1 --port 27023
>use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
At this moment, our shard/clusters (in this case, multiple mongod instances) has root user and corresponding password. You have noticed that we just need to set user and password just for one replicateset of each shard.
Now, we will configure and create 1 config server with 2 replicaset.
$mkdir sdb
1.2) Inside sdb/ directory we are going to create 6 directories as I mentioned earlier that I am going to create 3 shard with 2 replica sets:
Shard1:
$mkdir s1r1
$mkdir s1r2
Shard2:
$mkdir s2r1
$mkdir s2r2
Shard3:
$mkdir s3r1
$mkdir s3r1
1.3) Create mongo directory in the /etc directory and the following config files:
1.3.1: At first we will create keyfile which will enforce the authentication of the databases among the replica set. It is the minimum effort to enforce the security which acts as API key. It is required in our case because we will have user and password for our database. In the production environment, SSL certificate should be used instead of keyfile.
$openssl rand -base64 10 > keyfile
$chmod 600 keyfile
Otherwise, later you will receive: "permissions on /etc/mongo/keyfile are too open" error.
1.3.2: Now, we will create three config file for shards. The config file is YAML format:
Shard1: shard1_srv_mongod.conf
security:
authorization: enabled
keyFile: /etc/mongo/keyfile
sharding:
clusterRole: shardsvr
replication:
replSetName: sReplicaSet1
net:
bindIp: localhost
Shard2: shard2_srv_mongod.conf
security:authorization: enabled
keyFile: /etc/mongo/keyfile
sharding:
clusterRole: shardsvr
replication:
replSetName: sReplicaSet2
net:
bindIp: localhost
Shard3: shard3_srv_mongod.conf
security:authorization: enabled
keyFile: /etc/mongo/keyfile
sharding:
clusterRole: shardsvr
replication:
replSetName: sReplicaSet3
net:
bindIp: localhost
1.4) Each shard are independent which means they does not know each other. Only config server has the meta data to communicate among sharded servers. We are going to create root user for each shard:
1.4.1: $mongod --dbpath /opt/mongo_db/shard_db/sdb/s1r1 --port 27019
1.4.2: $mongo --port 27019 (in another terminal)
Create root user and password.
>use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
1.4.3: $mongod --dbpath /opt/mongo_db/shard_db/sdb/s2r1 --port 27021
>use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
1.4.4: $mongod --dbpath /opt/mongo_db/shard_db/sdb/s3r1 --port 27023
>use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
At this moment, our shard/clusters (in this case, multiple mongod instances) has root user and corresponding password. You have noticed that we just need to set user and password just for one replicateset of each shard.
Now, we will configure and create 1 config server with 2 replicaset.
2) Config servers
2.1) Create the following configdb directory:
$mkdir /opt/mongo_db/shard_db/configdb
2.2) Create two db directories of replicasets:
2.2.1: $mkdir /opt/.../configdb/cs1
2.2.2: $mkdir /opt/.../configdb/cs1
2.3) Add root user and password as shard:
$mongod --dbpath /opt/mongo_db/shard_db/configdb/cs1 --port 27017
$mongo --port 27017
> use admin
>db.createUser({
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
})
3) Initialize shards and config servers replicatesets
At first, we will start with config server:
3.1) $mongod --config /etc/mongod/config_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/configdb/cs1 --auth --port 27017
3.2) $mongod --config /etc/mongod/config_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/configdb/cs2 --auth --port 27018
3.3) Initialize the config server replicasets:
$mongod --port 27017
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "csReplicaSet",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" }
]
})
> rs.initiate( {
_id : "csReplicaSet",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" }
]
})
Now, we will start 3 shards with 2 replicasets (total 6)
3.3) $mongod --config /etc/mongo/shard1_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/sdb/s1r1 --auth --port 27019
3.4) $mongod --config /etc/mongo/shard1_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/sdb/s1r2 --auth --port 27020
3.5) $mongod --config /etc/mongo/shard2_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/sdb/s2r1 --auth --port 27021
3.6) $mongod --config /etc/mongo/shard2_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/sdb/s2r2 --auth --port 27022
3.7) $mongod --config /etc/mongo/shard3_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/sdb/s3r1 --auth --port 27023
3.8) $mongod --config /etc/mongo/shard3_srv_mongod.conf --dbpath /opt/mongo_db/shard_db/sdb/s3r2 --auth --port 27024
3.9) Initialize shard1 replicatesets:
$mongo --port 27019
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "sReplicaSet1",
members: [
{ _id: 0, host: "localhost:27019" },
{ _id: 1, host: "localhost:27020" }
]
})
4.0) Initialize shard2 replicatesets:
$mongo --port 27021
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "sReplicaSet2",
members: [
{ _id: 0, host: "localhost:27021" },
{ _id: 1, host: "localhost:27022" }
]
})
4.1) Initialize the replicaset of config servers from the primary shard2:
$mongo --port 27023
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "sReplicaSet3",
members: [
{ _id: 0, host: "localhost:27023" },
{ _id: 1, host: "localhost:27024" }
]
})
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "sReplicaSet1",
members: [
{ _id: 0, host: "localhost:27019" },
{ _id: 1, host: "localhost:27020" }
]
})
4.0) Initialize shard2 replicatesets:
$mongo --port 27021
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "sReplicaSet2",
members: [
{ _id: 0, host: "localhost:27021" },
{ _id: 1, host: "localhost:27022" }
]
})
4.1) Initialize the replicaset of config servers from the primary shard2:
$mongo --port 27023
> use admin
> db.auth("admin","admin")
> rs.initiate( {
_id : "sReplicaSet3",
members: [
{ _id: 0, host: "localhost:27023" },
{ _id: 1, host: "localhost:27024" }
]
})
4) Mongos
Create mongos to perform db operation:
At first, we will create configuration file for mongos in the /etc/mongo/mongos_mongod.conf:
security:
keyFile: /etc/mongod/keyfile
replication:
localPingThresholdMs: 10000
sharding:
configDB: csReplicaSet/localhost:27017,localhost:27018
$mongos --port 27025 --config /etc/mongod/mongos_mongod.conf
At first, we will create configuration file for mongos in the /etc/mongo/mongos_mongod.conf:
security:
keyFile: /etc/mongod/keyfile
replication:
localPingThresholdMs: 10000
sharding:
configDB: csReplicaSet/localhost:27017,localhost:27018
$mongos --port 27025 --config /etc/mongod/mongos_mongod.conf
> use admin
> db.auth(“admin”,”admin”)
Add shards to config server via mongos:
> sh.addShard("sReplicaSet1/localhost:27019")
> sh.addShard("sReplicaSet1/localhost:27020")
> sh.addShard("sReplicaSet2/localhost:27021")
> sh.addShard("sReplicaSet2/localhost:27022")
> sh.addShard("sReplicaSet3/localhost:27023")
> sh.addShard("sReplicaSet3/localhost:27024")
Create database called: “mydb”
> db.createUser(
{
user: "test",
pwd: "test",
roles: [{role:"readWrite", db:"mydb"}]
})
In this example, we will create job queue collection:
> db.createCollection("mycollection")
> db.mycollection.createIndex({myKey:1})
Note: myKey is compound shard key. I did not explain about the shard key in this blog.
Enable the sharding on database
> sh.enableSharding("mydb")
Add shard key to the checkin_queue:
> sh.shardCollection("mydb.mycollection", {myKey:1})
Extras:
Change the chunk size to see the distribution among the shards. The default size is 64MB. Shard distribution is not based on volume of request. It is based on volume of payload size.
Therefore, we may not see any distribution in the simple scenario.
Change shard chunk size:
$mongo --port 27025 --host localhost
> use admin
> db.auth(“admin”,”admin”)
> use config
> db.settings.save({_id:”chunksize”, value=1MB});
Check shard status:
$mongo --port 27025 --host localhost
> use admin
> db.auth(“admin”,”admin”)
> sh.status()
Check shard distribution:
$mongo --port 27025 --host localhost
> use admin
> db.auth(“admin”,”admin”)
> db.checkinJobCollection.getShardDistribution()
Comments
Post a Comment