MongoDB 副本集 + 分片搭建
症状
目标:为 MongoDB 搭建具备自动故障转移的副本集,并将其扩展为分片集群以实现横向扩展。
1. 以相同的 replSet 名称启动 mongod 进程
以相同的 --replSet 名称和可访问的 --bind_ip 启动每个副本集成员。生产环境中建议使用 keyFile 或 TLS 进行内部认证。投票成员数应为奇数,以形成明确的多数派。
MongoDB
mongod --replSet rs0 --port 27017 --dbpath /data/n1 --bind_ip localhost,10.0.0.11
mongod --replSet rs0 --port 27017 --dbpath /data/n2 --bind_ip localhost,10.0.0.12
mongod --replSet rs0 --port 27017 --dbpath /data/n3 --bind_ip localhost,10.0.0.132. 初始化副本集
用 mongosh 连接到一个成员,调用 rs.initiate() 并定义所有成员。这会触发第一次选举并选出主节点。用 rs.status() 确认 PRIMARY/SECONDARY 角色。
MongoDB
rs.initiate({
_id: 'rs0',
members: [
{ _id: 0, host: '10.0.0.11:27017' },
{ _id: 1, host: '10.0.0.12:27017' },
{ _id: 2, host: '10.0.0.13:27017' }
]
})
rs.status()3. 添加成员、设置优先级,必要时添加 arbiter
之后用 rs.add() 添加成员。priority 决定哪个成员倾向于成为主节点(0 = 永远不会成为主节点)。arbiter 只投票、不保存数据;在数据节点数为偶数时用作决胜者,但出于数据安全考虑更推荐使用真正的成员。在基于 arbiter 的拓扑(尤其是 PSA)中,数据节点宕机时 majority write concern 无法满足,写入会等待;在 5.0+ 中,添加 arbiter 之前可能需要用 setDefaultRWConcern 显式设置集群级默认 write concern。
MongoDB
rs.add({ host: '10.0.0.14:27017', priority: 0.5 })
// Arbiter only if really needed (a data-bearing member is preferred):
rs.addArb('10.0.0.15:27017')
// change priority:
cfg = rs.conf(); cfg.members[0].priority = 2; rs.reconfig(cfg)4. 为分片搭建 config server 副本集
分片集群的元数据保存在 config server 副本集(--configsvr)中。它本身也以副本集方式初始化;为实现高可用,建议使用 3 个成员。
MongoDB
mongod --configsvr --replSet cfgrs --port 27019 --dbpath /data/cfg1 --bind_ip localhost,10.0.0.21
-- mongosh (on the config server):
rs.initiate({ _id: 'cfgrs', configsvr: true, members: [
{ _id: 0, host: '10.0.0.21:27019' },
{ _id: 1, host: '10.0.0.22:27019' },
{ _id: 2, host: '10.0.0.23:27019' } ] })5. 启动分片副本集和 mongos 路由器
每个分片都是一个以 --shardsvr 启动的独立副本集(数据持久性来自分片内部的复制)。mongos 路由器启动时指向 config server;应用连接到 mongos。
MongoDB
mongod --shardsvr --replSet shard1rs --port 27018 --dbpath /data/s1 --bind_ip localhost,10.0.0.31
# initiate shard1rs with rs.initiate, then mongos:
mongos --configdb cfgrs/10.0.0.21:27019,10.0.0.22:27019,10.0.0.23:27019 --port 27017 --bind_ip localhost,10.0.0.406. 添加分片并对集合分片
连接到 mongos,用 sh.addShard() 添加每个分片副本集。在数据库上启用分片,并用 sh.shardCollection() 按分片键分布集合。键的选择至关重要:应具有高基数且分布均匀。用 sh.status() 监控 chunk 分布。
MongoDB
sh.addShard('shard1rs/10.0.0.31:27018')
sh.addShard('shard2rs/10.0.0.32:27018')
sh.enableSharding('appdb')
sh.shardCollection('appdb.events', { customer_id: 'hashed' })
sh.status()