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

        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" } ]
           })

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" }
           ]
        })

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" }
           ]
      })

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

    > 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

Popular posts from this blog

There is a process already using the admin port 4848 -- it probably is another instance of a GlassFish server; ERROR

How to Convert OutputStream to InputStream

How to compile and install GraphicsMagick (GM) in Linux