副本集
MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制还允许您从硬件故障和服务中断中恢复数据。
什么是复制?
- 保障数据的安全性
- 数据高可用性 (24*7)
- 灾难恢复
- 无需停机维护(如备份,重建索引,压缩)
- 分布式读取数据
MongoDB复制原理
mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
MongoDB复制结构图如下所示:
以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时, 主节点与从节点进行数据交互保障数据的一致性。
副本集特征:
- N个节点的集群
- 任何节点可作为主节点
- 所有写入操作都在主节点上
- 自动故障转移
- 自动恢复
MongoDB副本集配置
- MongoDB数据文件存储路径
- MongoDB日志文件存储路径
- MongoBD key文件存储路径
- MongoDB实例监听端口(28010/28011/28012)
先把要存储的目录和文件先建一下,key0,key1,key2的文件内容是一样的。
1 | . |
启动3个mongod实例的副本集
1 | mongod --replSet myset --keyFile key/key0/key0 --port 28010 --dbpath data/data0 --logpath log/log0/log0.log --logappend |
启动可能会有一个错误:
mongodb/key/key0/key0 are too open
查了一下说是key的文件权限太大了,chmod 700 key/key0/key0
改一下权限再启动就好了。
现在这3个mongod的实例还没有通信,还没有在一个副本集中,还需要用客户端连接到其中一个实例做一些配置。
1 | mongo --port 28010 |
出错了,说准备初始化一个bafeite的副本集,但是命令行启动的时候是myset
,所以拒绝。
1 | > config_myset={_id:'myset', members:[{_id:0, host:'localhost:28010'},{_id:1, host:'localhost:28011'},{_id:2, host:'localhost:28012'}]}; |
members就是副本集里面的mongod实例,stateStr表示了实例是Primary或者Secondary,lastHeartbeat就是上次心跳检测的时间。
插入数据
1 | > db.article.save({title:'MongoDB应用开发实战', author:'zhangsan', creationDate:new Date()}); |
得到一个错误,查了下是因为指定了keyFile以后,mongodb默认就会加上--auth
启动,为了简化操作,先把keyFile参数去掉重启一下吧。
1 | ~ mongo --port 28010 |
现在去连接另外一个mongod实例,看看这个数据在不在。
1 | mongo --port 28011 |
执行不了,报错了,是因为从实例需要设置一下才能查询。
1 | myset:SECONDARY> db.getMongo().setSlaveOk(); |
添加副本集
rs.add('host:port')
删除副本集
rs.remove('host:port')
重新配置
1 | var config = rs.config(); |
监控-mongostat
mongodb提供了一个mongostat命令用于监控mongodb服务器。
1 | ➜ ~ mongostat --help |
监控副本集的命令:
1 | ➜ ~ mongostat --host=myset/localhost:28010,localhost:28011,localhost:28012 |
关于副本集的原理分析:
副本集有且只有一台机器是primary,primary与secondary之间的数据复制是异步进行的,并且通过oplog进行。
副本集中的机器数最好为奇数。
Primary机器接收所有的写操作(无法改变的),我们可以配置read preference,使得读操作可以发生在secondary机器上。如果读操作发生在primary机器上,那么机器就是强一致性的;
副本集中最多有50台机器,之前的版本最多有12台机器。如果超过了50台,那么只能使用Master-Slave方式。不过如果使用Master-Slave方式,那么就失去了自动化的failover机制。
Arbiter机器(仲裁机器),它本身并不存放数据库数据,仅提供选举功能。
不要将arbiter机器放在primary或是secondary机器上。
对于secondary机器,可以进行如下配置:
- 禁止某台secondary机器成为primary机器,priority为0。
- 禁止客户端读取某台secondary机器的数据,隐藏成员。
- 仅记录历史快照的secondary,延迟成员。比如说延迟一小时
最常见的secondary机器依然是进行数据异步复制与保持系统高可用的形式。
副本集中最多有50台机器,其中具有投票功能的机器数量最多是7台。
Priority为0的机器:无法成为primary。不能触发一个选举
关于MongoDB的读写分离:
- 如果进行读写分离,那么要注意到读会有延迟
- secondary机器要通过oplog异步复制primary机器的数据,因此从整体来看,primary与secondary机器的读速度是大体相当的。
- 默认情况下,MongoDB的读写都是在primary上进行的。
关于Read preference:
- Primary(默认值)
- primaryPreferred
- secondary
- secondaryPreferred
- nearest(网络延迟最少的)
关于延迟成员(delayed member)
- 延迟成员的priority必须为0,表示它无法成为primary。
- 延迟成员也是隐藏成员,应用是无法通过延迟成员查询数据的。
- 可以对primary的选举进行投票。
请确保副本集中成员的个数为奇数,如果是偶数的话,请添加一个arbiter成员。
关于MongoDB的投票与故障恢复:
- MongoDB投票要求投票时系统中可用的机器数量要是全体副本集成员个数的大多数。
- 如果副本集中有3台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以正常使用?2台。
- 如果副本集中有4台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以正常使用?3台。
- 如果副本集中有5台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以正常使用?3台。
- 如果副本集中有6台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以正常使用?4台。
- 如果副本集中有7台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以正常使用?4台。
向副本集中添加成员并不总是会确保系统的故障恢复能力,不过这样做可以实现一些额外的功:备份、统计报表等。