MongoDB副本集,增删查改

环境准备
51~53都需要安装MongoDB服务,并设置对应的ip地址跟端口

副本集介绍

  • 也称为MongoDB复制
  • 指在多个服务器上存储数据副本,并实现数据同步
  • 提高数据可用性、安全性、方便数据故障恢复

MongoDB复制原理

  • 副本集工作过程
    至少需要两个节点,其中一个是主节点,负责处理客户端请求,其余是从节点,负责复制主节点数据
  • 常见搭配方式:一主一从、一主多从
  • 主节点记录所有操作oplog,从节点定期轮询主节点获取获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致

副本集实现方式

  • Master-Salve主从复制
    启动一台服务器时加上 “-master” 参数,做为主节点
    启动其他服务器时加上“-slave” 和 “-source” 参数,做为从节点
  • 主从复制的优点
    从节点可以提供数据查询,降低主节点的访问压力
    由从节点执行备份,避免锁定主节点数据
    当主节点故障时,可快速切换到从节点,实现高可用
  • Replica Sets副本集
    从1.6版本开始支持,优于之前的replication
    支持故障自动切换、自动修复成员节点,降低运维成本
    Replica Sets副本集的结构类似高可用集群

配置Replica Sets

一、运行MongoDB服务

  • 启动服务时,指定主机所在副本集名称
    所有副本集成员使用相同的副本集名称
  • –replSet rs1 //指定副本集名称

51~53上操作

  1. 修改配置文件,指定副本集
[root@ip51 ~]# mstop
[root@ip51 ~]# vim /usr/local/mongodb/etc/mongodb.conf 
... ...
replSet rs1
[root@ip51 ~]# mstart

二、配置节点信息

  1. 在任意一台主机连接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"}
    ]
    };
  1. 初始化Replica Sets环境
  • 执行如下命令
 > rs.initiate(config)
{
	"ok" : 1,
	"operationTime" : Timestamp(1558755758, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1558755758, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
  1. 查看副本集信息

-查看状态信息

> rs.status()
  • 查看是否是master库
> rs.isMaster()

副本集创建失败,解决办法
1.停止服务
2.删除配置文件里面的副本集配置
3.启动服务
4.连接服务后,删除local库,断开连接
5.在配置文件中,启用配置副本集配置
6.重启服务
7.连接服务后,创建成员列表,然后创建副本集

三、验证副本集配置

  1. 同步数据验证,允许从库查看数据
> db.getMongo().setSlaveOk()
  1. 自动切换主库验证
> rs.isMaster()
  1. 登录主库创建数据,查看从库同步情况
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" }

测试高可用

  1. 停掉51主库,查看52,53主机状态
  2. 客户端连接新的主库,插入新数据,在另一台从库上查看新数据
  3. 启动51主机服务,登录,查看51当前状态(变为当前主库的从库)

创建时指定主库

> config = {
    _id:"rs1",
    members:[
    {_id:0,host:"192.168.4.51:27051",priority:10},
    {_id:1,host:"192.168.4.52:27052",priority:30},
    {_id:2,host:"192.168.4.53:27053",priority:20}
    ]
    };

创建时指定优先级,谁的优先级最高,谁是主库

插入文档

save()

  • 格式
    > db.集合名.save({key:"值",key:"值"})
  • 注意
    集合不存在时创建集合,然后再插入记录
    _id字段值已存在时,修改文档字段值
    _id字段不存在时,插入文档

insert()

  • 格式
    > 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:"[email protected]"}
     ]
   )
rs1:PRIMARY> db.t2.insertMany([
             {name:"jack",age:888},
             {mail:"[email protected]",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})

匹配条件

  • 简单条件
    > db.集合名.find({key:"值"})
    > db.集合名.find({key:"值",keyname:"值"})
rs1:SECONDARY> db.user.find({shell:"/bin/bash"}) //显示shell为/bin/bash的数据
rs1:SECONDARY> db.user.find({shell:"/bin/bash"},{_id:0})  //显示shell为/bin/bash,除了_id之外的数据
rs1:SECONDARY> db.user.find({shell:"/bin/bash",name:"root"},{_id:0,name:1,shell:1})  //显示shell为/bin/bash且name为root的数据,不显示_id,只显示name跟shell字段
  • 范围比较
    $in 在...里
    $nin 不在...里
    $or 或
rs1:SECONDARY> db.user.find({name:{$in:["root","adm","bin"]}})  //显示name为root、adm、bin的数据
rs1:SECONDARY> db.user.find({uid:{$nin:[9,7,21]}},{_id:0,name:1,uid:1})  //显示uid不是9,7,21的数据
rs1:SECONDARY> db.user.find({$or:[{name:"root"},{uid:1},{shell:"/bin/bash"}]},{_id:0,name:1,uid:1})   //查找name是root的或者uid为1的或者shell是/bin/bash的数据。只显示name跟uid字段

正则匹配

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的数据

你可能感兴趣的:(MongoDB,副本集,增删改查,数据库)