1 MongoDB 介绍
1.4 什么时候使用MongoDB
1.数据量是有亿万级或者需要不断扩容 2.需要2000-3000以上的读写每秒 3.新应用,需求会变,数据模型无法确定 4.需要整合多个外部数据源 5.系统需要99.999%高可用 6.系统需要大量的地理位置查询 7.系统需要提供最小的latency 8.管理的主要数据对象<10 满足上面一条,可以考虑MongoDB;当有2个以上的时候:MongoDB是不二的选择!
1.6 版本
MongoDB有两个发布版本: 1.社区版:社区版是基于SSPL,一种和AGPL基本类似的开源协议 2.企业版:企业版是基于商业协议,需付费使用
1.7 MongoDB 常见部署架构
单机版, 复制集(主从+哨兵模式), 分片集群(类似redis的cluster集群,解决单点写入性能问题,至少10台机器)
1.9 MongoDB 参考资料
http://mongoing.com/
2 MongoDB 部署和访问
官方安装说明
#安装社区免费版 https://docs.mongodb.com/manual/installation/
2.2 基于rpm/deb包安装
#官方仓库路径 https://repo.mongodb.org/ #国内镜像(测试阿里源/清华源都有问题) https://mirrors.tuna.tsinghua.edu.cn/mongodb/ https://mirrors.aliyun.com/mongodb/ #路径一直点看到repodata为止,不用进去了
2.2.1 基于CentOS安装
[root@rocky ~]# vim /etc/yum.repos.d/mongodb.repo [mongodb-org-5.0] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/5.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc #更新缓存 [root@rocky ~]# yum makecache [root@rocky ~]# yum update #或者单独更新一个源 [root@rocky ~]# yum update --enablerepo= /etc/yum.repos.d/mongo.repo #看下能不能列出来 [root@rocky ~]# yum repolist repo id repo name appstream Rocky Linux 8 - AppStream baseos Rocky Linux 8 - BaseOS extras Rocky Linux 8 - Extras mongodb mongodb #安装最新版 [root@rocky ~]# yum install mongodb-org #安装指定版本 yum install -y mongodb-org-5.0.2 mongodb-org-database-5.0.2 mongodb-org-server-5.0.2 mongodb-org-shell-5.0.2 mongodb-org-mongos-5.0.2 mongodb-org-tools-5.0.2 [root@rocky ~]# systemctl status mongod.service #看到已设为开机启动 [root@rocky ~]# systemctl start mongod.service [root@rocky ~]# ss -ntl #端口为27017,后续要改配置成0.0.0.0
2.3 二进制包安装
#二进制包下载链接 https://www.mongodb.com/try/download/community #根据版本选择,tgz压缩包就行(但工具不全,工具要在工具栏单独下载) #官网下载mongodb-linux-x86_64-rhel80-5.0.4.tgz,拷贝到rocky中
2.3.1 安装前准备
关闭iptables防火墙 关闭 SELinux 安装相关包 #Red Hat/CentOS: yum install libcurl openssl #Ubuntu 18.04 LTS ("Bionic")/Debian 10 "Buster": sudo apt-get install libcurl4 openssl #Ubuntu 16.04 LTS ("Xenial")/Debian 9 "Stretch": sudo apt-get install libcurl3 openssl
关闭大页内存机制,其他系统关闭参照官方文档: (不管性能会受影响)
https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
内核参数ulimit
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/ Starting in MongoDB 4.4, a startup error is generated if the `ulimit` value for number of open files is under `64000`.
范例: 内核优化
cat >> /etc/rc.local <<EOF echo never > /sys/kernel/mm/transparent hugepage/enabled EOF chmod +x /etc/rc.local
2.3.2 二进制安装 MongoDB
#配置文件官方说明 https://docs.mongodb.com/manual/reference/configuration-options/ 范例: 二进制安装MongoDB #创建所需用户和组 useradd mongod #创建mongodb所需目录结构 mkdir -p /mongodb/{conf,data,log} #创建YAML格式的配置文件,早期3.0版本以前是普通文本格式 cat > /mongodb/conf/mongo.conf <<EOF #日志相关 systemLog: destination: file path: "/mongodb/log/mongodb.log" #日志位置 logAppend: true #追加日志 #数据存储有关 storage: dbPath: "/mongodb/data/" #数据路径的位置 #进程控制 processManagement: fork : true #后台守护进程 #网络配置有关 net: port: 27017 #端口号,默认不配置端口号,是27017 bindIp: 0.0.0.0 #监听地址自MongoDB 3.6版本后默认监听在localhost #安全验证有关配置 security: authorization: enabled #是否打开用户名密码验证,默认此项为关掉 EOF #查看设置好的配置文件 cat /mongodb/conf/mongo.conf systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" processManagement: fork: true net: port: 27017 bindIp: 0.0.0.0 chown -R mongod.mongod /mongodb/ tar xf mongodb-linux-x86_64-rhel70-v3.6-latest.tgz -C /usr/local ln -s /usr/local/mongodb-linux-x86_64-rhel70-3.6.23-8-gc2609ed/ /usr/local/mongodb #设置PATH变量 echo PATH=/usr/local/mongodb/bin/:'$PATH' > /etc/profile.d/mongodb.sh . /etc/profile.d/mongodb.sh #启动 su - mongod #切换账号 #执行下方命令或从配置文件里读 mongod --dbpath /mongodb/data --bind_ip_all --port 27017 --logpath /mongodb/log/mongod.log --logappend --fork #或者执行下方命令 mongod -f /mongodb/conf/mongo.conf #登录mongodb mongo #mongodb的关闭方式 mongod -f /mongodb/conf/mongo.conf --shutdown #mongodb使用systemd管理 cat > /lib/systemd/system/mongod.service <<EOF [Unit] Description=mongodb After=network.target remote-fs.target nss-lookup.target [Service] Type=forking User=mongod Group=mongod ExecStart=/usr/local/mongodb/bin/mongod --config /mongodb/conf/mongo.conf ExecReload=/bin/kill -s HUP \$MAINPID ExecStop=/usr/local/mongodb/bin/mongod --config /mongodb/conf/mongo.conf -- shutdown PrivateTmp=true # file size LimitFSIZE=infinity # cpu time LimitCPU=infinity # virtual memory size LimitAS=infinity # open files LimitNOFILE=64000 # processes/threads LimitNPROC=64000 # locked memory LimitMEMLOCK=infinity # total threads (user+kernel) TasksMax=infinity TasksAccounting=false # Recommended limits for mongod as specified in # https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now mongod
2.4 客户端连接
2.4.1 MongoDB 后台管理 Shell
2.4.1.1 mongo
[root@rocky ~]# mongo #查看库(兼容mysql命令) > show dbs > show databases #显示表 > show tables #显示当前所在数据库 > db #切库(库不用事先存在) > use magedu
2.4.1.2 mongosh
下一代客户端工具,需要安装下(yum安装是有的)
[root@rocky ~]# mongosh
二进制编译安装的话,在官网tools选择版本rpm包下载
#下载路径 https://www.mongodb.com/try/download/shell #从官网下载 mongodb-mongosh-1.1.2.el8.x86_64.rpm [root@rocky ~]# yum -y install mongodb-mongosh-1.1.2.el8.x86_64.rpm
2.4.2 使用 MongoDB Compass 连接
官网工具栏下compass选择版本下载(windows msi安装包,zip绿色免安装版)
3 MongoDB 管理
3.1 MongoDB 操作数据库
3.1.1 MongoDB 默认数据库介绍
MongoDB 默认存在的库 1.admin库:系统预留库,MongoDB系统管理库 2.local库:本地预留库,存储关键日志 3.config库:MongoDB配置信息库 4.test:登录时默认存在的测试库,生产中可以将之删除
3.1.3.1 库的操作
#use可以自动建库,如果库内没有数据,则不使用时会自动删除库 >use test #删除当前所在库 >db.dropDatabase() { "dropped" : "test", "ok" : 1 }
3.1.3.2 集合(表)的操作
#建表方法1:直接创建表 app>db.createCollection ('student') #建表方法2:当插入一个文档的时候,一个集合就会自动创建。 use magedu db.student.insert({id:1, name : "wang" ,age:20, gender: "m" }) #查看库中的集合列表 show tables show collections #查看集合的信息 db.student.stats() #删除集合 db.student.drop()
3.1.3.3 记录(文档)操作
#查询数据行数: db.student.count() #全表查询,默认每页显示20行 db.student.find() it #继续显示下面行 #只显示前3个 db.student.find().limit(3) #跳过前面10个显示后面的文档 db.student.find().skip(10) #按照条件查询 db.student.find({uid: 10}) #查询大于等于18并正序排序users集合 db.users.find({age: { $gte: 18 }}).sort({age: 1}) #查询users集合中的小于18的前5个文档中两个key:name和address db.users.find({age: {$lt: 18 }},{ name: 1, address: 1}).limit(5) #修改文档,如果没有加multi: true.默认只修改第一个符合条件的文档 db.student.update({uid:1},{$set:{age: 20}},{multi: true}) #删除指定的文档 db.student.remove({uid: 10}) #删除集合中所有记录,但表还存在 db.student.remove({}) #查看集合存储信息,包括集合中索引和数据压缩存储后的大小 db.student.totalSize()
3.2 用户及权限管理
3.2.1 关于用户验证库
1.创建用户时,use所在的库就是此用户的验证库 2.登录时,必须明确指定验证库才能登录 3.一个数据库可以成为多个用户的验证库,但一个用户只能使用一个验证库 4.对于管理员用户,必须在admin下创建,即管理员用的验证库是admin 5.普通用户的验证库一般是所管理的库 6.如果直接登录到数据库,不进行use,默认的验证库是test 7.从3.6版本开始,配置文件中不添加bindIp参数,默认不允许远程登录,只能本地管理员登录。
3.2.2 用户管理
#官方帮助 https://docs.mongodb.com/manual/tutorial/create-users/
3.2.2.1 开启用户认证
MongoDB数据库默认是无认证功能,可以直接登录做任务操作,为了安全需启用认证功能
#注意:启用认证后,仍然可以直接登录,但无权限做数据操作,但可以创建用户 #方法1:命令行方式通过“--auth”参数 mongod --auth --port 27017 --dbpath /data/db #方法2,修改配置文件中,加入以下配置 (这次采用二进制安装,用这种方法) cat >> /mongodb/conf/mongo.conf <<EOF security: authorization: enabled EOF systemctl restart mongod
3.2.2.2 用户管理说明
用户的创建,需要基于指定数据库,即用户是存放于特定数据库的,即验证库
3.2.2.3 范例
范例: 创建MongoDB的超级管理员
[root@rocky ~]# mongosh test> use admin #角色必须是root,只要对admin是root权限就是超级管理员 admin> db.createUser ( {user: "root",pwd: "123456",roles: [{role: "root", db: "admin"}]}) #登录验证(验证库admin) [root@rocky ~]# mongosh -u root -p 123456 admin --authenticationDatabase admin
范例: 创建普通用户
use test db.createUser( { user: "myTester", pwd: passwordPrompt(), //交互式指定密码 roles: [ { role: "readWrite", db: "test" }, { role: "read", db: "test2" } ] } ) #查看账号(只能看当前库里的账号) test> db.getUsers() #登录 mongosh -u myTester test -p 123456 mongo -u myTester test -p 123456 #查看所有用户 use admin admin> db.system.users.find()
范例: 创建应用用户
use magedu db.createUser ( { user: "app01", pwd: "123456", roles: [{role: "readWrite", db: "magedu"}] } ) db.createUser ( { user: "app02", pwd: "123456", roles: [{role: "readWrite", db: "magedu"}] } ) #验证用户(不需要登录就能验证) use magedu #选择用户对应的验证库,否则验证会失败 magedu> db.auth('app01','123456') { ok: 1 }
范例:删除用户
#以管理员root身份登录,use到被删除用户的验证库才能删除用户 use magedu db.dropUser ("app02")
4 MongoDB 复制集
4.2 复制集实现
4.2.2 准备配置文件
#3台机器上追加配置 [root@rocky ~]# vim /mongodb/conf/mongo.conf replication: replSetName: myrepl #指定复制集名称,所有复制集成员此名称要一致 [root@rocky ~]#systemctl restart mongod.service
4.2.3 配置复制集: 1主2从
#登录机器(只需要在3台中任一机器上完成) mongo --port 28017 admin #指定复制集的所有成员信息 >config = { _id: 'myrepl', members: [ {_id: 0, host: '10.0.0.8:28017'}, {_id: 1, host: '10.0.0.18:28017'} , {_id: 2, host: '10.0.0.28:28017'}] } #初始化并启动复制集 >rs.initiate(config) #搭建完成
测试
#从节点如果需要查看数据,登录从节点输入 myrepl:SECONDARY> rs.secondaryOk() #主节点输入数据,2个从节点自动同步数据 #从节点无法写入 #关闭主节点,一个从会变为主,原主节点变为从节点 #主节点可读可写
4.3.1 查看复制集状态
#查看整体复制集状态 rs.status() #查看当前是否是主节点 rs.isMaster() #查看复制集配置信息 rs.conf()
4.3.2 添加和删除节点
再搭一个节点 #在10.0.0.38上二进制安装mongodb [root@rocky ~]# vim /mongodb/conf/mongo.conf replication: replSetName: myrepl #指定复制集名称,所有复制集成员此名称要一致 [root@rocky ~]# systemctl restart mongod.service #此时集群并没有加入,需要在主节点执行添加命令 myrepl:PRIMARY> rs.add ("10.0.0.38: 27017") #可以查看,集群已加入新节点 rs.isMaster() #删节点 myrepl:PRIMARY> rs.remove ("10.0.0.38: 27017")
4.3.3 特殊从节点管理
范例: 实现特殊节点功能
#在主节点执行下面操作配置特殊节点并保存 config=rs.conf() #定义变量 config.members[3].hidden=true #设置hidden,3表示第4个成员,从0开始表示第1个,是rs.conf()显示的顺序,不是_id的值 config.members[3].priority=0 #优先级0表示不参选master,但可以投票,值越大优先级越高 config.members[3].arbiterOnly=true #也可将延时节点配置为arbiter节点 config.members[3].slaveDelay=120 #延时时长,以秒为单位,生产可延时3-6小时 config.members[3].votes=0 #持有票数为0 rs.reconfig(config) #加载配置 #取消以上配置 config=rs.conf() config.members[3].priority=1 config.members[3].hidden=false config.members[3].slaveDelay=0 config.members[3].votes=1 rs.reconfig(config) #配置成功后,通过以下命令查询配置后的属性 rs.conf();
5 MongoDB 分片集群
大型环境,大企业才会用
分片的缺点
1.分片额外消耗较多,约相当于单机性能的70%左右 2.管理复杂,尽量不要分片
5.1.1.2 分片设计思想
5.1.1.3 分片机制提供了如下三种优势
1.保证集群总是可读写 2.使集群易于扩展 3.对集群进行抽象,让集群“不可见” (开发连接方式和单机一样,感觉不到这是集群)
5.1.1.4 分片集群架构
访问通过mongos代理,再查询Config Servers索引数据库哪个分片上,然后访问具体分片服务器上
如上图,1个分片为主从架构(3台机器),2个分片6台。索引数据库要求复制集3台。mongos代理可1台,但为了安全2台
2台mongos代理可以通过keepalived实现高可用
如上所述,一个企业要搭建分片集群起步11台服务器
mongos 与 config通常消耗很少的资源,可以选择低规格虚拟机。资源的重点在于 shard 服务器
建议监控各项资源使用情况,无论哪一项达到60%以上,基于以下原因则开始考虑扩展
1.扩展需要新的资源,申请新资源需要时间,数据量大的话,可能会长达几天时间 2.扩展后数据需要均衡,均衡需要时间。应保证新数据入库速度慢于均衡速度 3.均衡需要资源,如果资源即将或已经耗尽,均衡也是会很低效的。
5.1.1.5 分片集群的相关概念
以下各种概念由小到大
片键shard key:文档中的一个字段(根据哪个片键来切表) 文档doc:包含shard key的一行数据 块Chunk :包含n个文档,默认64M 分片Shard:包含n个chunk,一个分片对应一个复制集 集群Cluster:包含n个分片
5.1.3 数据分片
5.1.3.2 以范围为基础的分片Sharded Cluster
5.1.3.3 基于哈希的分片
5.1.3.5 合理的分片
分片的基本标准: 1.关于数据:数据量不超过3TB,尽可能保持在2TB一个片 2.关于索引:常用索引必须容纳进内存 按照以上标准初步确定分片后,还需要考虑业务压力,随着压力增大,CPU、RAM、磁盘中的任何一项 出现瓶颈时,都可以通过添加更多分片来解决。 范例: 合理分片 A=所需存储总量/单服务器可挂载容量 如:8TB/2TB = 4 B=工作集大小/(单服务器物理内存容量*0.6) #0.6表示mongodb默认使用内存的60% 如:400GB / (256G*0.6) = 3 C=并发量总数/(单服务器并发量*0.7) #0.7表示单机变成分片有额外开销 如:30000/(9000*0.7)= 6 #结果: 分片数量=max(A,B,C)=6
5.4 实战案例: 多服务器实现MongoDB分片集群
5.4.1 环境规划
#准备十台主机,角色分配如下 #shard1 10.0.0.8:27017 10.0.0.18:27017 10.0.0.28:27017 #shard2 10.0.0.38:27017 10.0.0.48:27017 10.0.0.58:27017 #config server 10.0.0.68:27019 10.0.0.78:27019 10.0.0.88:27019 #mongos 10.0.0.98:27017
准备10台机器,都装上mongodb
5.4.2 实现过程
5.4.2.1 配置 shard1
#在shard1的三个节点上执行下面操作 [root@rocky8 ~]#cat > /mongodb/conf/mongo.conf <<EOF systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: port: 27017 bindIp: 0.0.0.0 replication : oplogSizeMB: 2048 #不定义默认值也行 replSetName: shard1 sharding: clusterRole: shardsvr #分片节点角色 EOF [root@rocky8 ~]#systemctl restart mongod.service #在10.0.0.8节点(3个中任一个)执行下面操作 [root@rocky8 ~]#mongo use admin config = { _id: 'shard1', members: [ {_id: 0, host: '10.0.0.8:27017'}, {_id: 1, host: '10.0.0.18:27017'}, {_id: 2, host: '10.0.0.28:27017'}] } rs.initiate (config)
5.4.2.2 配置 shard2
#在shard2的三个节点上执行下面操作 [root@rocky8 ~]#cat > /mongodb/conf/mongo.conf <<EOF systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: port: 27017 bindIp: 0.0.0.0 replication : oplogSizeMB: 2048 replSetName: shard2 sharding: clusterRole: shardsvr EOF [root@rocky8 ~]#systemctl restart mongod.service #在10.0.0.38节点(3个中任一个)执行下面操作 [root@rocky8 ~]#mongo use admin config = { _id: 'shard2', members: [ {_id: 0, host: '10.0.0.38:27017'}, {_id: 1, host: '10.0.0.48:27017'}, {_id: 2, host: '10.0.0.58:27017'}] } rs.initiate (config)
5.4.2.3 配置 config server
#在config的三个节点上执行下面操作 [root@rocky8 ~]#cat > /mongodb/conf/mongo.conf <<EOF systemLog: destination: file path: "/mongodb/log/mongodb.log" logAppend: true storage: dbPath: "/mongodb/data/" journal: enabled: true processManagement: fork: true net: bindIp: 0.0.0.0 replication: oplogSizeMB: 2048 replSetName: config sharding: clusterRole: configsvr #角色 EOF [root@rocky8 ~]#systemctl restart mongod.service #在10.0.0.68节点(3个中任一个)执行下面操作,注意:config server的端口默认是27019 [root@rocky8 ~]#mongo --port 27019 use admin config = { _id: 'config', members: [ {_id: 0, host: '10.0.0.68:27019' }, {_id: 1, host: '10.0.0.78:27019'} , {_id: 2, host: '10.0.0.88:27019'}] } rs.initiate (config)
5.4.2.4 配置 mongos
#不存放数据,所以data目录没用,可以删掉,留着也没事 [root@rocky8 ~]#rm -rf /mongodb/data #配置mongs节点 #在mongos节点10.0.0.98节点执行下面操作 [root@rocky8 ~]#cat > /mongodb/conf/mongo.conf <<EOF systemLog: destination: file path: "/mongodb/log/mongodb.log" sharding: configDB: config/10.0.0.68:27019,10.0.0.78:27019,10.0.0.88:27019 net: bindIp: 0.0.0.0 processManagement: fork: true EOF #先停止原mongod服务(使用mongs,如果启动mongod会端口冲突) [root@rocky8 ~]#systemctl stop mongod #启动mongs,注意不是mongod [root@rocky8 ~]#mongos -f /mongodb/conf/mongo.conf #登录 [root@rocky8 ~]#mongo admin #添加分片 mongos>sh.addShard("shard1/10.0.0.8:27017") mongos>sh.addShard("shard2/10.0.0.38:27017") #或者 mongos>sh.addShard("shard1/10.0.0.8:27017,10.0.0.18:27017,10.0.0.28:27017") mongos>sh.addShard("shard2/10.0.0.38:27017,10.0.0.48:27017,10.0.0.58:27017") #查看分片状态 mongos> sh.status()
5.4.2.5 配置分片规则
5.4.2.5.1 启用 Range 分片规则
#启用数据库的分片 mongos> sh.enableSharding("test") #创建索引(那个字段分片,就要对它创建索引) mongos>use test mongos>db.vast.createIndex({id: 1}) #针对id字段从小到大创建索引 #开启range分片规则(1表示范围分片) mongos>sh.shardCollection("test.vast", {id: 1}) #如果是对_id进行range分片,无需创建索引 mongos>sh.shardCollection("test.vast", {_id: 1}) #插入足够的大量数据才会分片(刚开始先写入一个分片,写完了它会自动把一般一到另一个分片上) mongos> use test mongos> for (i=0;i<1000000 ;i++){ db.vast.insert ( { "id" :i, "name" : "wang" , "age" : 20,"date" : new Date()})}
5.4.2.5.2 启用 Hash 分片规则
对另一个数据库采用另一种分片
#启用数据库的分片 mongos> sh.enableSharding("magedu") #指定在magedu库的vast表的id列上创建hash索引 mongos> use magedu mongos> db.vast.createIndex({id: "hashed"} ) #指定表分片基于hash规则 mongos> sh.shardCollection("magedu.vast", {id: 'hashed'}) #插入足够的大量数据才会分片 mongos> use magedu mongos> for (i=0;i<1000000 ;i++){ db.vast.insert ( { "id" :i, "name" : "wang" , "age" : 20,"date" : new Date()})}
5.4.2.6 验证分片集群
#分别在shard1和shard2上验证数据数量 use test db.vast.count() use magedu db.vast.count()
5.5 balance 操作
5.5.1 介绍
mongos的一个重要功能balancer,自动巡查所有shard节点上的chunk的情况,自动做chunk迁移,即实 现balance功能
balancer工作时机
1.自动运行,当检测系统不繁忙的时候做迁移 2.在做节点删除的时候,立即开始迁移工作 3.balancer可以指定只在预设定的时间窗口内运行
注:mongo没有事务概念,一定不能在备份的时候做平衡
比如:备份的时候进行balance会导致数据不一致,所以需要错开备份时间段
范例: 停止和开启balancer mongos> sh.stopBalancer() mongos> sh.startBalancer()
5.5.2 自定义自动平衡进行的时间段
#connect to mongos mongo --port 38017 admin use config #设置3:00到5:00进行balance db.settings.update({id: "balancer"},{$set: {activeWindow:{start: "3:00",stop : "5:00"}}}, true) #查看 db.settings.find() { "_id" : ObjectId("619a0c8d251b017dc44bfde2"), "id" : "balancer", "activeWindow" : { "start" : "3:00", "stop" : "5:00" } }
5.5.3 集合的balance管理
#关闭某个集合的balancer sh.disableBalancing("test.vast") #打开某个集合的balancer sh.enableBalancing ("test.vast") #确定某个集合的balance是开启或者关闭 db.getSiblingDB("config").collections.findOne({_id : "magedu.vast"}).noBalance false #表示balance打开的
6 MongoDB 备份恢复
6.1 备份恢复工具介绍
6.1.1 mongoexport/mongoimport说明
mongoexport/mongoimport可以实现逻辑备份,类似于mysqldump,可以导出json或csv格式文件
应用场景总结
异构平台迁移,比如:MySQL和MongoDB 同平台跨大版本的MongoDB数据导出导入: 比如mongodb 2 ----> mongodb 3
6.1.2 mongodump/mongorestore说明
物理备份,日常备份恢复时使用.导出的二进制文件
mongodump出来的数据不能表示某个时间点,只是某个时间段
6.1.3 mongoexport/mongoimport与 mongodump/mongorestore的对比
mongoexport/mongoimport导入/导出的是JSON格式,而mongodump/mongorestore导入/导出的是BSON格式。
6.1.4 备份工具安装
备份工具要自己下载
官网tools栏下选MongoDB Database Tools,选版本下载(选rpm包即可,tgz包解压后bin目录里直接可以使用) https://www.mongodb.com/try/download/database-tools #这里下载mongodb-database-tools-rhel80-x86_64-100.5.1.rpm [root@rocky ~]# yum -y install mongodb-database-tools-rhel80-x86_64-100.5.1.rpm
6.2 mongoexport/mongoimport
6.2.1 导出工具mongoexport
$mongoexport --help 参数说明: -h #指明数据库宿主机的IP -u #指明数据库的用户名 -p #指明数据库的密码 -d #指明数据库的名字 -c #指明collection的名字 -f #指明要导出那些列 -o #指明到要导出的文件名 -q #指明导出数据的过滤条件 --type=csv或 --csv #指定导出为csv格式,默认json格式 --authenticationDatabase <验证库> #指定验证库 范例: #创建备份文件夹 [root@rocky ~]# mkdir /backup/ #单表备份至json格式 mongoexport -d test -c vast -o /backup/vast.json #单表备份至csv格式,则需要使用--type=csv参数 mongoexport -d test -c vast --type=csv -f uid,name,age,date -o /backup/vast.json
6.2.2 导入工具mongoimport
mongoimport --help #参数说明: -h #指明数据库宿主机的IP -u #指明数据库的用户名 -p #指明数据库的密码 -d #指明数据库的名字 -c #指明collection的名字 -f #指明要导入那些列 --type=csv #指定导入csv格式文件,默认json格式 -j,--numInsertionworkers=<number> #同时插入的数量,默认为 --headerline #指明第一行是列名,不需要导入 范例: 数据恢复 #导入json格式表数据到vast2表中(表名可以和原来不一样) mongoimport -d test -c vast2 /backup/vast.json
6.2.3 异构平台迁移案例
6.2.3.1 将MySQL数据迁移至MongoDB
#将hellodb数据库下students表进行导出,导入到mongodb 1) mysql开启安全路径(否则不让导) [root@rocky ~]#vim /etc/my.cnf [mysqld] secure-file-priv=/tmp #导出路径 [root@rocky ~]#vim /lib/systemd/system/mysqld.service #PrivateTmp=true 将此行注释,否则会在/tmp/生成如下类似的临时的子目录(太麻烦) #/tmp/systemd-private-4e55a87321e741b7b98959db343effa5-mysqld.service-JsMtwj/tmp/students_info.csv [root@rocky ~]# systemctl daemon-reload [root@rocky ~]# systemctl restart mysqld 2)导出mysql的students表数据 #默认导出为Tab分隔的csv文件(不用这个) mysql> select * from hellodb.students into outfile '/tmp/students.csv'; #指定导出分隔符为,的csv文件(用这一种) mysql> select * from hellodb.students into outfile '/tmp/students.csv' fields terminated by ','; 3)查看mysql表的列名 4)在mongodb中导入备份 #方法1 将第3步查出的列名加入到前面导出的文件students.csv的第一行 [root@rocky ~]#mongoimport -uroot -p123456 --port 27017 --authenticationDatabase admin -d test -c students --type=csv --headerline --file /tmp/students.csv #方法2:使用选项 -f 指定列名 [root@rocky ~]#mongoimport -uroot -p123456 --port 27017 --authenticationDatabase admin -d test -c students --type=csv -f StuID,Name,Age,Gender,ClassID,TeacherID --file /tmp/students.csv
6.3 mongodump和mongorestore
6.3.1 mongodump
mongodump --help 参数说明: -h #指明数据库宿主机的IP -u #指明数据库的用户名 -p #指明数据库的密码 -d #指明数据库的名字 -c #指明collection的名字 -o #指明到要导出的文件名 -q #指明导出数据的过滤条件 -j, --numParallelCollections= #并行导出的数量,默认为4 --oplog #备份的同时备份oplog,此选项是replica set或者master/ slave模式专用
6.3.2 mongorestore
mongorestore --help -h #指明数据库宿主机的IP -u #指明数据库的用户名 -p #指明数据库的密码 -d #指明数据库的名字 -c #指明collection的名字 -o #指明到要导出的文件名 -q #指明导出数据的过滤条件 --authenticationDatabase #验证数据的名称 --gzip #备份时压缩 --oplogReplay #恢复完数据文件后再重放oplog。默认重放dump/oplog.bson --oplogFile=<filename> #指定需要重放的oplog文件位置 --oplogLimit=<seconds>[:ordinal] #重放oplog 时截止到指定时间点 --drop #恢复的时候把之前的集合drop掉
6.3.3 备份和恢复范例
范例:mongodump
#建全备文件夹 [root@rocky ~]#mkdir /backup/full #完全备份 [root@rocky ~]#mongodump -o /backup/full #只备份test数据库 mkdir -p /backup/test_backup [root@rocky ~]#mongodump -d test -o /backup/test_backup #备份magedu库下的vast集合 mkdir -p /backup/vast mongodump -d magedu -c vast -o /backup/vast #完全备份并压缩备份 mkdir -p /backup/full_gzip mongodump -o /backup/full_gzip --gzip
范例: mongorestore
#恢复完全备份 [root@rocky ~]#mongorestore /backup/full #如果有数据需要drop先删再还原 [root@rocky ~]#mongorestore --drop /backup/full #恢复一个库(如果已有test库无法还原,要加--drop删掉再还原) [root@rocky ~]#mongorestore -d test /backup/full/test/ [root@rocky ~]#mongorestore -d test --drop /backup/full/test/
6.3.4 利用 oplog 恢复数据
备份是一个时间段的,备份当中发生的操作无法确定是否备份进去了,可以通过执行这段时间的oplog进行保证
范例: 利用oplog幂等性恢复数据的一致
#注意:此操作不要在分片集群中执行(分片企业版才支持) #单机默认没有oplog,需要实现复制集才能开启oplog #插入大量数据,同时执行后面的备份操作 myrepl:PRIMARY> use test myrepl:PRIMARY> for (i=1;i<1000000 ;i++){ db.magedu.insert ( { "id" :i, "name" : "wang" , "age" : 20,"date" : new Date()})} #oplog只支持完全备份 [root@ubuntu1804 ~]#mkdir /backup/ #使用--oplog选项可以备份同时也备份oplog实现热备份,会记录备份过程中的数据变化。并以oplog.bson保存下来 [root@ubuntu1804 ~]#mongodump --oplog -o /backup/ [root@ubuntu1804 ~]#ls /backup/ #oplog.bson放的是变化中的数据 admin config oplog.bson test #查看所有操作的oplog [root@ubuntu1804 ~]#mongo myrepl:PRIMARY>use local myrepl:PRIMARY>db.oplog.rs.find().pretty() #查看创建操作的oplog,op的i表示insert,u表示update,d表示delete,c表示ddl,n表示note myrepl:PRIMARY>db.oplog.rs.find({op: "c"}).pretty() #备份完成后删除表magedu [root@ubuntu1804 ~]#mongo myrepl:PRIMARY>use test myrepl:PRIMARY>db.magedu.drop() #不使用oplog恢复,查看数据数量 [root@ubuntu1804 ~]#mongorestore --drop /backup [root@ubuntu1804 ~]#mongo >my_repl:PRIMARY> db.magedu.count() #使用oplog恢复,查看数据数量,和上面比较 (还原更多的数据,备份期间数据的变化也还原了) [root@ubuntu1804 ~]#mongorestore --drop --oplogReplay /backup [root@ubuntu1804 ~]#mongo >myrepl:PRIMARY> db.magedu.count()
范例: 利用oplog恢复误删除的表
故障说明: 每天3点全备,oplog恢复窗口为48小时 上午10点test库的vast业务表被误删除。 恢复过程: 1、停应用 2、找测试库 3、恢复昨天晚上全备 4、截取全备之后到test.vast被误删除时间点的oplog 5、恢复到测试库 6、将误删除表导出,恢复到生产库
故障还原过程
1)完全备份 mongo myrepl:PRIMARY> use test myrepl:PRIMARY> for (i=0;i<100 ;i++){ db.vast.insert ( { "id" :i, "name" : "wang" , "age" : 20,"date" : new Date()})} #执行完全备份 mkdir -p /backup/full mongodump --oplog -o /backup/full ls /backup/full/ admin config oplog.bson test 2)模拟数据变化 mongo myrepl:PRIMARY> db.test1.insert({id:1}) myrepl:PRIMARY> db.test2.insert({name:"wang"}) myrepl:PRIMARY> show tables test1 test2 vast 3)模拟10:00误删除test库中的vast表 myrepl:PRIMARY> db.vast.drop() myrepl:PRIMARY> show tables test1 test2 #开始恢复,先停应用后,执行下面恢复过程 4)备份当前oplog.rs表即备份最新oplog #oplog.rs表存放oplog信息 mongodump -d local -c oplog.rs -o /backup/oplog tree /backup/oplog/ /backup/oplog/ └── local ├── oplog.rs.bson └── oplog.rs.metadata.json 1 directory, 2 files 5)将备份下来的oplog的bson文件,覆盖完全备份的oplog.bson文件,用来还原#相当3-10点的日志也放入了 cp /backup/oplog/local/oplog.rs.bson /backup/full/oplog.bson 6)查看local库的oplog.rs表获取误删除vast表的时间戳 myrepl:PRIMARY> use local myrepl:PRIMARY> db.oplog.rs.find({op:"c"}).pretty() #输入it换页查找 #查看到误删除vast表的记录如下,记下ts信息 ..... { "op" : "c", "ns" : "test.$cmd", "ui" : UUID("db7e9d49-d965-42ad-9134-863d723cbbd6"), "o" : { "drop" : "vast" }, "o2" : { "numRecords" : 99 }, "ts" : Timestamp(1574251087, 1), #此行需要记录下来 "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2019-11-20T11:58:07.223Z") } 7)利用oplog恢复备份至误删除时间点 mongorestore --oplogReplay --oplogLimit "1574251087:1" --drop /backup/full/ 8)验证是否恢复 myrepl:PRIMARY> use test myrepl:PRIMARY> show tables; test1 test2 vast myrepl:PRIMARY> db.vast.count() 100
标签:rocky,--,MongoDB,分片,db,mongodb,test,root From: https://www.cnblogs.com/ludingchao/p/18451606