MongoDB 分片集群搭建教程

当单个 MongoDB 副本集 的存储容量或读写性能达到瓶颈时,分片(Sharding)是实现水平扩展的解决方案。分片将数据分散到多个分片服务器上,每个分片只存储数据的一部分,从而突破单节点的限制。本文将在搬瓦工 VPS 上演示一个最小化的分片集群搭建流程。

一、分片集群架构

MongoDB 分片集群由三种组件组成:

  • Shard(分片服务器):存储实际数据。每个分片本身就是一个副本集,提供高可用。
  • Config Server(配置服务器):存储集群元数据和分片路由信息。也是一个副本集。
  • Mongos(路由):客户端的入口点,将请求路由到正确的分片。无状态,可以部署多个。

本教程搭建包含 2 个分片的最小集群。为简化演示,将在同一台 VPS 上使用不同端口模拟。生产环境应分别部署在独立服务器上。

二、环境规划

# Config Server 副本集 (configRS)
# 端口: 27019, 27020, 27021

# Shard 1 副本集 (shard1RS)
# 端口: 27101, 27102, 27103

# Shard 2 副本集 (shard2RS)
# 端口: 27201, 27202, 27203

# Mongos 路由
# 端口: 27017

创建数据目录:

mkdir -p /data/mongodb/{config1,config2,config3}
mkdir -p /data/mongodb/{shard1a,shard1b,shard1c}
mkdir -p /data/mongodb/{shard2a,shard2b,shard2c}
mkdir -p /var/log/mongodb

三、启动 Config Server 副本集

# 启动三个 Config Server
mongod --configsvr --replSet configRS --port 27019 --dbpath /data/mongodb/config1 --logpath /var/log/mongodb/config1.log --fork --bind_ip_all
mongod --configsvr --replSet configRS --port 27020 --dbpath /data/mongodb/config2 --logpath /var/log/mongodb/config2.log --fork --bind_ip_all
mongod --configsvr --replSet configRS --port 27021 --dbpath /data/mongodb/config3 --logpath /var/log/mongodb/config3.log --fork --bind_ip_all

初始化 Config Server 副本集:

mongosh --port 27019 --eval '
rs.initiate({
  _id: "configRS",
  configsvr: true,
  members: [
    { _id: 0, host: "localhost:27019" },
    { _id: 1, host: "localhost:27020" },
    { _id: 2, host: "localhost:27021" }
  ]
})'

四、启动 Shard 副本集

4.1 Shard 1

mongod --shardsvr --replSet shard1RS --port 27101 --dbpath /data/mongodb/shard1a --logpath /var/log/mongodb/shard1a.log --fork --bind_ip_all
mongod --shardsvr --replSet shard1RS --port 27102 --dbpath /data/mongodb/shard1b --logpath /var/log/mongodb/shard1b.log --fork --bind_ip_all
mongod --shardsvr --replSet shard1RS --port 27103 --dbpath /data/mongodb/shard1c --logpath /var/log/mongodb/shard1c.log --fork --bind_ip_all

mongosh --port 27101 --eval '
rs.initiate({
  _id: "shard1RS",
  members: [
    { _id: 0, host: "localhost:27101" },
    { _id: 1, host: "localhost:27102" },
    { _id: 2, host: "localhost:27103" }
  ]
})'

4.2 Shard 2

mongod --shardsvr --replSet shard2RS --port 27201 --dbpath /data/mongodb/shard2a --logpath /var/log/mongodb/shard2a.log --fork --bind_ip_all
mongod --shardsvr --replSet shard2RS --port 27202 --dbpath /data/mongodb/shard2b --logpath /var/log/mongodb/shard2b.log --fork --bind_ip_all
mongod --shardsvr --replSet shard2RS --port 27203 --dbpath /data/mongodb/shard2c --logpath /var/log/mongodb/shard2c.log --fork --bind_ip_all

mongosh --port 27201 --eval '
rs.initiate({
  _id: "shard2RS",
  members: [
    { _id: 0, host: "localhost:27201" },
    { _id: 1, host: "localhost:27202" },
    { _id: 2, host: "localhost:27203" }
  ]
})'

五、启动 Mongos 路由

mongos --configdb configRS/localhost:27019,localhost:27020,localhost:27021 --port 27017 --logpath /var/log/mongodb/mongos.log --fork --bind_ip_all

连接 Mongos 并添加分片:

mongosh --port 27017

sh.addShard("shard1RS/localhost:27101,localhost:27102,localhost:27103")
sh.addShard("shard2RS/localhost:27201,localhost:27202,localhost:27203")

// 查看分片状态
sh.status()

六、启用分片和选择分片键

6.1 为数据库启用分片

sh.enableSharding("myapp")

6.2 分片键选择策略

分片键的选择直接影响数据分布和查询性能,是分片集群最关键的设计决策。

  • 哈希分片:数据均匀分布,适合写入密集型负载。但范围查询需要广播到所有分片。
  • 范围分片:支持高效的范围查询,但可能导致热点分片。
  • 复合分片键:组合多个字段,兼顾分布均匀和查询效率。

6.3 配置分片集合

// 哈希分片示例(适合用户表)
sh.shardCollection("myapp.users", { user_id: "hashed" })

// 范围分片示例(适合日志表)
sh.shardCollection("myapp.logs", { created_at: 1 })

// 复合分片键示例(适合订单表)
sh.shardCollection("myapp.orders", { user_id: 1, order_date: 1 })

七、数据均衡与管理

// 查看分片分布
use myapp
db.users.getShardDistribution()

// 查看均衡器状态
sh.getBalancerState()
sh.isBalancerRunning()

// 设置均衡窗口(仅在低峰期执行迁移)
use config
db.settings.updateOne(
  { _id: "balancer" },
  { $set: { activeWindow: { start: "02:00", stop: "06:00" } } },
  { upsert: true }
)

// 手动移动 chunk
sh.moveChunk("myapp.users", { user_id: MinKey }, "shard2RS")

八、分片集群监控

// 查看集群详细状态
sh.status(true)

// 查看各分片的 chunk 数量
use config
db.chunks.aggregate([
  { $group: { _id: "$shard", count: { $sum: 1 } } }
])

// 查看慢操作
db.currentOp({ "secs_running": { $gt: 5 } })

// 查看分片键统计
db.collection.stats().shards

九、Docker Compose 部署方案

生产环境推荐使用 Docker Compose 简化部署。如果你还没安装 Docker,请参考 Docker 安装教程。以下是简化的 Compose 配置框架:

version: '3.8'
services:
  config1:
    image: mongo:7.0
    command: mongod --configsvr --replSet configRS --port 27019
    volumes:
      - config1_data:/data/configdb

  shard1a:
    image: mongo:7.0
    command: mongod --shardsvr --replSet shard1RS --port 27018
    volumes:
      - shard1a_data:/data/db

  mongos:
    image: mongo:7.0
    command: mongos --configdb configRS/config1:27019,config2:27019,config3:27019 --port 27017
    ports:
      - "27017:27017"
    depends_on:
      - config1

volumes:
  config1_data:
  shard1a_data:

十、常见问题

  • 分片键选错:分片键一旦设定不可更改(MongoDB 5.0 之前)。务必在设计阶段充分评估查询模式。
  • Jumbo Chunk:单个 chunk 超过 64MB 且无法分裂,通常因为分片键值重复太多导致。
  • 均衡器影响性能:chunk 迁移会消耗 IO 和网络带宽,建议设置均衡窗口在低峰期执行。
  • scatter-gather 查询:查询不包含分片键时需要广播到所有分片,性能较差。确保高频查询包含分片键。

总结

MongoDB 分片集群是应对海量数据和高并发的利器,但架构复杂度也相应增加。在搬瓦工 VPS 上,如果数据量在百 GB 级以下,副本集 通常已经足够。只有当单副本集无法满足需求时再考虑分片。选购搬瓦工 VPS 请查看 全部方案,使用优惠码 NODESEEK2026 享受 6.77% 折扣,通过 bwh81.net 进入官网购买。

关于本站

搬瓦工VPS中文网(bwgvps.com)是非官方中文信息站,整理搬瓦工的方案、优惠和教程。我们不销售主机,不提供技术服务。

新手必读
搬瓦工优惠码

NODESEEK2026(优惠 6.77%)

购买时填入即可抵扣。