一、备份和恢复
MongoDB提供了备份和恢复的功能,分别是mongodump和mongorestore,可以使用如下命令:
1、备份:mongodump
// 语法
mongodump -h host -d dbname -o directory -u username -p pwd
// 示例,将本地test1数据库的数据备份到D:\Java\mongo_dump文件夹下面
mongodump -h 127.0.0.1 -d test1 -o D:\Java\mongo_dump -u testAdmin -p 123456
- 新建如下目录:D:\Java\mongo_dump
- 新打开一个cmd命令行窗口执行:
mongodump -h 127.0.0.1 -d test1 -o D:\Java\mongo_dump -u testAdmin -p 123456
注:因为启动mongodb的时候添加了–auth,所以这里需要用户名和密码,如果启动的时候没有添加–auth,这里就不需要-u和-p了,mongodump -h 127.0.0.1 -d test1 -o D:\Java\mongo_dump 就可以了
在查看刚刚新建的mongo_dump文件夹里面已经有备份的数据了
命令选项 | 释义 |
-h | -h后面的值是MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017 |
-d | -d的后面的值是需要备份的数据库实例名称,例如:test1 |
-c | 指定数据库里面的集合 |
-o | -o后面的值是备份的数据存放的位置,例如:D:\Java\mongo_dump,该目录需要提前建立,在备份完成后,系统自动在mongo_dump目录下建立一个test1目录,这个目录里面存放该数据库实例的备份数据 |
-u | -u的后面的值是登陆账号 |
-p | -u的后面的值是登陆账号的密码 |
–authenticationDatabase | 指定认证的数据库 |
–authenticationMechanism | 指定认证的算法 ,默认值 SCRAM-SHA-1 |
2、恢复:mongorestore
// 语法
mongorestore -h dbhost -d dbname dbdirectory
// 示例,将D:\Java\mongo_dump\test1文件夹下备份的数据恢复到本地的test1数据库
mongorestore -h 127.0.0.1 -d test1 D:\Java\mongo_dump\test1 -u testAdmin -p 123456 --authenticationDatabase test1
注:test1是要恢复的数据库名称,D:\Java\mongo_dump\test1是前面备份的test1的数据文件路径。
二、导出和导入
1、导出:mongoexport
// 语法
mongoexport -h dbhost -d dbname -c collectionname -o dir -u username -p pwd
// 示例,将本地test1数据库中的user集合的数据导出到D:\Java\mongo_dump\123.json
mongoexport -h 127.0.0.1 -d test1 -c user -o D:\Java\mongo_dump\123.json -u testAdmin -p 123456
导出后可以在文件夹下面看到导出的数据
2、导入:mongoimport
// 语法
mongoimport -h dbhost -d dbname -c collectionname -o dir -u username -p pwd
// 示例,将D:\Java\mongo_dump\123.json中备份的数据恢复到本地test1数据库中的user集合
mongoimport -h 127.0.0.1 -d test1 -c user D:\Java\mongo_dump\123.json -u testAdmin -p 123456
三、主从复制
MongoDB提供的主从复制的功能,基本的方式就是设置一个主节点,一个或多个从节点,每个从节点配置主节点的ip端口即可。
接下来启动一个主节点和一个从节点,(之前的cmd窗口全部关掉):
1、启动主节点
- 新建如下目录文件夹:D:\Java\mongo_master
- 新打开一个cmd,使用命令启动主节点:
mongod --dbpath D:\Java\mongo_master --port 27000 --master
(注:–port指定端口号,–master表示自己是主节点)
- 新打开一个cmd,连接上主节点:
mongo 127.0.0.1:27000
2、启动从节点
- 新建如下目录文件夹:D:\Java\mongo_slave
- 新打开一个cmd,使用命令启动主节点:
mongod --dbpath D:\Java\mongo_slave --port 27001 --slave --source 127.0.0.1:27000
(注:–port指定端口号,–slave表示自己是从节点,–source指定主节点的ip和端口)
- 新打开一个cmd,连接上从节点:
mongo 127.0.0.1:27001
3、测试主从复制数据
- 1、连接上主节点后新建一个test2数据库,然后创建一个user集合,向user集合中插入一条数据
- 2、连接上从节点后查看test2数据库的user集合中是否有数据,执行show dbs查询数据库,这个时候会报错。这是正常的,因为从库默认是不允许读写的,可以通过rs.secondaryOk();来解决。
可以看到主库的数据全部同步到了从库里面
四、副本集集群
MongoDB除了提供主从复制,还提供副本集,可以搭建高可用集群。MongoDB不推荐主从复制,推荐建立副本集(Replica Set)来保证主节点服务挂了,可以有其他服务顶上,程序正常运行,多个服务节点的数据都是一样的,后台自动同步。副本集比传统的Master-Slave主从复制有改进的地方就是它可以进行故障的自动转移,如果我们停掉主节点,那么剩余成员会再自动选举一个节点作为节点,副本集总有一个活跃点(primary)和一个或多个备份节点(secondary)。
1、创建如下三个路径文件夹,分别对应三个节点
- D:\Java\mongo_node1
- D:\Java\mongo_node2
- D:\Java\mongo_node3
2、分别启动三个节点
- 启动节点1:
mongod --dbpath D:\Java\mongo_node1 --logpath D:\Java\mongo_node1\logs.txt --logappend --port 10001 --replSet test
- 启动节点2:
mongod --dbpath D:\Java\mongo_node2 --logpath D:\Java\mongo_node2\logs.txt --logappend --port 10002 --replSet test
- 启动节点3:
mongod --dbpath D:\Java\mongo_node3 --logpath D:\Java\mongo_node3\logs.txt --logappend --port 10003 --replSet test
(注: --logpath指定日志路径,–port 指定端口号,–replSet 指定副本集名称)
3、初始化节点
初始化节点(只能初始化一次):随便登录一个节点,我登陆10001为例,
新开一个cmd窗口,执行如下命令:
// 连接上端口为10001的mongodb
mongo 127.0.0.1:10001
// 定义一个config配置节点
config={_id:"test",members:[{_id:1,host:"127.0.0.1:10001","priority":3},
{_id:2,host:"127.0.0.1:10002","priority":2},{_id:3,host:"127.0.0.1:10003","priority":1}]}
// 初始化配置
rs.initiate(config)
(注: test就是上面启动三个节点–replSet 后面的test名称,members:就是节点配置, host:节点的ip和端口,priority:权重,范围从1~1000,越大的数字,权重比越大,越容易成为主库)
查询当前10001节点的状态: rs.status()
test:OTHER> rs.status()
{
"set" : "test",// 集群名称
"date" : ISODate("2021-11-06T08:52:32.565Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1636188751, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1636188751, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1636188751, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1636188751, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:10001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",// 主节点
"uptime" : 259,
"optime" : {
"ts" : Timestamp(1636188751, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2021-11-06T08:52:31Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1636188748, 1),
"electionDate" : ISODate("2021-11-06T08:52:28Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "127.0.0.1:10002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",// 从节点
"uptime" : 14,
"optime" : {
"ts" : Timestamp(1636188737, 1),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(1636188737, 1),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("2021-11-06T08:52:17Z"),
"optimeDurableDate" : ISODate("2021-11-06T08:52:17Z"),
"lastHeartbeat" : ISODate("2021-11-06T08:52:30.697Z"),
"lastHeartbeatRecv" : ISODate("2021-11-06T08:52:32.190Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:10001",
"syncSourceHost" : "127.0.0.1:10001",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "127.0.0.1:10003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",// 从节点
"uptime" : 14,
"optime" : {
"ts" : Timestamp(1636188737, 1),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(1636188737, 1),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("2021-11-06T08:52:17Z"),
"optimeDurableDate" : ISODate("2021-11-06T08:52:17Z"),
"lastHeartbeat" : ISODate("2021-11-06T08:52:30.700Z"),
"lastHeartbeatRecv" : ISODate("2021-11-06T08:52:32.160Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:10001",
"syncSourceHost" : "127.0.0.1:10001",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1636188751, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1636188751, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
4、测试集群数据
- 在主库中新建test3数据,创建一个user集合,并向里面插入一条数据
- 连接上从库10002,mongo 127.0.0.1:10002,查看所有数据库show dbs,这个时候也会报错,和主从复制一样,从库默认不能读写,使用rs.secondaryOk()解决。然后查看主库保存的数据,可以看到主库保存的数据
- 测试主库挂掉,看看会不会重新选出主节点,直接把启动主节点10001端口的cmd窗口关掉
然后在从节点10002执行 rs.status()看看现在主节点是谁,可以看到10002已经成为了主节点
如果刚刚挂掉的10001节点又重新启动上线了,mongodb会自动加入到这个集群里面
5、集群添加节点和删除节点
- 1、添加节点
集群创建好之后我们也可以手动添加新的节点进去,创建mongo_node4文件夹:D:\Java\mongo_node4
启动节点4:
//
mongod --dbpath D:\Java\mongo_node4 --logpath D:\Java\mongo_node4\logs.txt --logappend --port 10004 --replSet test
在主节点执行命令:rs.add(“127.0.0.1:10004”),格式rs.add(“ip:端口”)
在查看是否已经将10004加入到集群
- 2、删除节点
在主节点执行rs.remove(“127.0.0.1:10004”)即可删除对应节点
五、MongoDB分片存储
- MongoDB提供了分片存储的机制,可以将数据分别存储到不同的机器上。MongoDB分片的基本逻辑是将集合切分成小块,这些计划分散到不同的分片机器上,每片值负责总数据中的一部分。而且应用程序不需要知道数据对应到那个片区,甚至都不需要知道数据被拆分了。
- 分片需要用到mongos命令,mongos是MongoDB shard的缩写,它是为应用层提供查询和写入请求并决定数据在MongoDB中的分片路由,说白了mongos相当于我们客户端和分片集群的一个桥梁,mongos知道数据和分片的关系。
- 官网解释:https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos.
对于分片集群,mongos实例提供客户端应用程序和分片集群之间的接口。mongos实例将查询和写入操作路由到碎片。从应用程序的角度来看,mongos实例的行为与任何其他MongoDB实例相同。
1、分片配置,创建如下文件夹,分别存放两个片区的数据和config配置(注:从MongoDB 3.2开始,要将分片集群的配置服务器部署为副本集,所以这里配置服务器和分片服务器都配置了副本集,也可以配置多个副本集):
- D:\Java\mongo_shard1
- D:\Java\mongo_shard2
- D:\Java\mongo_shard3
- D:\Java\mongo_shard4
- D:\Java\mongo_config1
- D:\Java\mongo_config2
2、启动config服务器副本集:
// 打开一个cmd命令行窗口启动config1服务
mongod --dbpath D:\Java\mongo_config1 --port 10001 --replSet myConfig --configsvr
// 打开一个cmd命令行窗口启动config2服务
mongod --dbpath D:\Java\mongo_config2 --port 10002 --replSet myConfig --configsvr
// 打开一个cmd命令行窗口连接上10001的服务,配置副本集
mongo 127.0.0.1:10001
// mongodb支持Js语法
var config = { _id:"myConfig", members:[{_id:0,host:"127.0.0.1:10001"}, {_id:1,host:"127.0.0.1:10002"} ] }
// 初始化副本集,没有配置权重的话,差不多10s左右当前服务会成为主节点
rs.initiate(config)
3、启动和配置分片服务器副本集myShard:
// 打开一个cmd命令行窗口启动shard1服务
mongod --dbpath D:\Java\mongo_shard1 --port 10003 --replSet myShard --shardsvr
// 打开一个cmd命令行窗口启动shard2服务
mongod --dbpath D:\Java\mongo_shard2 --port 10004 --replSet myShard --shardsvr
// 打开一个cmd命令行窗口连接上10003的服务,配置副本集
mongo 127.0.0.1:10003
var config = { _id:"myShard", members:[{_id:0,host:"127.0.0.1:10003"}, {_id:1,host:"127.0.0.1:10004"} ] }
// 初始化副本集
rs.initiate(config)
4、启动和配置分片服务器副本集myShard1:
// 打开一个cmd命令行窗口启动shard3服务
mongod --dbpath D:\Java\mongo_shard3 --port 10006 --replSet myShard1 --shardsvr
// 打开一个cmd命令行窗口启动shard4服务
mongod --dbpath D:\Java\mongo_shard4 --port 10007 --replSet myShard1 --shardsvr
// 打开一个cmd命令行窗口连接上10006的服务,配置副本集
mongo 127.0.0.1:10006
var config = { _id:"myShard1", members:[{_id:0,host:"127.0.0.1:10006"}, {_id:1,host:"127.0.0.1:10007"} ] }
// 初始化副本集
rs.initiate(config)
5、打开一个cmd命令行窗口,启动路由节点mongos:
// 启动mongos服务,myConfig是刚刚config副本集的名称,后面是ip和端口
mongos --port 10005 --configdb=myConfig/127.0.0.1:10001,127.0.0.1:10002
6、给mongos添加分片,并测试数据:
// 打开一个cmd命令行窗口连接上mongos服务
mongo 127.0.0.1:10005
// 配置shard节点,myShard是刚刚分片副本集的名称,后面是ip和端口
sh.addShard("myShard/127.0.0.1:10003,127.0.0.1:10004")
sh.addShard("myShard1/127.0.0.1:10006,127.0.0.1:10007")
// 启动sharding功能,enableSharding:对哪个库开启分片,shardCollection:对库中的哪个集合的哪个字段分片
sh.enableSharding("test")
sh.shardCollection("test.user",{"age":1})
查看10003的分片是否有数据: