搭建Mongo集群以及基本操作

549 阅读7分钟

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

搭建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备份时压缩
--oploguse 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备份时压缩
--oploguse 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备份之间的对比

原文

  1. mongoexport/mongoimport导入/导出的是JSON格式,而mongodump/mongorestore导入/导出的是BSON格式。
  2. JSON可读性强但体积较大,BSON则是二进制文件,体积小但对人类几乎没有可读性。
  3. 在一些mongodb版本之间,BSON格式可能会随版本不同而有所不同,所以不同版本之间用mongodump/mongorestore可能不会成功,具体要看版本之间的兼容性。当无法使用BSON进行跨版本的数据迁移的时候,使用JSON格式即mongoexport/mongoimport是一个可选项。跨版本的mongodump/mongorestore并不推荐,实在要做请先检查文档看两个版本是否兼容(大部分时候是的)。
  4. 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}) 即可。