组件 | 介绍 |
---|---|
mongos | 前端路由,分发请求,让整个集群看上去像单一数据库 |
config servers | 记录全局配置信息,3.4开始必须部署两个为副本集 |
shard server | 完成数据提取和查询,实际的数据块 |
名称 | 角色 | IP | 端口 | 副本集名称 |
---|---|---|---|---|
mongos | mongos | 172.20.0.15 | 27017 | |
config_server_0 | configsvr | 172.20.0.13 | 27019 | rs_config_server |
config_server_1 | configsvr | 172.20.0.14 | 27019 | rs_config_server |
shard_server_0 | shardsvr | 172.20.0.11 | 27018/30001 | shard_server0/shard_server1 |
shard_server_1 | shardsvr | 172.20.0.12 | 27018/30002 | shard_server0/shard_server1 |
shard_server_2 | shardsvr(仲裁) | 172.20.0.16 | 27018/30003 |
目录结构如下:
docker_mongo_swarm
├── data
└── docker-compose.yml
docker-compose.yml这里使用mongo:4.0.19基础镜像,准备了3个副本集,2个配置服务器,1个mongos路由。由于不知道怎么在yml里配多个mongo守护进程,所以待会在镜像里面启动多1个mongo。
docker-compose.yml文件git地址
~ docker-compose up -d #启动yml后台挂起
~ docker stats -a #查看容器状态
先进入任意1台配置服务器里面关联2台配置服务器,不然mongos没法用。
~ docker exec -it rs_config_server_1 /bin/bash
root@acca86ab949e:/# mongo 127.0.0.1:27019
> rs.initiate({
_id: "rs_config_server",
configsvr: true,
members: [
{ _id : 0, host : "172.20.0.13:27019" },
{ _id : 1, host : "172.20.0.14:27019" }
]
});
依次进入,主动挂起shard_server1的分片集群。
#shard_server_0
~ docker exec -it shard_server_0 /bin/bash
root@acca86ab949e:/# mongod --port=30001 --dbpath=/data/set1 --shardsvr --replSet=shard_server1 --bind_ip_all >/dev/null 2>&1 &
#shard_server_1
~ docker exec -it shard_server_1 /bin/bash
root@acca86ab949e:/# mongod --port=30002 --dbpath=/data/set1 --shardsvr --replSet=shard_server1 --bind_ip_all >/dev/null 2>&1 &
#shard_server_2
~ docker exec -it shard_server_2 /bin/bash
root@acca86ab949e:/# mongod --port=30003 --dbpath=/data/set1 --shardsvr --replSet=shard_server1 --bind_ip_all >/dev/null 2>&1 &
#在任意容器可以看看有没有启动2个mongo,第1个是docker,第2个是刚刚启动的。
root@acca86ab949e:/# ps aux
在任意shard容器都可以运行,我这里再起了1个终端在shard_server_0容器里面操作。
~ docker exec -it shard_server_0 /bin/bash
root@acca86ab949e:/# mongo 127.0.0.1:27018
> rs.initiate({
_id: "shard_server0",
members: [
{ _id : 0, host : "172.20.0.11:27018"},
{ _id : 1, host : "172.20.0.12:27018" },
{ _id : 2, host : "172.20.0.16:27018",arbiterOnly:true}
]
});
~ docker exec -it shard_server_0 /bin/bash
root@acca86ab949e:/# mongo 127.0.0.1:30001
> rs.initiate({
_id: "shard_server1",
members: [
{ _id : 0, host : "172.20.0.11:30001"},
{ _id : 1, host : "172.20.0.12:30002" },
{ _id : 2, host : "172.20.0.16:27018",arbiterOnly:true}
]
});
#关联完可以看下副本集状态,有1个PRIMARY,1个SECONDARY,1个ARBITER。
shard_server0:PRIMARY> rs.status()
shard_server1:PRIMARY> rs.status()
#如果是SECONDARY节点,用slaveOk命令允许查询操作。
shard_server0:SECONDARY> rs.slaveOk()
shard_server0:SECONDARY> rs.status()
关联前面配置的副本集和分片。
docker exec -it mongos /bin/bash
root@acca86ab949e:/# mongo 127.0.0.1:27017
sh.addShard("shard_server0/172.20.0.11:27018,172.20.0.12:27018")
sh.addShard("shard_server1/172.20.0.11:30001,172.20.0.12:30002")
配完结果如下:
在mongos主路由里,对age按hash作为片键,输入2W个数据,落到各个分片。
mongos> sh.enableSharding('testdb')
mongos> use testdb
mongos> sh.shardCollection("testdb.test_shard",{"age": "hashed"})
mongos> for (i = 1; i <= 20000; i++) db.test_shard.insert({age:(i%100), name:"user"+i, create_at:new Date()})
mongos> db.test_shard.find().count()
20000
mongos> db.stats()
可以看到shard_server1落了11400条记录,shard_server0落下了8600条记录。
这里主动让作为 PRIMARY 的 shard_server0 容器断掉
~ docker stop shard_server_0
mongos> db.test_shard.find().count()
20000
停掉shard_server_0后发现数据并没有丢失,因为shard_server_1保存了se0和se1完整的副本集,所以数据会同步。
~ docker exec -it shard_server_1 /bin/bash
root@acca86ab949e:/# mongo 127.0.0.1:27018
shard_server0:PRIMARY> rs.status()
进入shard_server_1的se0的副本集查看,看到172.20.11:27018的健康状态是no healthy,而172.20.12:27018已被仲裁节点自动选为 PRIMARY(如果没有仲裁节点,SECONDARY 不会自动变成 PRIMARY )。
在当前节点查看数据,发现只有8600,别紧张,这只是set0的数据,启动另一个终端,再看看set1的数据11400。
shard_server1:PRIMARY> use testdb
shard_server0:PRIMARY> db.test_shard.find().count()
8600
shard_server1:PRIMARY> use testdb
shard_server1:PRIMARY> db.test_shard.find().count()
11400
启动shard_server_0容器,再看看,发现172.20.0.11:27018已经变成了SECONDARY节点。
~ docker start shard_server_0
#数据库 命令
db.serverStatus().connections; //连接数查看
show collections //查看表信息
db.test_shard.find().count() //查看table1数据长度
db.test_shard.remove({}) //删除数据表
db.stats() //查看所有的分片服务器状态
db.adminCommand( { listShards: 1 } ) //分片列表
db.test_shard.find({ age: 36 }).explain() //精确查询
db.test_shard.find({ age: { $gte : 36 ,$lt : 73 } }).explain() //范围查询
#分片 操作命令
sh.enableSharding('testdb') //开启数据库testdb分片
sh.shardCollection('testdb.users',{uid:1}) //按testdb.users的uid字段分片
sh.shardCollection("testdb.test_shard",{"age": 1}) //按ranged分片
sh.shardCollection("testdb.test_shard2",{"age": "hashed"}) //按hash分片
sh.status() //查看分片节点
sh.addShard() //向集群中添加一个 shard
sh.getBalancerState() //查看平衡器
sh.disableBalancing() //禁用平衡器
sh.enableBalancing() //启用平衡器
db.runCommand( { removeShard: "mongodb0" } ) //删除分片mongodb0,迁移数据查看命令
db.runCommand( { movePrimary: "test", to: "mongodb1" }) //将数据库test未分片mongodb0的数据,迁移到mongodb1主分片。
db.adminCommand("flushRouterConfig") //处理分片后,刷新路由数据。
use config
db.databases.find() //查看所有数据库使用分片
db.settings.save({_id:"chunksize",value:1}) //将 chunk 的大小调整为 1MB
db.serverStatus().sharding
#副本集 操作命令
rs.status() //查看成员的运行状态等信息
rs.config() //查看配置信息
rs.slaveOk() //允许在SECONDARY节点上进行查询操作,默认从节点不具有查询功能
rs.isMaster() //查询该节点是否是主节点
rs.add({}) //添加新的节点到该副本集中
rs.remove() //从副本集中删除节点
rs.stepDown //降级节点
db.printSlaveReplicationInfo() //查看同步情况
rs.addArb("172.20.0.16:27038") //添加仲裁节点
#强制加入仲裁节点:
config=rs.conf()
config.members=[config.members[0],config.members[1],{_id:5,host:"127.0.0.1:27023",priority:5,arbiterOnly:"true"}]
rs.reconfig(config,{force:true})
#强制主节点:
cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 0.5
cfg.members[2].priority = 1
rs.reconfig(cfg)
#备份/恢复
mongodump -h 127.0.0.1:27017 -d test -o /data/backup/
mongorestore -h 127.0.0.1:27017 -d test --dir /data/db/test
参考:
https://www.jianshu.com/p/7be177d669be
https://www.cnblogs.com/hukey/p/5774397.html
https://www.ibm.com/developerworks/cn/opensource/os-mongodb-sharded-cluster/index.html