Skip to main content

·

[MongoDB – Part 4] Hands-On MongoDB Sharding: Deployment and Configuration

I. INTRODUCTION

For those who are new to my blog, let me briefly introduce myself. My articles mainly cover Backend, Blockchain, and DevOps. Besides technical topics, I also share my thoughts, personal reflections, and perspectives on life, particularly in areas such as psychology, finance, and personal development.
Continuing from my previous post, I'm picking up the MongoDB series I started back in 2022 with an article on the theoretical principles behind MongoDB sharding. If you'd like to revisit the earlier articles in this series, you can find them here:
  • Part 1: Configuring a Standalone MongoDB Instance
  • Part 2: Configuring a MongoDB Replica Set
  • Part 3: MongoDB Sharding — Architecture and Configuration Principles
Since the topic is quite extensive, I've split MongoDB sharding into two articles. Today, we'll continue with the next part: Hands-on MongoDB Sharding Deployment and Configuration [MongoDB — Part 4].

II. HANDS-ON IMPLEMENTATION

Before diving into the practical steps, I recommend revisiting Part 2 of the MongoDB series to learn how to set up a MongoDB replica set.

1. Step-by-Step Guide to Setting Up MongoDB Sharding

Step 1 — Set Up the MongoDB Config Server
  • The Config Server manages metadata and data distribution information for the sharded cluster.
  • Initialize a Config Server Replica Set, typically consisting of three nodes to ensure high availability.
Step 2 — Configure Shard Server Replica Sets
  • Set up Replica Sets to represent individual shards.
  • Each Replica Set stores a portion of the cluster's data.
  • Deploy at least two Replica Sets to support load distribution.
Step 3 — Run mongos and Add Shards to the Cluster
  • Use mongos as the router to direct queries to the appropriate shards.
  • Connect mongos to the Config Server.
  • Add the shard Replica Sets to the cluster through mongos.
Step 4 — Shard Data in Collections
  • Enable sharding for the database.
  • Shard the collections that require it by selecting an appropriate shard key to optimize performance.
Step 5 — Analyze Shard Utilization
  • Monitor and analyze shard utilization to ensure data is distributed evenly.
  • Use MongoDB commands such as sh.status() to inspect the sharding status.

2. Dockerizing MongoDB Sharding

Deployment Architecture

  • VPS 1:
    • Hosts the Config Server and mongos.
    • Hosts one Shard Replica Set (shard1).
  • VPS 2:
    • Hosts one Shard Replica Set (shard2).
!image.png

Install Docker and Docker Compose on Both VPS Instances

  1. Install Docker
    1. sudo apt update sudo apt install docker.io -y sudo systemctl start docker sudo systemctl enable docker
  1. Install Docker Compose
    1. sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose

Sample docker-compose.yml Files for Both VPS Instances

VPS 1: Config Server, mongos, and shard1

version: '3.8' services: configsvr: image: mongo:6.0 container_name: configsvr command: --configsvr --replSet configReplSet --bind_ip_all ports: - "27019:27019" volumes: - config_data:/data/db mongos: image: mongo:6.0 container_name: mongos command: > mongos --configdb configReplSet/configsvr:27019 ports: - "27017:27017" depends_on: - configsvr shard1-a: image: mongo:6.0 container_name: shard1-a command: --shardsvr --replSet shard1 --bind_ip_all ports: - "27021:27021" volumes: - shard1_data:/data/db volumes: config_data: shard1_data:

VPS 2: shard2

version: '3.8' services: shard2-a: image: mongo:6.0 container_name: shard2-a command: --shardsvr --replSet shard2 --bind_ip_all ports: - "27022:27022" volumes: - shard2_data:/data/db volumes: shard2_data:

Deployment Steps

  1. Start Docker Compose on Both VPS Instances
    1. docker-compose up -d
  1. Configure the Replica Sets
      • Connect to each container:
        • docker exec -it <container_name> mongo
      • Initialize the Replica Sets for the Config Server, shard1, and shard2 as appropriate.
        • rs.initiate({ _id: "configReplSet", members: [{ _id: 0, host: "configsvr:27019" }] })
  1. Add Shards to the Cluster
      • Connect to mongos:
        • docker exec -it mongos mongo
      • Add the shards:
        • sh.addShard("shard1/shard1-a:27021") sh.addShard("shard2/shard2-a:27022")
  1. Enable Sharding for the Database
    1. sh.enableSharding("myDatabase") sh.shardCollection("myDatabase.myCollection", { shardKeyField: 1 })
  1. Check the Sharding Status
    1. sh.status()

III. PRACTICAL EXPERIENCE

1. Do You Need an Arbiter Node for MongoDB Sharding?

In a MongoDB sharded cluster, each shard is typically deployed as a Replica Set to provide high availability and fault tolerance. When deploying sharding with Replica Sets, a common question is whether adding an arbiter node can improve the election process while keeping infrastructure costs down.
!image.png

When Should You Use an Arbiter Node in a Sharded Cluster?

Consider adding an arbiter node in the following situations:
  1. A shard's Replica Set has an even number of voting members:
      • An arbiter can help establish an odd number of votes, allowing the system to elect a primary when some nodes become unavailable.
      • For example, suppose a shard has two nodes, A and B. If one node goes down, the remaining node cannot obtain a majority because 1 out of 2 votes is insufficient. Adding an arbiter, C, creates three votes, allowing the remaining data-bearing node to obtain a majority of 2 out of 3 votes.
  1. Limited infrastructure resources:
      • An arbiter is a lightweight process that does not store data. This can reduce infrastructure costs, especially in environments where resource optimization is important, such as EC2 micro instances.
  1. Distributed infrastructure:
      • In deployments spanning multiple data centers or availability zones, an arbiter may help resolve voting outcomes during a network partition.
      • For example, with four nodes—two in DC1 and two in DC2—an arbiter could be placed in either location to influence which partition can maintain a voting majority and prevent both sides from independently electing a primary.

When Is an Arbiter Node Unnecessary?

  • The Replica Set already has an odd number of voting members:
    • An arbiter is generally unnecessary because the Replica Set already has an odd number of votes to support primary elections.
  • High-performance requirements:
    • An arbiter does not store data. If a data-bearing node becomes unavailable, the cluster may need to elect a new primary before normal writes can resume. Depending on the topology, this can affect applications that require low latency or handle high query volumes.

Considerations When Deploying an Arbiter in a Sharded Cluster

  1. Avoid placing the arbiter on the same server as another node in the Replica Set:
      • If that server goes down, you could lose both a data-bearing node and the arbiter, potentially losing the voting majority.
  1. Do not deploy more than one arbiter per Replica Set:
      • An arbiter's role is to participate in voting without storing data. Adding multiple arbiters is generally unnecessary and may complicate the configuration.
  1. Consider the arbiter's placement during network partitions:
      • An arbiter should be placed where it can reliably communicate with the relevant members and where its placement supports the intended failure-domain strategy.

Takeaways

  • An arbiter can be useful in certain Replica Set configurations, particularly when infrastructure resources are limited.
  • In a sharded cluster, whether an arbiter is appropriate depends on each shard's voting configuration and failure-tolerance requirements.
  • However, arbiters should not be used indiscriminately. Their placement and role must be carefully considered to avoid losing a voting majority or introducing configuration issues.

2. Shard Key Selection Strategies

1. Low-Cardinality Shard Key

A low-cardinality shard key is based on a field with a limited number of distinct values, such as a continent.
!image.png
  • Advantages: Easy to understand and implement initially. For example, you could divide shards by geographical regions using ranges such as:
    • (-∞, "Antarctica")
    • ["Antarctica", "Asia")
    • ["Asia", "Australia")
    • ...
  • Disadvantages: If one shard contains significantly more data than others—for example, because Asia generates much more data—the system may struggle to distribute the workload evenly. Adding another field, such as a combination of continent and country, may improve distribution, but this approach may not be optimal in the long run.

2. Ascending Shard Key

This strategy uses an ascending shard key, typically a timestamp or ObjectId, to optimize access to more recent data.
  • Advantages:
    • Works well for applications that frequently access recent data, such as logs or transaction histories.
    • Recent data can be easy to locate when it is stored in the shard responsible for the latest key range.
  • Disadvantages:
    • New data is continually written to the shard responsible for the highest key values, causing that shard's data range to split repeatedly.
    • This can create a significant write hotspot and lead to severe load imbalance, particularly in write-intensive systems.

3. Random Shard Key

A random shard key uses random values, such as an MD5 hash or other unique values, to distribute data across shards.
  • Advantages:
    • Can distribute data more evenly across shards from the outset.
    • Helps prevent data from becoming concentrated on a small number of shards.
  • Disadvantages:
    • Random distribution can make queries less efficient when they cannot target a shard using the shard key or an appropriate index.
    • During rebalancing, MongoDB may need to migrate chunks across shards, consuming additional time and resources.

4. A Good Shard Key

A good shard key must balance data distribution with query performance. One approach is to combine the following considerations:
  • Ascending key: Use time-based values, such as date/time, to divide data into appropriate ranges.
  • Search key: Combine the time-based field with another field, such as user or category, to improve data distribution and support query patterns.
Example:
Suppose an application needs to analyze data from the most recent month.
  1. Initially, the shard key is {month, user}, with a single chunk covering the entire key space:
      • (-∞, ∞)
  1. As data grows, the chunk may split into smaller ranges, such as:
      • ((-∞, -∞), ("2011-04", "susan"))
      • [("2011-04", "susan"), (∞, ∞)]
  1. When a new month begins, data from the previous month may be stored on a less heavily utilized shard, helping reduce the load on the primary shards handling new data.
Advantages:
  • Distributes data based on both time and the associated entity.
  • Older data does not necessarily need to be redistributed, potentially reducing unnecessary chunk migrations.

Summary

  • Low-cardinality shard key: Suitable for smaller systems with relatively stable workloads, provided the selected key can support sufficient data distribution.
  • Ascending shard key: Useful for accessing recent data, but requires careful design to avoid creating a write hotspot on the shard handling the highest key values.
  • Random shard key: Can improve distribution, but query targeting and rebalancing costs must be considered.
  • Good shard key: A carefully designed combination of time-based and query-oriented fields can help balance data distribution and long-term query performance.

IV. CONCLUSION

More than two years after publishing the first article in my MongoDB knowledge-sharing series, I've finally completed the series with this article on MongoDB sharding.
I hope this article has helped you understand the basic steps involved in setting up a MongoDB sharded cluster, along with some practical tips and lessons I've learned from hands-on experience.
As I mentioned in my previous blog post, I'll try to publish more consistently and focus on writing more articles in English on my personal blog. I'll also continue exploring other topics, including finance, psychology, critical thinking, and personal reflections on life.
If you found this article interesting or useful, feel free to leave a like, upvote, or comment. Your feedback and encouragement motivate me to keep sharing more high-quality, insightful, and engaging technical content in the future.

V. REFERENCES

Subscribe to the newsletter

Get new posts on Backend, Blockchain, DevOps, and life notes.

Loading Comments...