分片集群的扩容与缩容
分片集群的扩容与缩容
MongoDB分片集群通过水平扩展解决单机性能瓶颈,但业务量波动时需要动态调整集群规模。分片扩容涉及新分片加入和数据迁移,缩容则需安全移除节点并重新平衡数据分布。
扩容分片集群
添加配置服务器
配置服务器存储集群元数据,建议部署为副本集。扩容时需先扩展配置服务器副本集成员:
// 连接到配置服务器主节点
conf = db.getSiblingDB("admin").getMongo().getDB("admin")
conf.add({_id: 3, host: "cfg3.example.net:27019"})
// 验证副本集状态
conf.rs.status()
加入新分片副本集
- 部署新的副本集并初始化
mongod --shardsvr --replSet shardC --dbpath /data/shardC --port 27018
- 将副本集加入集群
sh.addShard("shardC/rs1.example.net:27018,rs2.example.net:27018")
触发数据均衡
新分片加入后需手动触发均衡器:
sh.startBalancer()
// 查看迁移任务
use config
db.chunks.find({jumbo: true}) // 检查大块数据
典型数据迁移日志示例:
{"t":"2023-05-17T03:22:15.234+0000","s":"I", "c":"SHARDING","id":22194,
"ctx":"Balancer","msg":"Migration succeeded","attr":{"from":"shardA","to":"shardC"}}
缩容分片集群
数据迁移出目标分片
- 首先确保分片不是主分片:
use admin
db.runCommand({removeShard: "shardB"})
// 返回结果包含需要迁移的chunk数量
- 监控迁移进度:
mongos> db.adminCommand({balancerStatus: 1})
{
"mode": "full",
"inBalancerRound": false,
"numBalancerRounds": 42,
"migrations": {
"shardB": {
"chunksInProgress": 3,
"bytesToMigrate": 157286400
}
}
}
移除空分片
当分片数据量降为0后完成移除:
// 再次执行移除命令
db.adminCommand({removeShard: "shardB"})
// 返回状态变为"completed"后即可下线节点
特殊场景处理
处理jumbo chunk
当存在超过默认64MB大小的chunk时:
- 手动拆分大chunk:
sh.splitAt("db.collection", {_id: ObjectId("5f4d7a9e6c3f2b1a")})
- 临时提高chunk大小阈值:
use config
db.settings.update(
{_id: "chunksize"},
{$set: {value: 128}},
{upsert: true}
)
维护窗口操作
在业务低峰期执行缩容时,可控制迁移速率:
db.adminCommand({
configureBalancer: {
mode: "limited",
maxParallelMigrations: 1,
migrationThrottlingMs: 5000
}
})
监控与验证
关键指标监控
- 迁移队列积压:
sh.getBalancerState()
- 网络流量:
db.serverStatus().network
- 磁盘空间变化:
db.stats(1024*1024)
// MB单位
数据一致性检查
迁移完成后执行:
// 比对不同分片文档数
db.collection.getShardDistribution()
// 使用hash校验
function compareShards() {
let mapFunc = function() { emit(this._id, hash(this)); };
let reduceFunc = function(k, v) { return v[0]; };
db.collection.mapReduce(mapFunc, reduceFunc, {out: "hashes"});
}
自动化运维实践
使用Ansible模板扩容
- name: Add new shard
mongodb_shard:
login_host: mongos1
login_user: admin
login_password: "{{vault_password}}"
replica_set: shardD
members:
- host: shardD1:27018
priority: 1
- host: shardD2:27018
priority: 0.5
shardsvr: yes
通过API动态调整
调用MongoDB管理API实现自动扩缩容:
async function resizeCluster(targetShard) {
const status = await sh.status();
if (status.shards.length > currentNeed) {
await sh.drainShard(targetShard);
await updateDNSRecord(targetShard, 'REMOVE');
} else {
await spinUpEC2Instance('shard-template');
await sh.addShard(newShardURI);
}
}
性能优化要点
- 预分裂集合:在插入数据前预先创建空chunk
for (let i=0; i<100; i++) {
sh.splitFind("db.orders", {order_id: i*10000})
}
- 标签感知分片:按机房位置打标签
sh.addTagRange("db.orders", {_id: MinKey}, {_id: MaxKey}, "EU-West")
sh.addShardTag("shardC", "EU-West")
- 索引同步策略:确保所有分片建立相同索引
db.getSiblingDB("db").getCollectionNames().forEach(coll => {
db.getSiblingDB("config").collections.findOne({_id: `db.${coll}`}).indexes.forEach(idx => {
db.getSiblingDB("db").getCollection(coll).createIndex(idx.key, idx.options)
})
})
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn