1. MongoDB 分片集群概述
分片集群(Sharded Cluster)是 MongoDB 实现水平扩展的核心方案,通过将数据分布到多个服务器(分片)中,解决单机存储容量和性能瓶颈。其核心目标是实现数据的分布式存储与负载均衡。
2. 分片集群架构与核心组件
2.1 分片(Shard)
作用:存储实际数据片段,每个分片包含数据集的一个子集。
实现方式:推荐使用副本集(Replica Set)作为分片,以提高可用性和数据冗余。
2.2 配置服务器(Config Server)
作用:存储集群元数据(如分片键、数据分布、路由规则等)。
要求:必须为副本集形式,确保元数据高可用。
2.3 查询路由(Mongos)
作用:作为客户端访问集群的入口,负责路由请求到目标分片。
特性:无状态服务,可部署多个实例以提高并发能力。
3. 分片键(Shard Key)与数据分布
3.1 分片键定义
定义:用于划分数据的字段(如
user_id
或timestamp
)。重要性:分片键的选择直接影响数据均衡性和查询性能。需满足高基数、低频率、值分布均匀。
3.2 Chunks(数据块)详解
定义:Chunk 是 MongoDB 分片集群中数据分片的基本单位,表示分片键值范围内的连续数据段。默认大小为 64MB~128MB(可配置)。
关键特性:
动态迁移:MongoDB 的平衡器(Balancer)会根据分片负载自动迁移 Chunk,确保数据均匀分布。
元数据记录:每个 Chunk 的边界信息(如最小 / 最大分片键值)存储在配置服务器中。
拆分机制:当 Chunk 大小超过阈值时,MongoDB 会自动将其拆分为多个更小的 Chunk。
操作流程:
数据写入时,根据分片键值分配到对应的 Chunk。
Chunk 达到阈值后触发拆分,生成新 Chunk。
平衡器监控各分片的 Chunk 数量,自动迁移 Chunk 以实现负载均衡。
4. 分片集群注意事项
4.1 容量规划与 Chunk 管理
注意点:当单个分片存储容量达到 60% 时,建议扩容新分片。
原因:容量超过阈值会导致 Chunk 迁移延迟,甚至触发频繁的自动拆分与迁移,增加集群负载,影响读写性能。
4.2 分片键设计
注意点:优先选择复合分片键(如
{region: 1, user_id: 1}
)。原因:单调递增的分片键(如时间戳)会导致新数据集中在最新 Chunk,形成写入热点;复合分片键可分散写入压力,同时提升范围查询效率。
4.3 配置服务器保护
注意点:禁止直接操作配置服务器,仅通过
mongos
管理集群。原因:配置服务器存储 Chunk 元数据,直接修改可能导致 Chunk 分布信息错误,引发数据路由混乱。
4.4 索引管理
注意点:在每个分片上为分片键创建索引。
原因:未创建索引时,查询会退化为全分片扫描,尤其是跨多个 Chunk 的查询会显著降低性能。
4.5 平衡器(Balancer)控制
注意点:在业务低峰期手动调整平衡器窗口时间。
原因:平衡器迁移 Chunk 时会占用大量 I/O 和网络资源,高峰期操作可能导致服务延迟。
5. Chunk 相关运维场景
5.1 Chunk 手动迁移
场景:分片负载不均时,可手动指定迁移特定 Chunk。
- 命令示例:
sh.moveChunk("database.collection", {shardKey: value}, "targetShard")
MongoDB 分片集群部署
共十一台机器
角色 |
IP |
端口 |
---|---|---|
shard1 - Master | 192.168.80.11 |
27017 |
shard1 - slave | 192.168.80.22 |
27017 |
shard1 - slave | 192.168.80.33 |
27017 |
shard2 - Master | 192.168.80.44 |
27017 |
shard2 - slave | 192.168.80.55 |
27017 |
shard2 - slave | 192.168.80.66 |
27017 |
配置服务器 - Master | 192.168.80.77 |
27019 |
配置服务器 - slave | 192.168.80.88 |
27019 |
配置服务器 - slave | 192.168.80.99 |
27019 |
Mongos + Keepalived1 | 192.168.80.100 |
27017 |
Mongos + Keepalived2 | 192.168.80.200 |
27017 |
搭建 shard1 复制集
shard1 角色编辑配置文件:
systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: port: 27017 bindIp: 0.0.0.0 replication: oplogSizeMB: 2048 replSetName: shard1 sharding: clusterRole: shardsvr
shard1 主节点赋值 config 变量
config = { _id: 'shard1', members: [ {_id: 0, host: '192.168.80.11:27017'}, {_id: 1, host: '192.168.80.22:27017'} , {_id: 2, host: '192.168.80.33:27017'}] } rs.initiate(config)
shard1 搭建完毕:
搭建 shard2 复制集
shard2 角色编辑配置文件:
systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: port: 27017 bindIp: 0.0.0.0 replication: oplogSizeMB: 2048 replSetName: shard2 sharding: clusterRole: shardsvr
shard2 主节点赋值 config 变量
config = { _id: 'shard2', members: [ {_id: 0, host: '192.168.80.44:27017'}, {_id: 1, host: '192.168.80.55:27017'} , {_id: 2, host: '192.168.80.66:27017'}] } rs.initiate(config)
shard2 搭建完毕:
搭建 config Server 节点
配置 config 节点配置文件
systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: bindIp: 0.0.0.0 replication: oplogSizeMB: 2048 replSetName: config sharding: clusterRole: configsvr
config Server 主节点赋值 config 变量
systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: bindIp: 0.0.0.0 replication: oplogSizeMB: 2048 replSetName: config sharding: clusterRole: configsvr
搭建 Mongos 节点
配置 Mongos 节点配置文件
systemLog: destination: file path: "/mongodb/log/mongodb.log" sharding: configDB: config/192.168.80.77:27019,192.168.80.88:27019,192.168.80.99:27019 processManagement: fork: true net: bindIp: 0.0.0.0
关闭 mongod 服务,启动 mongos 服务
systemctl stop mongod.service mongos -f /mongodb/conf/mongo.conf ss -nltp
mongos 两节点配置成功
mongos 添加分片
mongo admin sh.addShard("shard1/192.168.80.11:27017") sh.addShard("shard2/192.168.80.44:27017")
配置分片规则
启用 Range 分片规则
//启用数据库的分片 sh.enableSharding("test") //创建索引 use test db.vast.createIndex({id:1}) //开启range分片规则 sh.shardCollection("test.vase",{id:1}) //造数据 use test for(i=0;i<100000;i++){db.vase.insert({"id":i,"name":"kk","date":new Date()})}
启用 Hash 分片规则
//启用数据库的分片 sh.enableSharding("TestHash") //指定在TestHash库的testtable表上创建hash索引 use TestHash db.testtable.createIndex({id:"hash"}) //指定表分片基于hash规则 sh.shardCollection("TestHash.testtable",{id:"hashed"}) //造数据 use TestHash for(i=0;i<30000;i++){db.testtable.insert({"id":i,"name":"kk","date":new Date()})}
查看分片状态:
查看两节点数据分布:
Balance 操作
介绍
mongos 的 Balancer(平衡器) 是 MongoDB 分片集群的核心组件,负责监测所有分片节点上的数据块(chunk)分布,并自动执行数据块迁移以实现负载均衡。
Balancer 的工作时机
自动运行:当系统负载较低时触发迁移。 节点删除时:移除分片节点后立即触发迁移。 时间窗口限制:可配置为仅在指定时间段内运行。
何时需要关闭 / 开启 Balancer?
备份期间:避免因数据迁移导致备份不一致。 维护窗口:与高负载业务时段错开。
示例:手动控制 Balancer
// 停止 Balancer mongos.sh.stopBalancer() // 启动 Balancer mongos.sh.startBalancer()
自定义自动平衡的时间段
连接到 mongos 实例: mongo --port 27017 admin 启用 Balancer 并验证状态: use config sh.setBalancerState(true) // 启用 sh.getBalancerState() // 检查状态(返回 true 表示已启用) 设置时间窗口(例如 3:00 至 5:00): db.settings.update( { _id: "balancer" }, { $set: { activeWindow: { start: "3:00", stop: "5:00" } } }, { upsert: true } )
验证配置:
sh.getBalancerWindow() // 查看时间窗口 sh.status() // 检查集群状态 db.settings.find() // 查询详细配置
集合级别的 Balance 管理
关闭 / 开启指定集合的 Balance
// 关闭集合 test.vast 的 Balance sh.disableBalancing("XXXXX") // 开启集合 test.vast 的 Balance sh.enableBalancing("XXXXX")
检查集合的 Balance 状态
// 查询集合的 noBalance 字段(true 表示已关闭) db.getSiblingDB("config").collections.findOne({ _id: "XXXXX" }).noBalance
Mongos 节点配置 Keepalived 实现高可用
Mongos 本身是无状态的,并没有故障转移功能,所以在特定场景中需要配置 Keepalived 实现 Mongos 的高可用
装置 keepalived 后编辑两节点配置文件
Mongos1: global_defs { router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.80.50/24 192.168.80.51/24 192.168.80.52/24 } } Mongos2: global_defs { router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 60 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.80.50/24 192.168.80.51/24 192.168.80.52/24 } }
查看 VIP 状态,并尝试 Mongos 故障切换:
例如此时 Mongos1 故障,VIP 切换到 Mongos2 所在节点: