您的位置:首页 > 数据库 > Mongodb

Mongodb -副本集与读写分离(一)

2017-04-18 10:08 225 查看
Mongodb 副本集与读写分离(一)

采用读写分离技术可以减轻主库的压力,使主库提供写操作,从库提供读操作。如果所有的操作都放在主库中,那么当大量的读操作,将会锁住数据库。很多架构采用的是一主多从的方式。

副本集在某种程度上可以支持读写分离,其优势为:

1、            在实际生产环境中,一个Mongod风险会很高,在某段时间内,数据库发生了奔溃,会有一段时间内数据库不可用。硬件出了问题,需要将数据拷贝到另一个电脑上。

2、            官方建议在所有的生产环境中都使用副本集,即使一台多态服务器中出现错误,也可以保证应用程序的正常运行和数据安全。

副本集操作:

1、  副本集的配置中不能使用Localhost作为副本集的配置,其它节点将无法识别。

2、  使用rs.add()添加副本集

3、  rs.remove()删除副本集

oplog

在多台服务器中进行数据同步,使用操作日志oplog,其中包含节点的每一次写操作,每个备份节点维护自己的oplog,记录每一次从主节点复制数据的操作。如果某个备份节点挂了,会从最后一个操作开始同步。复制的过程是先复制数据然后再写入oplog,也因此会存在在已经同步过的数据中再次复制。但是这种情况下,其得到的结果是一样的,数据不会有两份。单次请求会影响多个oplog的文档。比如一次批量写入,或者批量删除,更新,都会在oplog对应多个文档。在启动副本集中会尝试从某个节点中进行同步,如果该节点不行会尝试从其他的节点中进行同步。

所以oplog是一个纽带的作用,记录着所有写操作的记录。副本集的同步采用的是异步过程。在oplog中,其大小是可以调整的。默认值为可用磁盘空间的5%。当一个备份节点陈旧后,会查看副本集中其它成员,如果某个成员的oplog足够详尽,可以用于处理那些落下的操作,那么就从这个节点中同步,如果发现没有节点可以参考,那么需要重新进行同步。对于重新同步过程应该尽量的避免,所以在实际的部署中,oplog的长度至少要能够容纳一次完整同步的所有操作。通常会希望oplog能够保存几天或者一个星期的数据,给自己足够的时间去处理各种突发状况。所以,可能会需要动态的调整oplog的大小,一般来说是增加。

当负载能力不够的时候会导致副本集性能降低,导致备份节点落后于主节点。开始进行复制数据,导致主节点过载。进而整个副本集没有喘息机会。

需要注意的是:

1. 在主节点中发送创建索引的命令,从节点将会接受到指令,但是在这段时间内,备份节点会在同一时间开始创建索引,那么几乎同一时刻所有成员都不能用,知道所有的索引都创建完毕。

2. 在复制的过程中采用多线程批量写入,以提高并发性。在使用批量的时候,mongodb会阻塞所有的读操作。因此在这段时间内,所有向从节点发送的读操作都不能够返回数据。

Journal 与oplog

对于容易混淆的journal,当我们开启日志后,每次写入都会有一条日志记录。mongodb写入有两种情况,在开启日志后,如果是默认的,那么数据写入内存后,会在storage.journal.commitInternalMs间隔后,将日志写入journal文件中。当然在写的时候如果指定了j:true则会马上写入文件。

Mongodb副本集中写入一个文档包括的步骤有:

将文档写入集合

更新索引

写入oplog

所以,其实我们可以将oplog认为一个普通的集合。

参考文档:http://www.mongoing.com/archives/3988

 

副本集的优先级

副本集当中的节点即使使用了较高的优先级,但是如果数据不够新,依旧不会成为主节点。通过设置slaveDelay要求成员的优先级为0,延迟备份节点的数据将比主节点的数据延迟指定时间,以防止主节点在某一段时间内发生了异常影响备份节点的数据。一般这种情况下,要求备份节点的为隐藏节点,防止读操作定向于该节点。如果不希望某个节点被客户端读,可以设置该节点为隐藏节点。比如我们只是希望一个冗余备份,那么可以使用一个不太好的服务器设置为隐藏节点进行容灾。

同步过程

初始化同步:

 1、   复制除local之外的所有数据库。Mongod扫描所有的集合,并将所有的数据都写入对应的集合中。

2、    在3.4中当文档都复制到各个集合中的同时会创建所有集合的索引。在之前的版本中只有_id索引被写入。

3、    在初始化过程中,会将最新的增加记录从oplog中删除,即在同步初始化过程中,oplog不会占用很大的空间。

当初始化结束后,从节点会持续从主节点中异步复制,从节点不会从延时成员及隐藏节点中进行同步。

对于副本集的索引,如果不希望副本集中有索引,设置buildIndex 为false ,但是一旦设置为false,再成为true的话会非常难。在3.4中,默认会同步所有的索引。

问题

1、  那么一般意义的写与同步过程中的写区别是什么?异步?

首先,采用的是异步,会采用多线程去批量操作。如果是大并发的写入主库,那么对于写与同步过程来说只有1.时间的延时。2.批量写入。

2、  Mongodb的主从是否会有问题?

可以设置某个节点永远为主节点,通过设置隐藏节点,优先级等操作。如果不设置这些参数,添加一个仲裁节点虽然可能会有风险,比如主节点A宕掉之后,第二个节点B作为主节点。对于大规模写入的情况下,如果时间过长,当原来的主节点A启动,这其中的同步过程将会耗费很长时间,且这个从库中也无法提供读操作,所有的读操作还在在B节点中

3、一台服务器中部署多个shard节点?通过设置缓存的大小?

4、数据同步过程是否会增加额外的负担?

是的,同步过程需要首先从节点中复制数据,在已经负载很大压力情况下,会让节点产生更大的压力。再克隆数据的过程中,可能会损坏同步源的工作集,因为可能需要将数据子集常驻内存。在执行初始化同步的过程中会强制将当前成员的所有数据分页加载到内存中。那么对于原来需要频繁访问的数据就不能常驻内存,会导致很多的请求变慢。

读写分离

官网中建议不使用向从节点取数据。原因:

1、  所有的从节点拥有与主节点一样的写入负载,读的加入会增加其负载

2、  对于分片的集合,在平衡器的关系下,数据的返回结果可能会缺失或者重复某部分数据。

3、  相对而言,官方建议使用shard来分散读写请求。

使用的场景;

1、  异地的分布式部署

2、  故障切换,在紧急情况下向从节点读数据

总结:副本集不是为了提高读性能存在的,在进行oplog的时候,读操作时被阻塞的。提高读取性能应该使用分片和索引,它的存在更多是作为数据冗余,备份。尤其当主库本来就面临着大量的写入压力,对于副本集的节点,也同样会面临写的压力。

参考文献:

1. http://www.open-open.com/lib/view/open1448113292072.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: