MongoDB副本集概述

以下图片摘自MongoDB官方文档:http://docs.mongodb.org/manual/core/replication-introduction/

Primary节点接收客户端所有的写操作,整个副本集只会有一个primary节点。MongoDB副本集提供严格的一致性。主节点将所有的操作写入一个叫oplog的capped collection(这个collection的大小一般为磁盘剩余空间的5%,不同的系统可能不一样,详见http://docs.mongodb.org/manual/core/replica-set-oplog/)中,secondary节点通过复制oplog并执行oplog中的所有操作,因为对oplog的执行是幂等的,所以secondary节点上的数据可以保持和primary节点一样,当然这有一个“追赶”(catch up)的过程,会存在一定的落后(Lag)有时候因为网络延迟或宕机导致从节点永远赶不上主节点,这时候需要采取人为的干预了(后面会说到Resyncing Member of Replica Set)。

默认所有的读操作也是走的primary节点,当然客户端可以选择从secondary节点进行读取操作以减小主节点的压力(后面会对读写分离有详细说明)。

各个节点之间是通过心跳机制来维持联系的,当主节点无法和集群中其他节点通信超过10秒,集群会从剩下的节点中选择一个secondary作为primary,这个过程叫做选举(election),每个secondary节点都有一个优先级priority来参与投票(也可以有没有投票权的secondary节点),priority值越大就越优先成为主节点(所有的节点可以有相同的优先级,默认值都是1)。election的策略不仅仅就是根据priority值来,会综合很多其他的因素。总之MongoDB通过heartbeat和election机制实现了自动的Failover:

副本集要求参与选举投票(vote)的节点数为奇数,这很容易理解。当我们实际环境中因为机器等原因限制只有两个(或偶数)的节点,这时为了实现Automatic Failover引入另一类节点:仲裁者(arbiter),仲裁者只参与投票不拥有实际的数据,因此它对物理资源要求不严格。

上面已经提到了primary,secondary和arbiter,整个MongoDB副本集群中除了这三种类型的节点还有其他几种:

  • Secondary-Only:这种类型的节点和secondary节点一样拥有数据副本,但是它们在任何情形下都成为不了primary节点。
  • Hidden:这种类型的节点对客户端程序来说是不可见的,同样也不能成为primary节点,但是Hidden成员能够参与选举投票。
  • Delayed:这种类型的成员通过人为的设置,可以指定一个时间来延迟从primary节点同步数据。Delayed成员的作用在于帮助集群从一些误操作中恢复,比如管理员误删除了某个集合。不至于迅速扩散到整个集群中。因此Delayed节点必须不能成为primary节点(priority为0)并且是Hidden的。
  • Non-Voting:这就是上面提到了没有选举权的secondary节点。这种类型的节点一般当集群节点数超过12才会需要。

简单副本集的搭建

官方建议的最小化的副本集为Three Member Sets,一个primary和两个secondary。我们先就搭建一个这样的测试环境。

首先建立三个数据目录和日志目录:

.    cd /usr/local/mongodb-2.4./data/
. mkdir -p rs0- rs0- rs0-
. cd /usr/local/mongodb-2.4./log/
. mkdir -p rs0- rs0- rs0-

然后我们以守护进程的方式启动三个mongod进程,端口分别是37017,37018和37019:

.    ./bin/mongod --fork --dbpath data/rs0-/ --logpath log/rs0-/rs0-.log --rest --replSet rs0 --port
. ./bin/mongod --fork --dbpath data/rs0-/ --logpath log/rs0-/rs0-.log --rest --replSet rs0 --port
. ./bin/mongod --fork --dbpath data/rs0-/ --logpath log/rs0-/rs0-.log --rest --replSet rs0 --port

跟启普通的mongod进程基本相同,不同的跟了--replSet选项,rs0是该副本集的名称。--rest参数是打开web监控页面,比如我们这里监听37017端口,则打开http://192.168.129.129:38017/(mongod端口加上1000)就可以看到这个mongodb数据库进程的信息,如果是副本集就能查看整个副本集的相关信息。

然后我们用mongo shell连上端口为37017的mongod:

.    ./bin/mongo -port
. use admin

接着我们需要初始化一个Replica Set:首先创建一个副本集配置对象:

.    rsconf={
. "_id" : "rs0",
. "members" : [
. {
. "_id" : ,
. "host" : "192.168.129.129:37017"
. }
. ]
. }

然后用rs.initiate()进程初始化:

.    rs.initiate(rsconf)
. {
. "info" : "Config now saved locally. Should come online in about a minute.",
. "ok" :
. }

添加成员

通过rs.add()将另外两个mongod添加到副本集当中:

.    rs0:PRIMARY> rs.add("192.168.129.129:37018")
. { "ok" : }
. rs0:PRIMARY> rs.add("192.168.129.129:37019")
. { "ok" : }

会发现37017这个mongod默认就是PRIMARY节点了。通过rs.conf()可以查看集群的配置情况:

.    rs0:PRIMARY> rs.conf()
. {
. "_id" : "rs0",
. "version" : ,
. "members" : [
. {
. "_id" : ,
. "host" : "192.168.129.129:37017"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:37018"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:37019"
. }
. ]
. }

修改priority

副本中所有的secondary节点都有一个priority值,为任意的浮点数,该值越大则该节点在election中越优先成为primary节点,通过下面的命令修改该值,目前primary节点是37017:

.    rs0:PRIMARY> cfg=rs.conf()
. {
. "_id" : "rs0",
. "version" : ,
. "members" : [
. {
. "_id" : ,
. "host" : "192.168.129.129:37017"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:37018"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:37019"
. }
. ]
. }

我们将37019节点的priority设置成2:

.    rs0:PRIMARY> cfg=rs.conf()
. cfg.members[].priority =
.

这里数组的索引2其实跟rs.conf查看到的每个成员的_id不是一回事。

然后执行:

.    rs0:PRIMARY> rs.reconfig(cfg)

注意:执行rs.reconfig()命令会强制整个副本集集群进行一次election,这样priority较高的37019节点便成了primary节点:

整个election过程需要一点时间,在这之间整个集群的所有节点都是secondary

添加仲裁者

首先需要启动一个作为arbiter的mongod进程,端口40000,虽然arbiter不持有数据但是仍然需要数据目录来保存一些配置信息:

.    mkdir –p data/rs0-arb
. mkdir –p log/rs0-arb
. ./bin/mongod --fork --dbpath data/rs0-arb/ --logpath log/rs0-arb/rs0-arb.log --rest --replSet rs0 --port

然后进入primary节点执行下面命令添加arbiter:

.    rs0:PRIMARY> rs.addArb("192.168.129.129:40000")
. { "ok" : }
. rs0:PRIMARY> rs.conf()
. {
. "_id" : "rs0",
. "version" : ,
. "members" : [
. {
. "_id" : ,
. "host" : "192.168.129.129:37017"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:37018"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:37019"
. },
. {
. "_id" : ,
. "host" : "192.168.129.129:40000",
. "arbiterOnly" : true
. }
. ]
. }

仲裁节点的作用

通过实际测试发现,当整个副本集集群中达到50%的节点(包括仲裁节点)不可用的时候,剩下的节点只能成为secondary节点,整个集群只能读不能写。比如集群中有1个primary节点,2个secondary节点,加1个arbit节点时:当两个secondary节点挂掉了,那么剩下的原来的primary节点也只能降级为secondary节点;当集群中有1个primary节点,1个secondary节点和1个arbit节点,这时即使primary节点挂了,剩下的secondary节点也会自动成为primary节点。因为仲裁节点不复制数据,因此利用仲裁节点可以实现最少的机器开销达到两个节点热备的效果。

移除成员

移除一个成员使用rs.remove()命令:

.    rs0:PRIMARY> rs.remove("192.168.129.129:37019")
. Sun Aug ::22.754 DBClientCursor::init call() failed
. Sun Aug ::22.874 JavaScript execution failed: Error: error doing query: failed at src/mongo/shell/query.js:L78
. Sun Aug ::22.909 trying reconnect to 127.0.0.1:
. Sun Aug ::22.909 reconnect 127.0.0.1: ok

需要注意的是:虽然有错误信息,但其实操作已经成功了。参看官方的文档:

每改变一次集群的配置,副本集的version都会加1。我们重新将37019加入rs0这次提示信息有点不一样:

.    rs0:PRIMARY> rs.add("192.168.129.129:37019")
. { "down" : [ "192.168.129.129:37019" ], "ok" : }

我们打开http://192.168.129.129:38017/可以看到整个副本集的相关信息:

至此一个简单的用于开发和测试Three Member Sets就搭建完成了。下节会在此基础上做一些简单的数据测试。

MongoDB副本集学习(一):概述和环境搭建的更多相关文章

  1. MongoDB副本集学习(三):性能和优化相关

    Read Preferences/读写分离 有时候为了考虑应用程序的性能或响应性,为了提高读取操作的吞吐率,一个常见的措施就是进行读写分离,MongoDB副本集对读写分离的支持是通过Read Pref ...

  2. MongoDB副本集学习(二):基本测试与应用

    简单副本集测试 这一节主要对上一节搭建的副本集做一些简单的测试. 我们首先进入primary节点(37017),并向test.test集合里插入10W条数据: . rs0:PRIMARY> ;i ...

  3. MongoDB副本集(一主两从)读写分离、故障转移功能环境部署记录

    Mongodb是一种非关系数据库(NoSQL),非关系型数据库的产生就是为了解决大数据量.高扩展性.高性能.灵活数据模型.高可用性.MongoDB官方已经不建议使用主从模式了,替代方案是采用副本集的模 ...

  4. MongoDB副本集(一主一备+仲裁)环境部署-运维操作记录

    MongoDB复制集是一个带有故障转移的主从集群.是从现有的主从模式演变而来,增加了自动故障转移和节点成员自动恢复.MongoDB复制集模式中没有固定的主结点,在启动后,多个服务节点间将自动选举产生一 ...

  5. Mongodb副本集+分片集群环境部署记录

    前面详细介绍了mongodb的副本集和分片的原理,这里就不赘述了.下面记录Mongodb副本集+分片集群环境部署过程: MongoDB Sharding Cluster,需要三种角色: Shard S ...

  6. Mongodb副本集+分片集群环境部署

    前面详细介绍了mongodb的副本集和分片的原理,这里就不赘述了.下面记录Mongodb副本集+分片集群环境部署过程: MongoDB Sharding Cluster,需要三种角色: Shard S ...

  7. NoSQL数据库Mongodb副本集架构(Replica Set)高可用部署

    NoSQL数据库Mongodb副本集架构(Replica Set)高可用部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. MongoDB 是一个基于分布式文件存储的数据库.由 C ...

  8. MongoDB和Java(6):Spring Data整合MongoDB副本集、分片集群

    最近花了一些时间学习了下MongoDB数据库,感觉还是比较全面系统的,涉及了软件安装.客户端操作.安全认证.副本集和分布式集群搭建,以及使用Spring Data连接MongoDB进行数据操作,收获很 ...

  9. MongoDB 副本集的原理、搭建、应用

    概念: 在了解了这篇文章之后,可以进行该篇文章的说明和测试.MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组 ...

随机推荐

  1. 41.Android之图片放大缩小学习

    生活中经常会用到图片放大和缩小,今天简单学习下. 思路:1.添加一个操作图片放大和缩小类;  2. 布局文件中引用这个自定义控件;  3. 主Activity一些修改. 代码如下: 增加图片操作类: ...

  2. BZOJ-1625 宝石手镯 01背包(傻逼题)

    傻逼题,懒得打,复制蛋蛋的.. 1625: [Usaco2007 Dec]宝石手镯 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 1076 Solved: ...

  3. 洛谷P1656 炸铁路

    题目描述 因为某国被某红色政权残酷的高压暴力统治.美国派出将军uim,对该国进行战略性措施,以解救涂炭的生灵. 该国有n个城市,这些城市以铁路相连.任意两个城市都可以通过铁路直接或者间接到达. uim ...

  4. Bzoj3893 [Usaco2014 Dec]Cow Jog

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 302  Solved: 157 Description The cows are out exerci ...

  5. 在纯HTML的静态网页中添加一段统计网页访问量的JAVA Script代码?

    如何在网站上进行流量统计呢,可以找第三方服务网站去注册,但也可以在网站上直接添加代码,只需将以下代码copy到你的网页中,复制到</body>之前就可以啦!是不是很简单啊! <scr ...

  6. JAVA-封装

    1.什么是封装? 顾名思义,封装就是装起来,圈起来的意思,用于类与对象中来讲,就是在一个类中把对象拥有的属性和隐藏信息(条件)进行封装,不允许外部程序直接访问,而必须要通过该类提供的方法来实现对隐藏信 ...

  7. CSS3系列二(媒体支持、文字与字体相关样式、盒相关样式)

    CSS3媒体支持 在css3中允许我们在不改变内容的情况下,在样式中选择一种页面的布局以精确的适应不同的设备,从而改善用户体验 可以利用meta标签在页面中指定浏览器在处理本页面时按照多少像素的窗口宽 ...

  8. Servlet之Filter详细讲解

    Filter,过滤器,顾名思义,即是对数据等的过滤,预处理过程.为什么要引入过滤器呢?在平常访问网站的时候,有时候发一些敏感的信息,发出后显示时 就会将敏感信息用*等字符替代,这就是用过滤器对信息进行 ...

  9. UrlConnection连接和Socket连接的区别

    关于UrlConnection连接和Socket连接的区别,只知道其中的原理如下: 抽象一点的说,Socket只是一个供上层调用的抽象接口,隐躲了传输层协议的细节. urlconnection 基于H ...

  10. sql数据库常用语句总结

    1.增加字段     alter table docdsp     add dspcodechar(200)2.删除字段     ALTER TABLE table_NAME DROP COLUMNc ...