MongoDB 分片集群 + Keepliaved 高可用架构分析与实战部署

发布于:2025-04-15 ⋅ 阅读:(27) ⋅ 点赞:(0)

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。

  • 操作流程

    1. 数据写入时,根据分片键值分配到对应的 Chunk。

    2. Chunk 达到阈值后触发拆分,生成新 Chunk。

    3. 平衡器监控各分片的 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 所在节点: