一、副本集(即MongoDB复制Replica Sets )
——指在多个服务器上存储数据副本、并实现数据同步
——提高数据可用性、安全性、方便数据故障恢复
——是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。
1.1 MongoDB 复制原理
副本集工作过程:Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息 写入到自己的oplog。
——至少需要两个节点,其中一个是主节点,负责处理客户端请求,其余是从节点,负责复制主机点数据;
——常见搭配:一主一从、一主多从
——主节点记录所有操作的oplog,从节点定期轮询主节点获取这些操作,然后随自己的数据副本执行这些操作,
从而保证从节点的数据与主节点一致
其原理是:slave端从primary端获取日志,然后在自己身上完全顺序的执行日志所记录的各种操作(该日志是不记录查询操作的),这个日志就是local数据 库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设 定:–oplogSize 1000,单位是M。
注意:在副本集的环境中,要是所有的Secondary都宕机了,只剩下Primary。最后Primary会变成Secondary,不能提供服务。
1.2 主从集群:(Master-Slave 主从复制 和Replica Sets 副本集)
主服务器支持增删改,从服务器主要支持读
主从集群的优点:
——从节点可以提供数据查询,降低主节点的访问压力
——由从节点执行备份,避免锁定主节点数据
——当主节点故障,可快速切换到从节点,实现高可用
Master-Slave 主从复制(不推荐使用了)
——启动一台服务器时加上“-master” 参数,作为主节点
——启动其他服务器时加上“-slave” 和“-source” 参数,作为从节点
Replica Sets 副本集
——从1.6版本开始支持,优于之前的replcartion
——支持故障自动切换/自动修复成员节点,降低运维成本
——Replica Sets 副本集的结构类似高可用集群
特点:副本集没有固定的主节点,它是在整个集群中选择合适的节点
二、配置Replica Sets 副本集
注意:如果有三台mongodb 服务器,其中两台宕机了,那么最后一台直接变成只读库。
环境准备:
1、准备三台mongodb服务器
2、IP端口对应:
192.168.4.61 ——27061
192.168.4.62 —— 27062
192.168.4.63 —— 27063
2.1 将三台主机mongodb的启动和停用都设置别名
]# vim /etc/bashrc (添加下面两行)
alias qmdb=‘mongod -f /usr/local/mongodb/etc/mongodb.conf’
alias smdb=’ mongod -f /usr/local/mongodb/etc/mongodb.conf --shutdown ’
3.指定每台mongdb服务器的ip 和端口
61#/etc/mongod.conf
net:
port: 27061
bindIp: 192.168.4.61
]# netstat -antulp | grep :27061
62#/etc/mongod.conf
net:
port: 27062
bindIp: 192.168.4.62
netstat -antulp | grep :27062
63 #/etc/mongod.conf
net:
port: 27063
bindIp: 192.168.4.63
netstat -antulp | grep :27063
4、配置mongodb 副本集,在 61/62/63主机上启用副本集功能并定义名称
——所有副本集成员使用相同的副本集名称
#vim /usr/local/mongodb/etc/mongdb.conf
61] bind_ip=192.168.4.61
port=27061
replSet=rsl 副本集的名称
62] bind_ip=192.168.4.62
port=27062
replSet=rsl
63] bind_ip=192.168.4.63
port=27063
replSet=rsl
5、配置节点信息(61为主库)
#mongo --host 192.168.4.61 --port 27061
config = {_id:“rs1”, // rs1 指定的副本集名称
members:[ //members :副本集的服务器列表
{_id:0 , host:“192.168.4.61:27061”},
{_id:1 , host:“192.168.4.62:27062”},
{_id:2 , host:“192.168.4.63:27063”}]}; //创建副本集
rs.initiate(config) 初始化Replica Sets 环境(初始化副本集)
{
“ok” : 1,
“operationTime” : Timestamp(1558007002, 1), // Timestamp 时间戳
“$clusterTime” : {
“clusterTime” : Timestamp(1558007002, 1),
“signature” : {
“hash” : BinData(0,“AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),
“keyId” : NumberLong(0)
}
rs1:SECONDARY>
rs1:PRIMARY> show dbs //primary 表示主库
rs1:PRIMARY> use local
rs1:PRIMARY> show tables
rs1:PRIMARY> db.me.find() //查看本机的主机名
{ “_id” : ObjectId(“5cdd49688e51f19994e665f9”), “host” : “pc61” }
rs1:PRIMARY> rs.isMaster() //查看数据库角色信息 isMaster 可以用Tab键。
“ismaster” : true, //表明本机是主机
创建副本集且指定各节点优先级
“priority” 优先级(1-100),默认为1,优先级0为被动节点,值越大,优先权越高. 如果值是0,那么不能成为primay,适用于做冷备。
“arbiteronly”:仲裁节点,只参与投票,不能接收数据,也不能称为活跃点。
config={_id:“rs1”,members:[{_id:0,host:“192.168.4.61:27061”,priority:10}, //设置优先级为10
{_id:1,host:“192.168.4.62:27062”,priority:10}, //设置优先级为10,当主库宕机时,优先级高的节点主动升级为主库
{_id:2,host:“192.168.4.63:27063”,priority:12}]} //设置优先级为12,
查看副本集信息:
查看副本集状态信息:rs.status()
查看是否是master库 : rs.isMaster()
查看复制的情况: db.printSlaveReplicationInfo() source 从库ip/端口;syncedTo 最后一次同步时间
查看副本集的配置: rs.conf() 或 rs.config()
查看从库配置情况:
注意:默认情况下Secondary时不提供服务的,既不能读也不能写,一旦执行读或写会提示错误。
在特殊情况下需要执行读操作,需要先执行一次 rs.slaveOk() ,且只对当连接有效。
62】]# mongo -host 192.168.4.62 -port 27062
rs1:SECONDARY> db.getMongo().setSlaveOk() //设置从库执行查询命令
rs1:SECONDARY> show dbs
rs1:SECONDARY> rs.isMaster() //查看数据库角色信息
“ismaster” : false,
“secondary” : true, //本机为从库
63]]# mongo -host 192.168.4.63 -port 27063
rs1:SECONDARY> db.getMongo().setSlaveOk()
rs1:SECONDARY> rs.isMaster()
++++++++++++++++ ++++++++++++++++++++++++++++++
副本集配置失败排错思路:
1、关闭mongodb主配置文件mongodb.conf集群配置项
#replSet=集群名称
2、重启mongodb服务,登录并删除local库
3、启用mongodb主配置文件mongodb.conf的集群配置项
replSet=集群名称
4、重启mongodb服务,登录并重新配置集群
++++++++++++++++++++++++++++++++++++++++++++++++++
测试从库同步复制
61主库】rs1:PRIMARY> use db15
rs1:PRIMARY> db.t1.save({name:“bob”,age:26,sex:“boy”})
rs1:PRIMARY> db.t1.save({name:“lucy”,age:16,sex:“girl”})
62】63】主机上分别验证:rs1:SECONDARY> show dbs
rs1:SECONDARY> use db15
rs1:SECONDARY> show tables
rs1:SECONDARY> db.t1.find()
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
测试高可用
61】mongodb 服务停用 ]# smdb //sbmd为 别名
62】主机上 rs1:SECONDARY> db.isMaster()
“ismaster” : true, //变为主机
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
测试故障自动恢复
61】启动服务 ]# qmdb //qmdb 为mongodb启动命令的别名
rs1:SECONDARY> db.isMaster()
“ismaster” : false,
“secondary” : true, //61主机恢复之后自动称为从库
++++++++++++++++++++++++++++++++++++++++++++++
增删节点
rs.add(_id:3,host:“192.168.4.64:27064”) 增加副本集节点
rs.remove (_id:3,host:“192.168.4.64:27064”) 删除副本集节点
++++++++++++++++++++++++++++++++++++++++++++++
添加备份节点
hidden(成员用于支持专用功能):这样设置后此机器在读写中都不可见,并且不会被选举为Primary,但是可以投票,一般用于备份数据。
添加延迟节点
Delayed(成员用于支持专用功能):可以指定一个时间延迟从primary节点同步数据。主要用于处理误删除数据马上同步到从节点导致的不一致问题。
读写分离:
MongoDB副本集对读写分离的支持是通过Read Preferences特性进行支持的。
五种 Read Preferences 模式:
—— primary
主节点,默认模式,读操作只在主节点,如果主节点不可用,报错或者抛出异常。
—— primaryPreferred
首选主节点,大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点。
—— secondary
从节点,读操作只在从节点, 如果从节点不可用,报错或者抛出异常。
—— secondaryPreferred
首选从节点,大多情况下读操作在从节点,特殊情况(如单主节点架构)读操作在主节点。
—— nearest
最邻近节点,读操作在最邻近的成员,可能是主节点或者从节点,
二、MongoDB 文档管理
插入文档
—— sava 格式 : db.集合名.save({ key:“值”,key:“值”})
注意:— 集合不存在时创建集合,然后再插入记录
— _id 字段值已存在时,修改文档字段值
— _id 字段值不存在时,插入文档
—— insert 格式 :db.集合名.insert({ key:“值”,key:“值”})
注意:— 集合不存在时创建集合,然后再插入记录
— _id 字段值已存在时,放弃插入
— _id 字段值不存在时,插入文档
—— 插入多条记录 :db.集合名.insertMany ( [ { key:“值”,key:“值”},{ key:“值”,key:“值”},{ key:“值”,key:“值”} ] )
++++++++++++++++++++++++++++++++++++++++++
查询文档:
—— 显示所有行(默认输出20行,输入it可显示后续行)
db.集合名.find()
—— 显示第一行
db.集合名.findOne()
—— 指定查询条件并指定显示的字段
db.集合名.find ({条件},{定义显示的字段}) //0 不显示 1 显示
db.user.find({},{_id:0,name:1,shell:1})
—— 行数显示限制
limit(数字) //显示前几行
db.集合名.find().limit(3)
skip(数字) //跳过前几行
db.集合名.find().skip(2)
sort(字段名) //1升序,-1降序
db.集合名.find().sort(age:1|-1)
—— 匹配条件
简单条件: db.集合名.find({key:“值”})
范围比较 —— $in 在…里 ; —— $nin 不在…里 ; —— $or 或
正则匹配:
数值比较:—— $lt 小于 < ;
—— $lte 小于等于 <= ;
—— $gt 大于 > ;
—— $gte 大于等于 >= ;
—— $ne 不等于 != ;
匹配null ,也可以匹配没有的字段
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
更新文档
—— 格式:db.集合名.update({条件},{修改的字段}) (注意不需要修改的内容还要原样写下来)
—— 多文档更新格式: 默认只更新与条件匹配的第一行
db.user.update({条件},{ $set :{修改的字段}},false,true )
—— $set / $unset
$set 条件匹配时,修改指定字段的值
db.user.update({条件}, $set :{修改的字段}}
—— $unset 删除与条件匹配文档的字段
db.user.update({条件},{ $unset:{key:values}})
—— $inc 条件匹配时,字段值自加或自减 (+数字 :自增; - 数字 自减)
db.user.update({条件},{ $inc:{字段名:数字}})
—— $push 向数组中添加新元素
db.user.update({条件},{ $push :{数组名:“值”}})
—— $addToSet 避免重复添加
db.user.update({条件},{ $addToSet:{数组名:“值”}})
—— $pop 从数组头部删除一个元素
db.user.update({条件},{ $pop:{数组名:数字}})
( 1 删除数组尾部元素; -1 删除数组头部元素)
—— $pull 删除数组指定元素
db.user.update({条件},{ $pull:{数组名:值}})
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
删除文档
—— $drop 删除集合的同时删除索引
db.集合名.drop()
—— $ remove() 删除文档时不删除索引
db.集合名.remove({}) //删除所有文档
db.集合名.remove({条件}) //删除与条件匹配的文档
remove() 和 drop() 的区别:
remove() 删除文档时不删除索引
drop() 删除集合的同时删除索引
————+++++++++++++++++++++++++++++++++++++++++++++
实验:
插入多行文档:
】 db.t3.insertMany([{name:“xili”},{name:“lina”}])
】db.t3.insertMany([{name:“xili2”},{name:“traina”,age:23}])
】 db.t3.find({$or:[{name:“xili”},{name:“traina”}]},{name:1})
更新文档:
】db.user.update({name:“bin”},{ $unset:{comment:1}}) 删除指定字段
】db.user.update({name:“bin”},{ $set:{password:“abc123”}})
】db.user.find({name:/^a/},{_id:0,name:1,password:1})
】db.user.update({name:/^a/},{$set:{passwprd:“fff”}},false,true) false,true修改多行
]db.user.find({name:/^a/},{_id:0,name:1,password:1})
删除数组末尾最后一位元素
】db.user.insert({name:“bob”,like:[“a”,“b”,“c”,“d”]})
】db.user.update({name:“bob”},{KaTeX parse error: Expected 'EOF', got '}' at position 13: pop:{like:1}}̲) 】db.user.find…pull:{like:“b”}})
】db.user.find({name:“bob”})
删除数组头部一个元素
】db.user.insert({name:“bob”,like:[“a”,“b”,“c”,“d”,“e”,“f”]})
】db.user.find({name:“bob”})
】db.user.update({name:“bob”},{KaTeX parse error: Expected 'EOF', got '}' at position 14: pop:{like:-1}}̲) 】db.user.find…push:{like:“F”}})
存在时不添加
】 db.user.update({name:“bob”},{KaTeX parse error: Expected 'EOF', got '}' at position 20: …oSet:{like:"F"}}̲) 】db.user.find…inc:{uid:2}})
设置字段值自减(负数为自减)
】db.user.update({name:“bin”},{$inc:{uid:-1}})