简介
在生产环境中,为了保证数据的安全性,我们通常要使用冗余保存。MongoDB中我们提供了这个功能,也就是MongoDB的复制。
主从复制
主从是复制是MongoDB中最常见的复制方式,可以用于备份、故障恢复、读扩展等方面。
这种方式一般设置有1个主节点1到多个从节点,每个从节点都要知道主节点的位置并且从节点从主节点复制数据。一般情况下,从节点不要超过12个,同时。主节点与从节点不同的地方在于主节点有oplog,但是从节点没有。
MongoDB的主从设置方式和Hadoop不一样,Hadoop是要在每个节点的hadoop配置文件中配置,而MongoDB是在启动MongoDB实例的时候来指明当前实例是主节点还是从节点:
启动主节点:
mongod --dbpath 主节点数据目录 --port 端口号 --master
启动从节点:
mongod --dbpath 从节点数据目录 --port 端口号 --slave --source 主节点IP:port
主从复制的选项
--only
从节点使用,指明当前从节点只复制某个数据库
--slavedelay
从节点使用,应用主节点的最新操作的延时时间。防止主节点的错误操作直接的应用到从节点上,起到防护数据作用。
--fastsync
以主节点的数据快照为基础启动从节点,如果一开始就是使用数据库快照,那么以后的复制速度会较快。
--autoresync
如果主从节点不同步,则自动重新同步。
--oplogSize
主节点oplog的大小,单位是M。
添加、删除主节点
当启动从节点的时候,可以通过--source来指定主节点的网络位置,也可以在启动从节点时不指定--source,而是使用MongoDB给我们提供的命令添加或主节点:
use local//必须使用local数据库
db.sources.insert({'host':'IP:PORT'})
从上边的命令,我们可以看到MongoDB中从节点保存主节点信息的方式是在local数据库的sources集合中,所以相应的,我们就可以通过对local数据库中的sources集合修改实现从节点指向的主节点的变更,这个变更是热变更不需要重启从节点的MongoDB实例。
同时一个从节点可以复制多个主节点。
副本集
副本集就是有自动故障恢复功能的主从集群。副本集和主从复制相同的地方是他们都是由一个主节点和多个从节点构成的,而不同之处在于主从复制中的主节点是固定不变的,而副本集中的主节点是会改变的。
副本集中主节点的变化是全自动的、透明的。
每个副本集都有一个唯一的名称。
副本集操作
启动方式
- 启动副本集中的各个节点:
副本集节点1启动:
mongod --dbpath 数据目录--port 端口号 --replSet 副本集名称/ip地址或hostname2:端口号2(虽然2还没有启动)
副本集节点2启动
mongod --dbpath 数据目录--port 端口号 --replSet 副本集名称/ip地址或hostname2:端口号2
副本集节点N启动
mongod --dbpath 数据目录--port 端口号 --replSet 副本集名称/ip地址或hostname1:端口号1
- 使用mongo shell初始化副本集(随便连接一个副本集节点即可,只需要初始化一次)
useadmin//使用管理数据库
db.runCommand({'replSetInitiate':
'_id':副本集名称,
'members':[
{
'_id':节点编号,从1开始的数字,
'host':'IP地址或hostname:端口号'
},
{
'_id':节点编号,从1开始的数字,
'host':'IP地址或hostname:端口号'
}
]
})
向存在副本集中添加节点
- 首先,在要添加到副本集的节点上执行:
mongod --dbpath 数据目录 --replSet 副本集名称
- 然后,使用shell连接到副本集中的主节点,执行:
rs.add('IP;port',是否仲裁节点)
从存在的副本集中删除节点
在主节点上调用rs.remove('ip:port')即可删除节点。
查看副本集运行状态
在主节点上调用rs.status(),返回的文档就是当前节点所在的副本集运行的状态。stateStr指明了所在members数组元素的状态,primary为活跃节点。
节点说明
任何时间,副本集中有且只有一个活跃节点,其他的都是备份节点。有几种不同类型的节点可以存在于副本集中:
- standard
常规节点,存储一份完整的数据副本,可以成为活跃节点。
- passive
被动节点,存储完整的数据副本,不能成为活跃节点
- arbiter
仲裁者节点,不会保存数据,也不能成为活跃节点。只能投票。
所有的节点信息都保存在local.system.replset集合中,我们可以通过修改该集合中某个节点的priority来设定该节点的优先级(0-1000),通过arbiterOnly设置该节点是否是仲裁节点。
对于节点的优先级,优先级高的节点成为活跃节点的概率越高,当优先级相同时,数据越新那么越会成为活跃节点。
副本集功能
副本集不只是可以很好的冗余保存数据,保证应用7*24运行。同意也可以做一些特殊的应用扩展,例如:
- 读扩展
主节点执行写入操作,而从节点执行查询操作。但是一定要注意的是,从节点复制主节点数据时有一定延迟的,所以在使用读扩展的时候,一定要考虑到从节点的数据同步延迟性。
- 利用从节点处理数据
可以利用从节点来处理数据,一定要保证从节点与主节点的数据同步性,以及数据拷贝延迟性。
工作原理
简单的来说,MongoDB复制的工作原理很简单,也就是由主节点负责与客户端交互,记录客户端操作。从节点通过定期轮询主节点,得到客户端操作记录,在从节点自身执行这些操作,从而保证数据的一致性。在同步的过程中,需要用到以下文件:
- Oplog
主节点的操作记录就是oplog。oplog存储在local(本地)数据库中oplog.$main集合中。oplog中只记录对数据库数据变更的操作即曾删改操作,查询操作不会记录,同时oplog记录的操作会进过MongoDB处理后记录,不一定和客户端的原始操作完全一样。存储oplog的集合是一个固定集合,当集合满的时候,新操作会自动替换旧操作,启动MongoDB实例的时候使用--oplogSize指定存储oplog集合的大小
特殊说明:
- 从节点第一次启动,会全复制主节点的数据,然后去查询oplog并执行oplog。如果oplog所在的固定集合太小或者复制数据时间太长,那么从节点就会被主节点数据落下很远,这个时候使用oplog的数据已经不能保证主从节点的数据一致性了。虽然可以通过命令:resync或启动从节点的时候使用--autoresync命令自动重新同步,但是不能完全解决这个问题。最好的解决办法是配置足够大的oplog集合。即使用--oplogSize命令设置。
- MongoDB中local数据库的内容是不会被复制的。
监控复制状态
在主节点中,使用db.printReplicationInfo()函数,可以得到oplog的大小和oplog中可存储数据的时间段。
在从节点中,使用db.printSlaveReplicationInfo()函数可以得到当前从节点的数据源列表,以及滞后时间。