Skip to content

分片

分片(Sharding)是MongoDB实现水平扩展的核心机制。本章将介绍分片的概念、架构、配置和管理方法。

分片概述

什么是分片

javascript
// 分片是将数据分散存储在多个服务器上的方法

// 分片的特点:
// 1. 水平扩展:通过增加分片扩展存储容量和处理能力
// 2. 负载均衡:数据自动分布,负载分散到多个节点
// 3. 高可用:每个分片可以是复制集
// 4. 透明访问:应用程序无需关心数据分布

// 分片的适用场景:
// - 数据量超过单机存储能力
// - 活跃数据集超过内存容量
// - 吞吐量需求超过单机能力

分片架构

// MongoDB分片集群架构
//
// mongos (路由器) -----> mongos (路由器)
//      |                    |
//      v                    v
// Config Servers (配置服务器 - 复制集)
//      |
//      v
// +----+----+----+
// |    |    |    |
// v    v    v    v
// 分片1 分片2 分片3 ...
// (复制集)

分片组件

组件说明

javascript
// 分片集群由三个组件组成:

// 1. Shard(分片)
//    - 存储数据子集
//    - 通常是一个复制集
//    - 提供数据冗余和高可用

// 2. mongos(路由器)
//    - 接收客户端请求
//    - 路由请求到正确的分片
//    - 合并结果返回客户端

// 3. Config Servers(配置服务器)
//    - 存储集群元数据
//    - 存储分片键范围信息
//    - 必须是复制集

部署分片集群

部署配置服务器

bash
# 部署配置服务器复制集

# 启动配置服务器实例
mongod --configsvr --replSet configRs --port 27019 --dbpath /data/config1
mongod --configsvr --replSet configRs --port 27020 --dbpath /data/config2
mongod --configsvr --replSet configRs --port 27021 --dbpath /data/config3

# 初始化配置服务器复制集
mongosh --port 27019
rs.initiate({
    _id: "configRs",
    configsvr: true,
    members: [
        { _id: 0, host: "localhost:27019" },
        { _id: 1, host: "localhost:27020" },
        { _id: 2, host: "localhost:27021" }
    ]
})

部署分片

bash
# 部署分片复制集

# 启动分片实例
mongod --shardsvr --replSet shard1 --port 27017 --dbpath /data/shard1-1
mongod --shardsvr --replSet shard1 --port 27018 --dbpath /data/shard1-2

# 初始化分片复制集
mongosh --port 27017
rs.initiate({
    _id: "shard1",
    members: [
        { _id: 0, host: "localhost:27017" },
        { _id: 1, host: "localhost:27018" }
    ]
})

# 重复以上步骤部署更多分片

启动mongos

bash
# 启动mongos路由器
mongos --configdb configRs/localhost:27019,localhost:27020,localhost:27021 --port 27022

# 连接mongos
mongosh --port 27022

添加分片到集群

javascript
// 连接到mongos后执行

// 添加分片
sh.addShard("shard1/localhost:27017,localhost:27018")
sh.addShard("shard2/localhost:27023,localhost:27024")

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

分片键

分片键选择

javascript
// 分片键决定数据如何分布

// 分片键选择原则:
// 1. 基数高:字段值变化多,分布均匀
// 2. 写入分散:避免热点
// 3. 查询覆盖:常用查询条件包含分片键
// 4. 不可变性:分片键值不能修改

// 常见分片键类型:
// - 单字段分片键
// - 复合分片键
// - 哈希分片键

范围分片

javascript
// 范围分片:按分片键值范围划分数据

// 启用分片
sh.enableSharding("mydb")

// 创建范围分片
sh.shardCollection("mydb.users", { userId: 1 })

// 特点:
// - 支持范围查询
// - 可能产生热点
// - 数据分布可能不均匀

哈希分片

javascript
// 哈希分片:按分片键哈希值分布数据

// 创建哈希索引
db.users.createIndex({ userId: "hashed" })

// 创建哈希分片
sh.shardCollection("mydb.users", { userId: "hashed" })

// 特点:
// - 数据分布均匀
// - 不支持范围查询优化
// - 避免热点问题

分片管理

查看分片状态

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

// 查看集合分片信息
db.users.getShardDistribution()

// 查看分片标签
sh.shardCollection("mydb.users", { region: 1 }, tag: "region")

平衡器管理

javascript
// 查看平衡器状态
sh.getBalancerState()

// 启用平衡器
sh.setBalancerState(true)

// 禁用平衡器
sh.setBalancerState(false)

// 查看平衡进度
sh.isBalancerRunning()

手动迁移数据块

javascript
// 手动迁移数据块
sh.moveChunk("mydb.users", { userId: 100 }, "shard2")

// 分割数据块
sh.splitAt("mydb.users", { userId: 1000 })

// 查看数据块信息
db.chunks.find({ ns: "mydb.users" })

本章小结

本章介绍了MongoDB分片的相关知识:

  1. 分片概述:理解分片的概念和架构
  2. 分片组件:了解Shard、mongos、Config Servers的作用
  3. 部署分片:学会部署分片集群
  4. 分片键:掌握范围分片和哈希分片的选择
  5. 分片管理:学会管理平衡器和数据迁移

至此,MongoDB教程全部完成。希望本教程能帮助你掌握MongoDB数据库的核心知识和技能!