nosql第9周实验副本集,初始化vba库40040出错副本集时为什么一直出错不成功

Mongodb副本集实现及读写分离
在前面的文章&Mongodb的主从模式搭建实例&中,我们对如何搭建一个主从结构的Mongodb服务器环境进行了简单的介绍。但是对于主从结构,Mongodb官方并不推荐我们使用了,可能是因为主从模式存在以下两个缺点:
(1)主节点不可用之后,无法自动切换到从节点,无法确保业务访问的不间断性;
(2)所有的读写操作都是对主节点的,造成主节点的访问压力较大;
因此,Mongodb为我们提供了另外一种推荐的使用方法,那就是使用副本集ReplicaSets。在这篇文章中简单描述一下副本集是如何实现的,又是如何解决以上两个问题的。
首先我们先来搭建一个副本集(因为没有那么多服务器机器,这里采用在一台机器上,使用不同的端口号模拟不同的机器上的Mongodb实例)。
第一步:我们在本机的和3333三个端口上启动三个不同的Mongodb实例;
mongod --port 1111 --dbpath F:/mongodb1/data/db --logpath F:/mongodb1/data/log/mongodb.log --replSet test --logappend
mongod --port 2222 --dbpath F:/mongodb2/data/db --logpath F:/mongodb2/data/log/mongodb.log --replSet test --logappend
mongod --port 3333 --dbpath F:/mongodb3/data/db --logpath F:/mongodb3/data/log/mongodb.log --replSet test --logappend
在这里我们启动了三个Mongodb实例,并指定了相应的数据目录和日志目录,需要说明的是,这里需要使用--replSet说明该Mongodb实例是副本集中的节点,而该副本集的名称是test。
第二步:登录到一个实例上,编写指令,将三个不同的Mongodb实例结合在一起形成一个完整的副本集;
config_test={&_id&:&test&,members:[
{_id:0,host:&127.0.0.1:1111&},
{_id:1,host:&127.0.0.1:2222&},
{_id:2,host:&127.0.0.1:3333&},
这里,members中可以包含多个值,这里列举的就是刚才启动的三个Mongodb实例,并且通过_id字段给副本集起了名字test。
第三步:通过执行下面的命令初始化副本集。
rs.initiate(config_test);
这里使用上面的配置初始化Mongodb副本集。
通过上面的三步,便可以简单的搭建起一个由三个Mongodb实例构成的名称为test的副本集了。如果想查看副本集的状态,可以使用rs.status()命令来进行查看。
副本集现在搭建起来了,那么这个副本集能不能解决我们上面主从模式的两个问题呢?
我们首先从第一个问题开始看,我们将1111端口的Mongodb服务器给关闭,然后我们使用rs.status()命令来查看下,如下所示:
在这里,需要对返回信息中的个别字段进行简单说明,health表示副本集中该节点是否正常,0表示不正常,1表示正常;state表示节点的身份,0表示非主节点,1表示主节点;stateStr用于对节点身份进行字符描述,PRIMARY表示主节点,SECONDARY表示副节点;name是副本集节点的ip和端口信息,等等。
从返回包信息中,可以看到关闭1111端口后,在副本集节点的状态中该节点是不可达的,重新选取产生的主节点是3333端口上启动的Mongodb实例,至于选取的流程在后面的文章中将会讲到,这里简单讲一点,当主节点挂掉之后,其他节点可以发起选举行为,只要在选举过程中某个节点得到副本集节点数一半以上的选票并且没有节点投反对票,那么该节点就可以成为主节点。
在1111端口上的Mongodb实例挂掉之后,3333成为了新的主节点,可以实现自动切换,因此解决了第一个问题。
至于第二个问题,那就是主节点负责所有的读写操作造成主节点压力较大,那么在副本集中如何解决这个问题了呢?正常情况下,我们在中访问副本集是这样的,如下所示:
public class TestMongoDBReplSet {
public static void main(String[] args)
List addresses = new ArrayList();
ServerAddress address1 = new ServerAddress(&127.0.0.1& , 1111);
ServerAddress address2 = new ServerAddress(&127.0.0.1& , 2222);
ServerAddress address3 = new ServerAddress(&127.0.0.1& , 3333);
addresses.add(address1);
addresses.add(address2);
addresses.add(address3);
MongoClient client = new MongoClient(addresses);
DB db = client.getDB( &test&);
DBCollection coll = db.getCollection( &test&);
BasicDBObject object = new BasicDBObject();
object.append( &key1&, &value1& );
coll.insert(object);
DBCursor dbCursor = coll.find();
while (dbCursor.hasNext()) {
DBObject dbObject = dbCursor.next();
System. out.println(dbObject.toString());
} catch (Exception e) {
e.printStackTrace();
但是,上面不能做到在副本集中读写压力分散,其实在代码层面,我们可以设置再访问副本集的时候只从副节点上读取数据。副本集读写分离结构如下图所示:
为了在副本集上实现读写分离,我们需要实现以下两步:
(1)在副本节点上设置setSlaveOk;
(2)代码层面,在读操作过程中设置从副本节点读取数据,如下所示:
public class TestMongoDBReplSet {
public static void main(String[] args)
List addresses = new ArrayList();
ServerAddress address1 = new ServerAddress(&127.0.0.1& , 1111);
ServerAddress address2 = new ServerAddress(&127.0.0.1& , 2222);
ServerAddress address3 = new ServerAddress(&127.0.0.1& , 3333);
addresses.add(address1);
addresses.add(address2);
addresses.add(address3);
MongoClient client = new MongoClient(addresses);
DB db = client.getDB( &test&);
DBCollection coll = db.getCollection( &test&);
BasicDBObject object = new BasicDBObject();
object.append( &key1&, &value1& );
ReadPreference preference = ReadPreference.secondary();
DBObject dbObject = coll.findOne(object, null , preference);
System. out .println(dbObject);
} catch (Exception e) {
e.printStackTrace();
读参数除了secondary以外,还有其他几个参数可以使用,他们的含义分别如下所示:
primary:默认参数,只从主节点上进行读取操作;
primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据&旧&。
secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。
这样便实现了在副本集上的读写分离了,也就解决了文章最上面所说的第二个问题了。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'Read Preferences/读写分离
有时候为了考虑应用程序的性能或响应性,为了提高读取操作的吞吐率,一个常见的措施就是进行读写分离,MongoDB副本集对读写分离的支持是通过Read Preferences特性进行支持的,这个特性非常复杂和灵活。以下几种应用场景可能会考虑对副本集进行读写分离:
1)操作不影响前端应用程序,比如备份或者报表;
2)在一个物理上分布的副本集群中,为了减少应用程序的延迟,可能会优先选择离应用程序更近的secondary节点而不是远在千里之外机房的主节点;
3)故障发生时候能够提供一个优雅的降级。副本集primary节点宕机后再选出新的primary节点这段时间内(10秒或更长时间)能够依然响应客户端应用的读请求;
4)应用能够容忍一定程度的数据不一致性。
Read References:
应用程序驱动通过read reference来设定如何对副本集进行读取操作,默认的,客户端驱动所有的读操作都是直接访问primary节点的,从而保证了数据的严格一致性。
但有时为了缓解主节点的压力,我们可能需要直接从secondary节点读取,只需要保证最终一致性就可以了。
MongoDB 2.0之后支持五种的read preference模式:
primary:默认,只从主节点上进行读取操作;
primaryPreferred:在绝大部分的情形都是从主节点上读取数据的,只有当主节点不可用的时候,比如在进行failover的10秒或更长的时间内会从secondary节点读取数据。
警告:2.2版本之前的MongoDB对Read Preference支持的还不完全,如果客户端驱动采用primaryPreferred实际上读取操作都会被路由到secondary节点。
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据&旧&。
secondaryPreferred:优先从secondary节点进行读取操作;
nearest:既有可能从primary,也有可能从secondary节点读取,这个决策是通过一个叫member selection过程处理的。
MongoDB允许在不同的粒度上指定这些模式:连接、数据库、集合甚至单次的操作。不同语言的驱动基本都支持这些粒度。
oplog是一种特殊的capped collection,用来滚动的保存MongoDB中所有数据操作的日志。副本集中secondary节点异步的从primary节点同步oplog然后重新执行它记录的操作,以此达到了数据同步的作用。这就要求oplog必须是幂等的,也就是重复执行相同的oplog记录得到的数据结构必须是相同的。
事实上副本集中所有节点之间都相互进行heartbeat来维持联系,任何节点都能从其它节点复制oplog。
capped collection是MongoDB中一种提供高性能插入、读取和删除操作的固定大小集合。当集合被填满的时候,新的插入的文档会覆盖老的文档。因为oplog是capped collection所以指定它的大小非常重要。如果太小那么老的文档很快就被覆盖了,那么宕机的节点就很容易出现无法同步数据的结果,但也不是越大越好,MongoDB在初始化副本集的时候都会有一个默认的oplog大小:
在64位的Linux,Solaris,FreeBSD以及Windows系统上,MongoDB会分配磁盘剩余空间的5%作为oplog的大小,如果这部分小于1GB则分配1GB的空间。
在64的OS X系统上会分配183MB。
在32位的系统上则只分配48MB。
首先生产环境使用MongoDB毫无疑问必须的是64为操作系统。其次大多数情况下默认的大小是比较适合的。举个例子,如果oplog大小为空闲磁盘的5%,它在24H内能被填满,也就是说secondary节点可以停止复制oplog达24H后仍然能够catch up上primary节点。而且通常的MongoDB副本集的操作量要比这低得多。
oplog数据结构:
oplog的数据结构如下所示:
{ ts : ..., op: ..., ns: ..., o: ... o2: ...& }
ts: 8字节的时间戳,由4字节unix&timestamp&+&4字节自增计数表示。这个值很重要,在选举(如master宕机时)新primary时,会选择ts最大的那个secondary作为新primary。
op:1字节的操作类型,例如i表示insert,d表示delete。
ns:操作所在的namespace。
o:操作所对应的document,即当前操作的内容(比如更新操作时要更新的的字段和值)
o2:&在执行更新操作时的where条件,仅限于update时才有该属性
其中op有以下几个值:
"i":&insert
"u":&update
"d":&delete
"c":&db&cmd
"db":声明当前数据库&(其中ns&被设置成为=&数据库名称+&'.')
"n":&&no&op,即空操作,其会定期执行以确保时效性
注:关于oplog有两个常见的错误timestamp error和duplicate error,参看这里:
查看oplog大小:
通过&可以查看副本集节点的oplog状态:
rs0:PRIMARY& db.printReplicationInfo()
configured oplog size:
log length start to end: 12.714secs (0hrs)
oplog first event time:
Sat Jan 17 1970 06:22:38 GMT+0800 (CST)
oplog last event time:
Sat Jan 17 1970 06:22:51 GMT+0800 (CST)
Sat Aug 17 2013 18:02:12 GMT+0800 (CST)
以我之前搭建的副本集为例,oplog的大小是1793MB,其中持有的数据时间区间只有12秒。
修改oplog大小:
可以在启动mongod的时候指定--oplogSize,单位MB:
./bin/mongod --fork --dbpath data/rs0-0/ --logpath log/rs0-0/rs0-0.log --rest --replSet rs0 --oplogSize 500 --port 37017
但有的时候我们可能需要修改现有副本集的oplog大小。这个本人非常不推荐,官网有详细的教程,这里我就不赘述了,可以看这里:。
在现有的副本集中修改oplog的大小是相当麻烦的而且影响副本集性能,因此我们最好是预先根据应用的情况评估好oplog的大小:如果应用程序是读多写少,那么默认的大小已经足够了。如果你的应用下面几种场景很多可能考虑需要更大的oplog:
在同一个时刻更新多个文档:oplog为了维持幂等性必须将mutil-updates翻译成一个个独立的操作,这会用去大量的oplog空间,但数据库中的数据量却没有相对称的增加。
多文档同时更新从1.1.3就有的特性,在mongo shell执行类似如下的命令,第四个参数必须制定为true:
db.test.update({foo: "bar"}, {$set: {test: "success!"}}, false, true);
在插入时同时删除相同大小数据:和上面的结果一样在数据量没有增加的情况下却消耗了大量的oplog空间。
大量的In-Place更新操作:In-Place更新是指更新文档中原有的部分,但并不增加文档的大小。
上面三点总结起来就是消耗了大量的oplog但是数据量却没有等量的增加。
前面已经提到MongoDB副本集中secondary节点是通过oplog来同步primary节点数据的,那具体的细节是怎么样的?在说数据如何同步之间先介绍一下replication lag,因为存在数据同步那必然存在一定程度的落后。这个问题对于整个MongoDB副本集的部署是至关重要的。
rs0:PRIMARY& db.printSlaveReplicationInfo()
192.168.129.129:37019
syncedTo: Thu Aug 15 2013 20:59:45 GMT+0800 (CST)
= 172971 secs ago (48.05hrs)
192.168.129.129:37020
syncedTo: Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
secs ago (382429.04hrs)
当前集群的状况是,37017端口是primary节点,3是secondary节点,其中37020已经宕机,可以看到37019同步数据是在两天前(因为这两天我没有对副本集有任何数据操作),而宕机的节点显示的同步时间是一个很早时间点。
现在重新启动37020后再执行命令:
rs0:PRIMARY& db.printSlaveReplicationInfo()
192.168.129.129:37019
syncedTo: Thu Aug 15 2013 20:59:45 GMT+0800 (CST)
= 175566 secs ago (48.77hrs)
192.168.129.129:37020
syncedTo: Thu Aug 15 2013 20:59:45 GMT+0800 (CST)
= 175566 secs ago (48.77hrs)
可以看到两个secondary节点的同步时间是一致的,我们向集群中插入几条数据后再执行db.printSlaveReplicationInfo():
rs0:PRIMARY& db.test.insert({"name":"zhanjindong","age":23})
rs0:PRIMARY& db.printSlaveReplicationInfo()
192.168.129.129:37019
syncedTo: Sat Aug 17 2013 21:48:31 GMT+0800 (CST)
= 6 secs ago (0hrs)
192.168.129.129:37020
syncedTo: Sat Aug 17 2013 21:48:31 GMT+0800 (CST)
= 6 secs ago (0hrs)
可以看到很快就引发了primary和secondary之间的数据同步操作。
&滞后&是不可避免的,需要做的就是尽可能减小这种滞后,主要涉及到以下几点:
网络延迟:这是所有分布式系统都存在的问题。我们能做的就是尽可能减小副本集节点之间的网络延迟。
磁盘吞吐量:secondary节点上数据刷入磁盘的速度比primary节点上慢的话会导致secondary节点很难跟上primary节点的节奏。
并发:并发大的情况下,primary节点上的一些耗时操作会阻塞secondary节点的复制操作,导致复制操作跟不上主节点的写入负荷。解决方法是通过设置操作的write concern(参看这里:)默认的副本集中写入操作只关心primary节点,但是可以指定写入操作同时传播到其他secondary节点,代价就是严重影响集群的并发性。
注意:而且这里还存在一个问题如果,如果写入操作关心的某个节点宕机了,那么操作将会一直被阻塞直到节点恢复。
适当的write concern:我们为了提高集群写操作的吞吐量经常会将writer concern设置为,这导致primary节点的写操作很快而secondary节点复制操作跟不上。解决方法和第三点是类似的就是在性能和一致性之间做权衡。
副本集中数据同步有两个阶段。
初始化(initial sync):这个过程发生在当副本集中创建一个新的数据库或其中某个节点刚从宕机中恢复,或者向副本集中添加新的成员的时候,默认的,副本集中的节点会从离它最近的节点复制oplog来同步数据,这个最近的节点可以是primary也可以是拥有最新oplog副本的secondary节点。这可以防止两个secondary节点之间相互进行同步操作。
复制(replication):在初始化后这个操作会一直持续的进行着,以保持各个secondary节点之间的数据同步。
在MongoDB2.0以后的版本中,一旦初始化中确定了一个同步的目标节点后,只有当和同步节点之间的连接断开或连接过程中产生异常才可能会导致同步目标的变动,并且具有就近原则。考虑两种场景:
1) 有两个secondary节点在一个机房,primary在另外一个机房。假设几乎在同一时间启动这三个实例(之前都没有数据和oplog),那么两个secondary节点应该都是从primary节点同步数据,因为他们之前见都不会拥有比对方更新的oplog。如果重启其中一个secondary,那么它的同步目标将会变成另一个secondary,因为就近原则。
2) 如果有一个primary和一个secondary分别在不同的机房,那么在之前secondary所在的机房中向副本集中新加一个节点时,那么新节点必然是从原先的那个secondary节点同步数据的。
在2.2版本以后,数据同步增加了一些额外的行为:
1) secondary节点只有当集群中没有其他选择的时候才会从delayed节点同步数据;
2) secondary节点绝不会从hidden节点同步数据;
3) 当一个节点新加入副本集中会有一个recovering过程,在这段时间内secondary不会进行数据同步操作;
4) 当一个节点从另一个节点同步数据的时候,需要保证两个节点的local.system.replset.members[n].buildIndexes值是一样的,要不都是false,要不都是true。
注:buildIndexes指定副本集中成员是否可以创建索引(某些情况下比如没有读操作或者为了提高写性能可以省略索引的创建)。当然即使该值为false,MongoDB还是可以在_id上创建索引以为复制操作服务。
重新数据同步:
有时当secondary节点落后太多无法追赶上primary节点的时候,这时候可能需要考虑重新同步数据(Resync data)。
有两种方法一种是指定一个空的目录重新启动落后的节点,这很简单,但是数据量大的情况下回花费很长的时间。另一种方法是基于另一个节点的数据作为&种子&进行重新同步,关于这两种方法在后面向一个现有副本集中添加成员一节会有详细说明。
在以下几种情景发生的时候,副本集通过&选举&来决定副本集中的primary节点:
当第一次初始化一个副本集的时候;
primary几点steps down的时候,出现这种情况可能是因为执行了replSetStepDown命令,或者是集群中出现了更适合当primary的节点,比如当primary节点和集群中其他大部分节点无法通信的时候,当primary steps down的时候,它会关闭所有客户端的连接。
当集群中一个secondary节点无法和primary节点建立连接的时候也会导致一次election发生。
一次failover。
执行rs.conf()命令。
在一次选举中包括hidden节点、仲裁者甚至正处于recovering状态的节点都具有&投票权&。默认配置中所有参与选举的节点具有相等的权利,当然在一些特定情况下,应明确的指定某些secondary会优先成为primary,比如一个远在千里之外异地机房的节点就不应该成为primary节点,选举的权重通过设置priority来调节,默认该值都是1,在前面简单副本集的搭建中已经介绍过了如何修改该值。
集群中任何一个节点都可以否决选举,即使它是non-voting member:
如果发起选举的节点不具有选举权(priority为0的成员);
发起选举的节点数据落后太多;
发起选举的节点的priority值比集群中其他某一个节点的小;
如果当前的primary节点比发起选举的节点拥有更新或同等新的数据(也就&optime&值相等或更大)。
当前的primary节点会否决,如果它拥有比发起选举的节点更新或相同新的数据。
首先获取最多选票的成员(实际上要超过半数)才会成为primary节点,这也说明了为什么当有两个节点的集群中primary节点宕机后,剩下的只能成为secondary,当primary宕掉,此时副本集只剩下一个secondary,它只有1票,不超过总节点数的半数,它不会选举自己为primary。
要想更详细的了解选举细节,参看这篇源码分析的文章:
最近太忙,有时间再整理。
阅读(...) 评论()& MongoDB 副本集自动复制 Replica Set
MongoDB 副本集自动复制 Replica Set
,MongoDB做为NoSQL数据库,最近几年持续升温,越来越多的企业都开始尝试用MongoDB代替原有Database做一些事情。MongoDB也在集群,分片,复制上也有相当不错的的表现。我通过将做各种MongoDB的部署实验进行介绍。
关于作者:
张丹(Conan), 程序员Java,R,PHP,Javascript
weibo:@Conan_Z
转载请注明:
第二篇 MongoDB 副本集自动复制 Replica Set,分为7个部分
初始化文件目录
启动副本集 Replica Set
模拟 PRIMARY失败,SECONDARY自动切换
修复失败节点
恢复失败节点,补充到SECONDARY
删除一个Replica Set节点
新增加一个Replica Set节点
系统环境介绍:
Ubuntu 12.04. LTS 64bit Server
初始化文件目录
/home/conan/dbs
~ mkdir node1 node2 node3
drwxrwxr-x 2 conan conan 4096 May 31 14:21 node1
drwxrwxr-x 2 conan conan 4096 May 31 14:21 node2
drwxrwxr-x 2 conan conan 4096 May 31 14:21 node3
启动副本集 Replica Set
启动node1,node2,node3
mongod --dbpath /home/conan/dbs/node1 --port 10001 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node1.log
mongod --dbpath /home/conan/dbs/node2 --port 10002 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node2.log
mongod --dbpath /home/conan/dbs/node3 --port 10003 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node3.log
副本集初始化
~ mongo localhost:10001
MongoDB shell version: 2.4.3
connecting to: localhost:10001/test
& rs.initiate({_id:"blort",members:[
{_id:1,host:"localhost:10001"},
{_id:2,host:"localhost:10002"},
{_id:3,host:"localhost:10003"},
"info" : "Config now saved locally. Should come online in about a minute.",
查看日志信息:node1变选为PRIMARY,node2,node3分别是2个SECONDARY
Fri May 31 14:26:44.728 [conn2] ******
Fri May 31 14:26:44.728 [conn2] replSet info saving a newer config version to local.system.replset
Fri May 31 14:26:44.741 [conn2] replSet saveConfigLocally done
Fri May 31 14:26:44.741 [conn2] replSet replSetInitiate config now saved locally. Should come online in about a minute.
Fri May 31 14:26:44.741 [conn2] command admin.$cmd command: { replSetInitiate: { _id: "blort", members: [ { _id: 1.0, host: "localhost:10001" }, { _id: 2.0, host: "localhost:10002" }, { _id: 3.0, host: "localhost:10003" } ] } } ntoreturn:1 keyUpdates:0 locks(micros) W:646741 reslen:112 652ms
Fri May 31 14:26:53.682 [rsStart] replSet I am localhost:10001
Fri May 31 14:26:53.682 [rsStart] replSet STARTUP2
Fri May 31 14:26:53.683 [rsHealthPoll] replSet member localhost:10002 is up
Fri May 31 14:26:53.684 [rsHealthPoll] replSet member localhost:10003 is up
Fri May 31 14:26:54.285 [initandlisten] connection accepted from 127.0.0.1:4 connections now open)
Fri May 31 14:26:54.683 [rsSync] replSet SECONDARY
用mongo客户端查看设置
~ mongo localhost:10001
MongoDB shell version: 2.4.3
connecting to: localhost:10001/test
blort:PRIMARY& rs.status()
"set" : "blort",
"date" : ISODate("T06:34:12Z"),
"myState" : 1,
"members" : [
"_id" : 1,
"name" : "localhost:10001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 659,
"optime" : {
"optimeDate" : ISODate("T06:26:44Z"),
"self" : true
"_id" : 2,
"name" : "localhost:10002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 439,
"optime" : {
"optimeDate" : ISODate("T06:26:44Z"),
"lastHeartbeat" : ISODate("T06:34:11Z"),
"lastHeartbeatRecv" : ISODate("T00:00:00Z"),
"pingMs" : 0,
"syncingTo" : "localhost:10001"
"_id" : 3,
"name" : "localhost:10003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 439,
"optime" : {
"optimeDate" : ISODate("T06:26:44Z"),
"lastHeartbeat" : ISODate("T06:34:11Z"),
"lastHeartbeatRecv" : ISODate("T00:00:00Z"),
"pingMs" : 0,
"syncingTo" : "localhost:10001"
~ mongo localhost:10002
MongoDB shell version: 2.4.3
connecting to: localhost:10002/test
blort:SECONDARY&
在primary插入数据:
~ mongo localhost:10001
MongoDB shell version: 2.4.3
connecting to: localhost:10001/test
blort:PRIMARY& show dbs
local 1.078125GB
blort:PRIMARY& use fensme
switched to db fensme
blort:PRIMARY& db.user.insert({uid:10001})
blort:PRIMARY& db.user.find()
{ “_id” : ObjectId(&#df62a8c8”), “uid” : 10001 }
连接node2,SECONDARY查询数据
~ mongo localhost:10002
MongoDB shell version: 2.4.3
connecting to: localhost:10002/test
blort:SECONDARY& show dbs
fensme 0.203125GB
local 1.078125GB
blort:SECONDARY& use fensme
switched to db fensme
blort:SECONDARY& show collections
Fri May 31 14:39:22.276 JavaScript execution failed: error: { “$err” : “not master and slaveOk=false”, “code” : 13435 } at src/mongo/shell/query.js:L128
blort:SECONDARY& db.user.find()
error: { “$err” : “not master and slaveOk=false”, “code” : 13435 }
提示是不是master/slave的结构,SECONDARY不许允查询。
模拟 PRIMARY失败,SECONDARY自动切换
ps -aux|grep mongod
2.1 08 ? Sl 14:23 0:05 mongod --dbpath /home/conan/dbs/node1 --port 10001 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node1.log
2.2 60 ? Sl 14:24 0:04 mongod --dbpath /home/conan/dbs/node2 --port 10002 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node2.log
2.2 48 ? Sl 14:24 0:04 mongod --dbpath /home/conan/dbs/node3 --port 10003 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node3.log
kill -9 5110
ps -aux|grep mongod
2.2 96 ? Sl 14:24 0:04 mongod --dbpath /home/conan/dbs/node2 --port 10002 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node2.log
2.2 96 ? Sl 14:24 0:04 mongod --dbpath /home/conan/dbs/node3 --port 10003 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node3.log
连接node2,SECONDARY查询节点重新选举
~ mongo localhost:10002
MongoDB shell version: 2.4.3
connecting to: localhost:10002/test
blort:SECONDARY& rs.status()
“set” : “blort”,
“date” : ISODate(&#-31T06:42:51Z”),
“myState” : 2,
“syncingTo” : “localhost:1;,
“members” : [
“_id” : 1,
“name” : “localhost:1;,
“health” : 0,
“state” : 8,
“stateStr” : “(not reachable/healthy)”,
“uptime” : 0,
“optime” : {
“t” : ,
“i” : 1
“optimeDate” : ISODate(&#-31T06:38:00Z”),
“lastHeartbeat” : ISODate(&#-31T06:42:51Z”),
“lastHeartbeatRecv” : ISODate(&#-01T00:00:00Z”),
“pingMs” : 0
“_id” : 2,
“name” : “localhost:1;,
“health” : 1,
“state” : 2,
“stateStr” : “SECONDARY”,
“uptime” : 1088,
“optime” : {
“t” : ,
“i” : 1
“optimeDate” : ISODate(&#-31T06:38:00Z”),
“errmsg” : “syncing to: localhost:1;,
“self” : true
“_id” : 3,
“name” : “localhost:1;,
“health” : 1,
“state” : 1,
“stateStr” : “PRIMARY”,
“uptime” : 946,
“optime” : {
“t” : ,
“i” : 1
“optimeDate” : ISODate(&#-31T06:38:00Z”),
“lastHeartbeat” : ISODate(&#-31T06:42:51Z”),
“lastHeartbeatRecv” : ISODate(&#-01T00:00:00Z”),
“pingMs” : 0,
“syncingTo” : “localhost:1;
“ok” : 1
查看结果:
localhost:10001 : not reachable/healthy
localhost:10002: SECONDARY
localhost:10003: PRIMARY
连接node3, localhost:10003查看数据
mongo localhost:10003
MongoDB shell version: 2.4.3
connecting to: localhost:10003/test
blort:PRIMARY& show dbs
fensme 0.203125GB
local 1.078125GB
blort:PRIMARY& use fensme
switched to db fensme
blort:PRIMARY& show collections
system.indexes
blort:PRIMARY& db.user.find()
{ “_id” : ObjectId(&#df62a8c8”), “uid” : 10001 }
node1失效后,node3被选为了PRIMARY,数据在node3可以查询到。
修复失败节点
直接重启node1,启动失败:
~ mongod --dbpath /home/conan/dbs/node1 --port 10001 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node1_restart.log
MongoDB starting : pid=8544 port=10001 dbpath=/home/conan/dbs/node1 64-bit host=u1
Fri May 31 14:49:37.280 [initandlisten] db version v2.4.3
Fri May 31 14:49:37.280 [initandlisten] git version: feea03e91ecbf
Fri May 31 14:49:37.280 [initandlisten] build info: Linux ip-10-2-29-40 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST
BOOST_LIB_VERSION=1_49
Fri May 31 14:49:37.280 [initandlisten] allocator: tcmalloc
Fri May 31 14:49:37.280 [initandlisten] options: { dbpath: "/home/conan/dbs/node1", fork: true, logpath: "/home/conan/dbs/node1_restart.log", nojournal: true, port: 10001, replSet: "blort" }
**************
Unclean shutdown detected.
Please visit http://dochub.mongodb.org/core/repair for recovery instructions.
*************
Fri May 31 14:49:37.281 [initandlisten] exception in initAndListen: 12596 old lock file, terminating
Fri May 31 14:49:37.281 dbexit:
Fri May 31 14:49:37.281 [initandlisten] shutdown: going to close listening sockets...
Fri May 31 14:49:37.281 [initandlisten] shutdown: going to flush diaglog...
Fri May 31 14:49:37.281 [initandlisten] shutdown: going to close sockets...
Fri May 31 14:49:37.281 [initandlisten] shutdown: waiting for fs preallocator...
Fri May 31 14:49:37.281 [initandlisten] shutdown: closing all files...
Fri May 31 14:49:37.281 [initandlisten] closeAllFiles() finished
Fri May 31 14:49:37.281 dbexit: really exiting now
5. 恢复失败节点,补充到SECONDARY
mkdir /home/conan/dbs/repair/
mongod --dbpath /home/conan/dbs/node1 --port 10001 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node1_restart_repair.log --repairpath /home/conan/dbs/repair/
about to fork child process, waiting until server is ready for connections.
forked process: 13736
all output going to: /home/conan/dbs/node1_restart_repair.log
child process started successfully, parent exiting
修复成功。
重新连接node1,查看节点状态
~ mongo localhost:10001
MongoDB shell version: 2.4.3
connecting to: localhost:10001/test
blort:SECONDARY& rs.status()
“set” : “blort”,
“date” : ISODate(&#-31T07:04:34Z”),
“myState” : 2,
“syncingTo” : “localhost:1;,
“members” : [
“_id” : 1,
“name” : “localhost:1;,
“health” : 1,
“state” : 2,
“stateStr” : “SECONDARY”,
“uptime” : 74,
“optime” : {
“t” : ,
“i” : 1
“optimeDate” : ISODate(&#-31T06:38:00Z”),
“errmsg” : “syncing to: localhost:1;,
“self” : true
“_id” : 2,
“name” : “localhost:1;,
“health” : 1,
“state” : 2,
“stateStr” : “SECONDARY”,
“uptime” : 74,
“optime” : {
“t” : ,
“i” : 1
“optimeDate” : ISODate(&#-31T06:38:00Z”),
“lastHeartbeat” : ISODate(&#-31T07:04:33Z”),
“lastHeartbeatRecv” : ISODate(&#-01T00:00:00Z”),
“pingMs” : 0,
“syncingTo” : “localhost:1;
“_id” : 3,
“name” : “localhost:1;,
“health” : 1,
“state” : 1,
“stateStr” : “PRIMARY”,
“uptime” : 74,
“optime” : {
“t” : ,
“i” : 1
“optimeDate” : ISODate(&#-31T06:38:00Z”),
“lastHeartbeat” : ISODate(&#-31T07:04:33Z”),
“lastHeartbeatRecv” : ISODate(&#-31T07:04:34Z”),
“pingMs” : 0
“ok” : 1
查看结果:
localhost:10001: SECONDARY
localhost:10002: SECONDARY
localhost:10003: PRIMARY
node1节点已恢复。
6. 删除一个Replica Set节点
blort:PRIMARY& rs.remove("localhost:10001")
Fri May 31 15:40:21.977 DBClientCursor::init call() failed
Fri May 31 15:40:21.978 JavaScript execution failed: Error: error doing query: failed at src/mongo/shell/query.js:L78
Fri May 31 15:40:21.979 trying reconnect to localhost:10003
Fri May 31 15:40:21.980 reconnect localhost:10003 ok
rs.status()
"set" : "blort",
"date" : ISODate("T07:40:23Z"),
"myState" : 1,
"members" : [
"_id" : 2,
"name" : "localhost:10002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 2,
"optime" : {
"optimeDate" : ISODate("T07:40:21Z"),
"lastHeartbeat" : ISODate("T07:40:21Z"),
"lastHeartbeatRecv" : ISODate("T07:40:23Z"),
"pingMs" : 2,
"lastHeartbeatMessage" : "db exception in producer: 10278 dbclient error communicating with server: localhost:10003",
"syncingTo" : "localhost:10003"
"_id" : 3,
"name" : "localhost:10003",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 4539,
"optime" : {
"optimeDate" : ISODate("T07:40:21Z"),
"self" : true
清空node1,数据文件。
rm -rf node1*
drwxrwxr-x 3 conan conan 4096 May 31 14:38 node2/
-rw-rw-r-- 1 conan conan 509277 May 31 15:42 node2.log
drwxrwxr-x 3 conan conan 4096 May 31 14:38 node3/
-rw-rw-r-- 1 conan conan 515918 May 31 15:42 node3.log
drwxrwxr-x 2 conan conan 4096 May 31 15:02 repair/
7. 新增加一个Replica Set节点
mkdir node1
mongod --dbpath /home/conan/dbs/node1 --port 10001 --replSet blort --nojournal --fork --logpath /home/conan/dbs/node1.log
about to fork child process, waiting until server is ready for connections.
forked process: 15145
all output going to: /home/conan/dbs/node1.log
child process started successfully, parent exiting
新增加的node1节点
rs.add("localhost:10001")
blort:PRIMARY& rs.status()
"set" : "blort",
"date" : ISODate("T07:48:28Z"),
"myState" : 1,
"members" : [
"_id" : 2,
"name" : "localhost:10002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 487,
"optime" : {
"optimeDate" : ISODate("T07:47:47Z"),
"lastHeartbeat" : ISODate("T07:48:26Z"),
"lastHeartbeatRecv" : ISODate("T07:48:27Z"),
"pingMs" : 0,
"syncingTo" : "localhost:10003"
"_id" : 3,
"name" : "localhost:10003",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 5024,
"optime" : {
"optimeDate" : ISODate("T07:47:47Z"),
"self" : true
"_id" : 4,
"name" : "localhost:10001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 41,
"optime" : {
"optimeDate" : ISODate("T07:47:47Z"),
"lastHeartbeat" : ISODate("T07:48:27Z"),
"lastHeartbeatRecv" : ISODate("T00:00:00Z"),
"pingMs" : 0,
"syncingTo" : "localhost:10003"
增加的localhost:10001, 为SECONDARY.
实验完成!
Replica Set 做为FailOver的实现,还是很不错的。
转载请注明:
This entry was posted in ,
Designed by

我要回帖

更多关于 绘图引擎初始化出错 的文章

 

随机推荐