环境准备 51~53都需要安装MongoDB服务,并设置对应的ip地址跟端口
副本集介绍
也称为MongoDB复制指在多个服务器上存储数据副本,并实现数据同步提高数据可用性、安全性、方便数据故障恢复MongoDB复制原理
副本集工作过程 至少需要两个节点,其中一个是主节点,负责处理客户端请求,其余是从节点,负责复制主节点数据常见搭配方式:一主一从、一主多从主节点记录所有操作oplog,从节点定期轮询主节点获取获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致副本集实现方式
Master-Salve主从复制 启动一台服务器时加上 “-master” 参数,做为主节点 启动其他服务器时加上“-slave” 和 “-source” 参数,做为从节点主从复制的优点 从节点可以提供数据查询,降低主节点的访问压力 由从节点执行备份,避免锁定主节点数据 当主节点故障时,可快速切换到从节点,实现高可用Replica Sets副本集 从1.6版本开始支持,优于之前的replication 支持故障自动切换、自动修复成员节点,降低运维成本 Replica Sets副本集的结构类似高可用集群一、运行MongoDB服务
启动服务时,指定主机所在副本集名称 所有副本集成员使用相同的副本集名称–replSet rs1 //指定副本集名称51~53上操作
修改配置文件,指定副本集 [root@ip51 ~]# mstop [root@ip51 ~]# vim /usr/local/mongodb/etc/mongodb.conf ... ... replSet rs1 [root@ip51 ~]# mstart二、配置节点信息
在任意一台主机连接mongodb服务,执行如下操作 [root@ip51 ~]# /usr/local/mongodb/bin/mongo --host 192.168.4.51 --port 27051 > config = { _id:"rs1", members:[ {_id:0,host:"192.168.4.51:27051"}, {_id:1,host:"192.168.4.52:27052"}, {_id:2,host:"192.168.4.53:27053"} ] }; 初始化Replica Sets环境 执行如下命令 > rs.initiate(config) { "ok" : 1, "operationTime" : Timestamp(1558755758, 1), "$clusterTime" : { "clusterTime" : Timestamp(1558755758, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } 查看副本集信息-查看状态信息
> rs.status() 查看是否是master库 > rs.isMaster()副本集创建失败,解决办法 1.停止服务 2.删除配置文件里面的副本集配置 3.启动服务 4.连接服务后,删除local库,断开连接 5.在配置文件中,启用配置副本集配置 6.重启服务 7.连接服务后,创建成员列表,然后创建副本集
三、验证副本集配置
同步数据验证,允许从库查看数据 > db.getMongo().setSlaveOk() 自动切换主库验证 > rs.isMaster() 登录主库创建数据,查看从库同步情况 rs1:PRIMARY> use userdb rs1:PRIMARY> db.t1.save({"name":"bob","class":"beida"})从库上查看
rs1:SECONDARY> use userdb rs1:SECONDARY> db.t1.find() { "_id" : ObjectId("5ce8df5b8e839d6a2be24eba"), "name" : "bob", "class" : "beida" }创建时指定优先级,谁的优先级最高,谁是主库
格式 > db.集合名.insert({key:"值",key:"值"})
注意 集合不存在时创建集合,然后再插入记录 _id字段值已存在时,放弃插入 _id字段值不存在时,插入文档
rs1:PRIMARY> db.t1.save({_id:7,name:"tom"}) rs1:PRIMARY> db.t1.save({_id:7,name:"tom1"}) //修改值 rs1:PRIMARY> db.t1.insert({_id:8,name:"bob"}) rs1:PRIMARY> db.t1.insert({_id:8,name:"harry"}) //报错 插入多条记录 > db.集合名.insertMany( [ {name:"xiaojiu",age:19}, {name:"bob",email:"123@qq.com"} ] ) rs1:PRIMARY> db.t2.insertMany([ {name:"jack",age:888}, {mail:"456@qq.com",name:"reno"}, {x:99,y:77} ])查询语法
显示所有行(默认输出20行,输入it可显示后续行) > db.集合名.find()
显示第1行 > db.集合名.findOne()
指定查询条件并指定显示的字段 > db.集合名.find({条件},{定义显示的字段})
rs1:PRIMARY> db.user.find({},{_id:0,name:1,uid:1}) //0 不显示,1显示行数显示限制
limit(数字) > db.集合名.find().limit(3) //显示前几行 rs1:PRIMARY> db.user.find({},{_id:0,name:1,shell:1}).count() //统计个数 rs1:PRIMARY> db.user.find({},{_id:0,name:1,shell:1}).limit(10) skip(数字) > db.集合名.find().skip(2) //跳过前几行 rs1:PRIMARY> db.user.find({},{_id:0,name:1,shell:1}).limit(10).skip(3) //从第四行开始,显示10条 rs1:PRIMARY> db.user.find({shell:"/sbin/nologin"},{_id:0,name:1,uid:1,shell:1}).skip(2).limit(2) //显示shell是/sbin/nologin,从第三条开始显示两条 sort(字段名) > db.集合名.find().sort({age:1|-1}) //1升序,-1降序 rs1:PRIMARY> db.user.find({},{_id:0,name:1,uid:1}).skip(2).sort({uid:1})正则匹配
rs1:SECONDARY> db.user.find({name:/^a/}) //匹配以a开头的数据数值比较
$lt $lte $gt $gte $ne< <= > >= != rs1:SECONDARY> db.user.find({uid:{$gte:100}},{_id:0,name:1,uid:1}) //查找uid大于等于100的数据 rs1:SECONDARY> db.user.find({uid:{$gte:10,$lte:40}},{_id:0,name:1,uid:1}) //查找uid在10和40之间的数据匹配null,也可以匹配没有的字段
rs1:SECONDARY> db.user.find({password:null},{_id:0,name:1,uid:1})update()
语法格式 > db.集合名.update({条件},{修改的字段}) rs1:PRIMARY> db.user.update({uid:{$lte:3}},{password:"99999999999999"}) rs1:PRIMARY> db.user.find({password:"99999999999999"} //把文件的其他字段都删除了,只留下了password字段,且只修改与条件匹配的第一行多文档更新
语法更新:默认只更新与条件匹配的第1行 > db.user.update({条件},{$set:{修改的字段}},false,true) rs1:PRIMARY> db.user.update({uid:{$gte:3,$lte:20}},{$set:{name:"root",password:"11111"}},false,true) //修改uid在3和20之间的数据,将name修改成root,password修改成11111,其他的不变 rs1:PRIMARY> db.user.find({uid:{$gte:3,$lte:20}})$set/$unset
$set 条件匹配时,修改指定字段的值
$unset 删除与条件匹配文档的字段
rs1:PRIMARY> db.user.update({name:"root"},{$unset:{password:"11111"}}) //删除name为root,password为11111的第一条数据的password字段$inc
$inc 条件匹配时,字段值自加或者自减 > db.集合名.update({条件},{$inc:{字段名:数字}}) //数字为负,自减,数字为正,自加 rs1:PRIMARY> db.user.update({name:"root"},{$inc:{uid:-2}}) //查找name为root的数据,uid自减2 rs1:PRIMARY> db.user.update({name:"root"},{$inc:{uid:1000}}) //查找name为root的数据,uid自加1000$push/$addToSet
$push 向数组中添加新元素 > db.集合名.update({条件},{$push:{数组名:"值"}}) rs1:PRIMARY> db.t3.insert({name:"bob",likes:["a","b","c","d"]}) rs1:PRIMARY> db.t3.update({name:"bob"},{$push:{likes:"w"}}) //向bob用户数据likes里边插入w字段,字段可重复添加 $addToSet 避免重复添加 > db.集合名.update({条件},{$addToSet:{数组名:"值"}}) rs1:PRIMARY> db.t3.update({name:"bob"},{$addToSet:{likes:"q"}}) //q不存在则添加,存在的化不添加$pop/$pull
$pop从数组头部删除一个元素 > db.集合名.update({条件},{$pop:{数组名:数字}}) //数字为1,删除数组尾部元素,数字为-1,删除数组头部元素 rs1:PRIMARY> db.t3.update({name:"bob"},{$pop:{likes:1}}) //删除likes最后一个元素 rs1:PRIMARY> db.t3.update({name:"bob"},{$pop:{likes:-1}}) //删除likes第一个元素 $pull 删除数组指定元素 > db.集合名.update({条件},{$pull:{数组名:值}}) rs1:PRIMARY> db.t3.update({name:"bob"},{$pull:{likes:"d"}}) //删除数组元素d$drop/$remove
$drop 删除集合的同时删除索引 > db.集合名.drop() rs1:PRIMARY> db.t1.drop() $remove() 删除文档时不删除索引 > db.集合名.remove({}) //删除所有文档 > db.集合名.remove({条件}) //删除与条件匹配的文档 rs1:PRIMARY> db.t2.remove({}) rs1:PRIMARY> db.user.remove({uid:{$gte:10}}) //删除uid大于等于10的数据