`
jgsj
  • 浏览: 961074 次
文章分类
社区版块
存档分类
最新评论

从MongoDB Replica Set HA 看分布式系统读写一致性问题

阅读更多
副本集基础
Replica Set是mongodb提供的一个去中心化的备份模式(同时mongodb还提供了主从部署和分片模式),每个mongod都可以是master,且副本集内会自动选举出一个primary,其他都暂时为seconary,primary挂掉后会自动选举出新的primary。副本集内所有mongod存储的都是数据全集,secondary节点会从primary同步数据操作以保证自己的数据up-to-date。副本集有自己的选举机制,相对是一种比较简单的选举,根据心跳、权重等因素选取一个可用的节点来做primary。

副本集
副本集里只有一个primary可以写,保持严格的一致性(primary是严格一致性,secondary是最终一致性)。primary把log写在oplog里,secondary的节点异步拷贝primary的oplog(为了便利,副本集内各自的oplog都可以互相获得和拷贝),将operation作用在自己的数据集上。oplog里对于数据集的操作,都是幂等的。mongod启动的时候会产生一个默认大小的oplog,想要改变oplog size需要在启动前设置,启动后再设置需要走另一个流程,比较麻烦些。
如果副本集是偶数的话,可以加一个arbiter,他不维护数据,只参加投票。member还有别的状态,如delayed member,hidden member
clients默认读的是primary的数据集,读secondary的数据集可以另外指定。既然secondary是根据oplog对自己的数据集异步实施operation的,就一定存在延迟。
副本集数据同步存在两种方式:
1. 初始化同步:对于新的没有数据的member或者丢失了一部分历史记录的缺失数据集,拷贝现有副本集内某个member的整份数据。整个过程流程为先clone数据,然后apply all changes,最后建索引。
2. 不间断同步:一般secondary都是从primay同步(定时ping primary查看state)。
为了保证续航性(Durability),在单线程上提供了journaling,每次写需要先写进journal,然后再到数据集(默认需要64bit的mongodb2.0以上版本才有journal)。
对于多线程的Replication而言,mongodb用多线程批量写来保证并发,批处理按namespace分组,每个namespace里的并发写是有序的。当使用批量写的时候,mongodb不允许read。

使用journaling的时候,mongodb先把写操作记录存在内存里,实施在journal里。默认journal路径为/data/db,启动mongod的时候会预分配一定大小,里面的journal files是append-only的。jfile的最大容量可以设置,当jfile大于1G时候,会创建新jfile。jfile的路径也可以另外指定,指定到别的文件系统加快读写速度。一旦mongodb完成了所有写操作,这些jfile就会被删除。
简单描述下从内存到jfile再到disk数据集的过程。Journalling提供三种视图,shared views,private views(只读)和?。他们权限不同。mongodb用批处理的方式,先把内存里的写操作以private view的方式刷到jfile里,然后再把jfile里的内容以share view的方式flush到磁盘上,此时数据集得以更新到最新。

总结
Mongodb通过副本集的方式提高可用性,一方面副本集是去中心化的模式,能够自动检测选举新的primary,同步节点之间的数据,通过mongos路由路口,保证对client端透明;另一方面副本集存储数据全集,只要你能容忍他的最终一致性,secondary节点一样可以提供read。在Mongodb2.0之后的版本加入了journaling这个东西,更加增强了可靠性,保证当你的primary挂掉之后,前面几次修改操作仍然被记录在journal中,可以被还原也可以被撤销,避免数据不一致或弄脏的情况。journaling其实类似很多分布式系统中采用的做法,涉及到内存,涉及到先写到journal中,写成功后再执行到真的数据集中。
本文尝试通过mongodb副本集的分析,对分布式系统读写一致性问题做简单的理解,理解有误之处还请多包涵。

(全文完)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics