搭建Mongo集群
一主一从一仲裁模式。mongodump导出的是bson格式,是二进制形式。此工具对于恢复整个实例、单个数据库、指定集合都十分有用。他们可以用于备份实时运行的数据库(无需锁住或者关闭数据库)
安装
下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.2.8.tgz
解压
tar -zxf mongodb-linux-x86_64-rhel80-4.2.8.tgz
cd mongodb-linux-x86_64-rhel80-4.2.8/
配置主节点
vim mongodb.conf
conf内容如下:
port=27018
dbpath=/usr/local/mongo/db/master
logpath=/usr/local/mongo/logs/master/mongodb.log
pidfilepath=/usr/local/mongo/pid/master/mdb.pid
logappend=true
fork=true
maxConns=100
#noauth=false
journal=true
storageEngine=wiredTiger
bind_ip=0.0.0.0
replSet=rs0
创建软连接
ln -s /usr/local/mongo/master/bin/mongod /usr/bin/mongodmaster
ln -s /usr/local/mongo/master/bin/mongo /usr/bin/mongomaster
配置从节点
cd /usr/local/mongo/
mkdir slave
复制master的配置文件
cp -r master/* slave
修改
cd slave
vim mongodb.conf
内容如下:
port=27019
dbpath=/usr/local/mongo/db/slave
logpath=/usr/local/mongo/logs/slave/mongodb.log
pidfilepath=/usr/local/mongo/pid/slave/mdb.pid
logappend=true
fork=true
maxConns=100
#noauth=false
journal=true
storageEngine=wiredTiger
bind_ip=0.0.0.0
replSet=rsss0
创建软连接
ln -s /usr/local/mongo/slave/bin/mongod /usr/bin/mongodslave
ln -s /usr/local/mongo/slave/bin/mongo /usr/bin/mongoslave
配置仲裁节点
cd /usr/local/mongo/
mkdir arbiter
复制master的配置文件
cp -r master/* arbiter
修改
cd arbiter
vim mongodb.conf
内容如下:
port=27017
dbpath=/usr/local/mongo/db/arbiter
logpath=/usr/local/mongo/logs/arbiter/mongodb.log
pidfilepath=/usr/local/mongo/pid/arbiter/mdb.pid
logappend=true
fork=true
maxConns=100
#noauth=false
journal=true
storageEngine=wiredTiger
bind_ip=0.0.0.0
replSet=rs0
创建软连接
ln -s /usr/local/mongo/arbiter/bin/mongod /usr/bin/mongodslave
ln -s /usr/local/mongo/arbiter/bin/mongo /usr/bin/mongoslave
启动服务
master
cd /usr/local/mongo/master/
mongodmaster --config mongodb.conf
slave
cd /usr/local/mongo/slave/
mongodslave --config mongodb.conf
arbiter
cd /usr/local/mongo/arbiter/
mongodarbiter --config mongodb.conf
配置关系
mongomaster -port 27018 -host 127.0.0.1
rs.initiate({ _id:"rsss0", members:[ {_id:0,host:"127.0.0.1:27018",priority:2},{_id:1,host:"127.0.0.1:27019",priority:1},{_id:2,host:"127.0.0.1:27017",arbiterOnly:true} ] });
查看复制集状态:rs.status();
令查看当前节点是否是主节点:rs.isMaster();
在从节点上做读操作:rs.slaveOk(true)
rs.initiate({ _id:"rsss0", members:[ {_id:0,host:"127.0.0.1:27017",priority:2} ] });
备份数据
写入数据
mongomaster -port 27018 -host 127.0.0.1
use test
db.test.insert({"id":3})
exit
cd /usr/local/mongo/master/bin
mongodump -h 127.0.0.1:27018 -d test -o /usr/local/mongo/dbdump
将原有的数据文件删除后。
mongomaster -port 27018 -host 127.0.0.1
db.test.remove({'id':1})
exit
使用
mongorestore -h 127.0.0.1:27018 -d test /usr/local/mongo/dbdump/test/test.bson
发现数据成功恢复
配置身份验证
mongomaster 127.0.0.1:27018
use admin
db.createUser(
{
user: "user",
pwd: "pwd",
roles: [ { role: "root", db: "admin"} ]
}
)
exit
cd /usr/local/mongo
mkdir keyfile
cd keyfile
openssl rand -base64 741 > mongo.key
ls#降低文件的读写权限,如果不降低可能会报错,提示这个文件too open.
#错误提示如下:
permissions on /data/mongomaster/mongodb-linux-x86_64-rhel70-4.2.9/bin/keyfile/mongo.key are too open
cd /usr/local/mongo/master
vim mongo.conf
keyFile=/usr/local/mongo/keyfile/mongo.key
clusterAuthMode=keyFile
auth=TRUE
同理修改slave和arbiter的配置文件
最终的配置文件如下
port=27017
dbpath=/usr/local/mongo/db/arbiter
logpath=/usr/local/mongo/logs/arbiter/mongodb.log
pidfilepath=/usr/local/mongo/pid/arbiter/mdb.pid
keyFile=/usr/local/mongo/keyfile/mongo.key
logappend=true
fork=true
maxConns=100
#noauth=false
clusterAuthMode=keyFile
auth=TRUE
journal=true
storageEngine=wiredTiger
bind_ip=0.0.0.0
replSet=rsss0
重新开启服务后,就必须通过身份验证。
配置完创建了新的库,发现登陆不进去,即使登陆进去也没有权限操作,那么就从admin登录,然后切换到新建的库,创建新用户
use admin
db.auth("","")
use test
db.createUser(
... {
... user: "user",
... pwd: "pwd",
... roles: [ { role: "readWrite", db: "ziot" } ]
... }
... )
##
mongodump备份
编写shell脚本
vim dump.sh
#!/bin/bash
# mongodump命令路径
DUMP=/usr/local/mongo/mongodb-linux-x86_64-rhel80-4.2.8/bin/mongodump
# tar备份包临时备份目录,这个tar包最好定时传到本地存储做备份
OUT_DIR=/usr/local/mongo/dump
# 完整备份目录路径
TAR_DIR=/usr/local/mongo/dumps
# 获取当前系统时间
DATE=$(date +%Y%m%d%H%M)
# 数据库账号
DB_USER=user
# 数据库密码
DB_PASS=pwd
# DAYS=15代表删除15天前的备份,即只保留近15天的备份
DAYS=15
# 最终保存的数据库备份文件
TAR_BAK="mongodb_bak_$DATE.tar.gz"
cd $OUT_DIR
# rm -rf $OUT_DIR/*
if [ ! -d testgrid ];then
mkdir -p $OUT_DIR/$DATE
else
echo dir exist
fi
# 备份全部数据库
$DUMP -h 192.168.1.18:27017 -u $DB_USER -p $DB_PASS -o $OUT_DIR/$DATE
# 压缩为.tar.gz格式
tar -zcvf $TAR_DIR/$TAR_BAK $OUT_DIR/$DATE
# 删除15天前的备份文件
#find $TAR_DIR/ -mtime +$DAYS - delete
# 删除tar备份包10天前的备份文件
#find $OUT_DIR/ -mtime + 10 -name "*.tar.gz" -exec rm -rf {} \;
exit
使用crontab 定时运行
crontab -e
#每天凌晨3点开始执行MongoDB完整备份脚本
0 3 * * * sh /data/script/mongodbfullbackup.sh >/dev/null 2>&1
mongodump常用的命令
mongodump的参数
参数 | 参数说明 |
---|---|
-h | 指明数据库宿主机的IP |
-u | 指明数据库的用户名 |
-p | 指明数据库的密码 |
-d | 指明数据库的名字 |
-c | 指明collection的名字 |
-o | 指明到要导出的文件名 |
-q | 指明导出数据的过滤条件 |
--authenticationDatabase | 验证数据的名称 |
--gzip | 备份时压缩 |
--oplog | use oplog for taking a point-in-time snapshot |
mongodump参数实践
全库备份
mongodump -h IP地址:27017 -uroot -proot --authenticationDatabase admin -o /home/mongod/backup/full
备份test库
mongodump -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test -o /home/mongod/backup/
备份test库下的vast集合
mongodump -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test -c vast -o /home/mongod/backup/
压缩备份库
mongodump -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test -o /home/mongod/backup/ --gzip
压缩备份单表
mongodump -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test -c vast -o /home/mongod/backup/ --gzip
mongorestore恢复实践
mongorestore与mongoimport参数类似
参数 | 参数说明 |
---|---|
-h | 指明数据库宿主机的IP |
-u | 指明数据库的用户名 |
-p | 指明数据库的密码 |
-d | 指明数据库的名字 |
-c | 指明collection的名字 |
-o | 指明到要导出的文件名 |
-q | 指明导出数据的过滤条件 |
--authenticationDatabase | 验证数据的名称 |
--gzip | 备份时压缩 |
--oplog | use oplog for taking a point-in-time snapshot |
--drop | 恢复的时候把之前的集合drop掉 |
全库备份中恢复单库(基于之前的全库备份)
mongorestore -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test --drop /home/mongod/backup/full/test/
恢复test库
mongorestore -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test /home/mongod/backup/test/
恢复test库下的vast集合
mongorestore -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test -c vast /home/mongod/backup/test/vast.bson
--drop参数实践恢复
# 恢复单库
mongorestore -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test --drop /home/mongod/backup/test/
# 恢复单表
mongorestore -h IP地址:27017 -uroot -proot --authenticationDatabase admin -d test -c vast --drop /home/mongod/backup/test/vast.bson
mongo备份之间的对比
- mongoexport/mongoimport导入/导出的是JSON格式,而mongodump/mongorestore导入/导出的是BSON格式。
- JSON可读性强但体积较大,BSON则是二进制文件,体积小但对人类几乎没有可读性。
- 在一些mongodb版本之间,BSON格式可能会随版本不同而有所不同,所以不同版本之间用mongodump/mongorestore可能不会成功,具体要看版本之间的兼容性。当无法使用BSON进行跨版本的数据迁移的时候,使用JSON格式即mongoexport/mongoimport是一个可选项。跨版本的mongodump/mongorestore并不推荐,实在要做请先检查文档看两个版本是否兼容(大部分时候是的)。
- JSON虽然具有较好的跨版本通用性,但其只保留了数据部分,不保留索引,账户等其他基础信息。使用时应该注意。
python以副本集的方式连接mongo
def client(self, db):
# motor
self.motor_uri = 'mongodb://{account}{hostport0},{hostport1},{hostport2}/{database}?replicaSet=rs0'.format(
account='{username}:{password}@'.format(
username=self.MONGODB['MONGO_USERNAME'],
password=self.MONGODB['MONGO_PASSWORD'])
if self.MONGODB['MONGO_USERNAME'] else '',
hostport0=self.MONGODB['MONGOHOST_PORT'][0] if self.MONGODB['MONGOHOST_PORT'] else 'localhost:27017',
hostport1=self.MONGODB['MONGOHOST_PORT'][1] if self.MONGODB['MONGOHOST_PORT'] else 'localhost:27016',
hostport2=self.MONGODB['MONGOHOST_PORT'][2] if self.MONGODB['MONGOHOST_PORT'] else 'localhost:27015',
# host=self.MONGODB['MONGO_HOST'] if self.MONGODB['MONGO_HOST'] else 'localhost',
# port=self.MONGODB['MONGO_PORT'] if self.MONGODB['MONGO_PORT'] else 27017,
database=db)
print(self.motor_uri)
return AsyncIOMotorClient(self.motor_uri, retryWrites=False, io_loop=self.loop, tz_aware=True,
tzinfo=pytz.timezone('Asia/Shanghai'))
副本集命令
MongoDB 删除,添加副本集,并修改副本集IP等信息
添加副本,在登录到主节点下输入
rs.add("ip:port");
删除副本
rs.remove("ip:port");
新增仲裁节点
rs.addArb("ip:port");
修改副本host:
shard1:PRIMARY> cfg = rs.conf()
{
"_id" : "shard1",
"version" : 5,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:2777",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5d9c7a7e76695600e03e231f")
}
}
shard1:PRIMARY> cfg.members[0].host = "IP地址:27017"
IP地址1:27017
shard1:PRIMARY> rs.reconfig(cfg)
{ "ok" : 1 }
shard1:PRIMARY> rs.status()
{
"set" : "shard1",
"date" : ISODate("2021-06-09T02:59:26.916Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "IP地址:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 54711,
"optime" : {
"ts" : Timestamp(1570589961, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2021-06-09T02:59:21Z"),
"electionTime" : Timestamp(1570536062, 2),
"electionDate" : ISODate("2021-06-09T12:01:02Z"),
"configVersion" : 6,
"self" : true
}
],
"ok" : 1
}
如果你的mongo是以副本集连接,然而主节点崩掉了,此时你的mongo还不是主节点,此时就会陷入死局,此处可强制将你的mongo节点转为主节点。将上述的rs.reconfig(cfg)
改为 rs.reconfig(cfg,{"force": true})
即可。