mongoDB的读书笔记(04)_【Replica】(05)_初探Replica set副本集的搭建 By Test模式

Replica set Deployment On Test Mode

为啥是测试模式

标题写的比较含糊。配置副本集就配置吧,干嘛还要在一个测试Mode下呢。
其实是这样的,配置一个副本集集群按说应该在几个不同的节点上面配置,但是,一般情况下我们可能会首先在一个模拟环境下去试验,跑一些程序跑一些设置后,再在真正的多节点环境上铺开。所以我们首先先在一个简单的测试模式的基础上去感受一下mongoDB的Replica是个虾米东东。

实战

先絮叨絮叨操作系统

当下,windows系统基本上快从开发OS的第一阵营跌落了。很多的开源产品直接不提供windows的编译命令,比如Flume从2.0开始已经告别windows。而Hadoop从2.X开始也对windows的支持基本上say goodbye了。我去客户现场出差的时候米国和印度的哥们发过来的所有架构和代码都是基于Ubuntu的,我们这边用windows一个个去实验。。。结果啥都打不开。然后就用Cygwin,结果还是很多新版的东西根本不能支持,本想是否可以自己编译windows的命令包,我靠,除非搞研究行了,累死了。最后想想,人家的原生就是Linux你为啥非得移植到windows啊,乖乖的也扔掉windows完了。后来,我以windows要衰败的名义去Ginza还买了一台15寸的mac,嘿嘿嘿,然后没几天就用一个chown命令搞死了机器,当晚重装了mac的系统,觉得这系统太不健壮了,重装居然耗费了一宿也太tm夸张了吧。。。现在mac还躺在柜子里,啥时候想玩swift的时候再拿出来吧。
那,说到这个,mongoDB对于windows的命令支持真的是很不错yeah,业内良心,不打压寡头。呵呵。所以基本上现在我的操作都是windows的命令操作。

在一台机器上创建模拟5个节点

mongoDB的命令有shell命令,还有被封装的javascript命令,当然,自己也可以封装各种各样的javascript,这个没有尽头的东西,只能靠学用结合了。我的例子是权威指南书中的一个例子,当然,如果按照书中直接跑可能会有疑问,通过我的操作干掉这些疑问吧。

进入非db连接模式

C:\MongoDB\bin>mongo --nodb

这个命令不已连接或者创建DB为目的,而进入mongoDB的shell编辑环境

C:\MongoDB\bin>mongo --nodb
MongoDB shell version: 2.6.5
>

可以看出,我用的是2.6.5的版本,现在最新的是2.6.6?还是2.6.7来着。。。嗯。说到这里,提个题外话,之前我还在mongoDB的jira系统给mongo提了个bug,结果人家回复说,你的系统不支持Linux命令。唉,丢人丢大了。哈哈。

建立5个节点的test script

C:\MongoDB\bin>mongo --nodb
MongoDB shell version: 2.6.5
> rep = new ReplSetTest({"nodes":5})

输入rep = new ReplSetTest({“nodes”:5}) 这个命令后

        "removePartitionDelay" : function (from, to, bidirectional) {
    this.addPartitionDelay(from, to, 0, bidirectional);
},
        "addOneWayPartitionDelay" : function (from, to, delay) {
    this.addPartitionDelay(from, to, delay, false);
},
        "removeOneWayPartitionDelay" : function (from, to) {
    this.addPartitionDelay(from, to, 0, false);
}
}
>

如果出现了以下错误的话,请先做成一个C:\data\db 的文件夹,至于为什么下一节06的时候再说。

ERROR: dbpath (\data\db) does not exist.

屏幕像发疯了一样进行了一堆操作,这个都是在执行创建5个节点这个script后执行的一些后台操作,不用管啥意思了,除非你有兴趣看看屏幕这堆javascript代码

启动所有的节点

        "removePartitionDelay" : function (from, to, bidirectional) {
    this.addPartitionDelay(from, to, 0, bidirectional);
},
        "addOneWayPartitionDelay" : function (from, to, delay) {
    this.addPartitionDelay(from, to, delay, false);
},
        "removeOneWayPartitionDelay" : function (from, to) {
    this.addPartitionDelay(from, to, 0, false);
}
}
> rep.startSet()

然后输入rep.startSet()
图1
技术分享
屏幕不是一直固定成上面这个样子哦,你会发现屏幕一直在滚啊滚啊滚啊滚( ̄Q ̄)╯
如下面这样
图2
技术分享

我第一次玩的时候觉得,完蛋了出错了,但是是完全按照书上执行的啊,还得执行一个什么initiate呢啊,屏幕这么滚怎么执行啊。
其实是这样的,这个时候其实相当于你在5台机器上面每个机器都大开了一个mongod的实例,但是这5个实例都属于无组织无纪律的状态,他们之间也不知道互相的关系,所以,下一步需要把他们整合到一起,配置成一个可以管理的集群Replica。

配置节点

是酱紫的。这个Test模式呢,是使用已经Wrapped的script进行启动的,每个节点的端口号是从31000开始依次分配的(配置真正replica的时候port和ip之类都可以指定),所以,我们的hostname就是:

localhost:31000
localhost:31001
localhost:31002
localhost:31003
localhost:31004

那么,如果要配置节点呢,就要从上门的某一个节点入手即可,用一个节点来配置真个集群。说到这里可能会有疑问,这5个节点为啥就知道他们5个是一个Replica的集群呢?mongoDB的mongod启动命令中是有一个–replSet 的参数选项的,如果你希望把几个节点设置成一组集群那么就把这个参数设置成一样的,比如–replSet rs001,那么所有被设置成rs001的节点在下面的操作中就都会被召唤到一起。我们使用的test模式系统自动写死给这个集群的–replSet定义为:“TestReplSet”。在图1中可以找到”replSet”:”TestReplSet”这个定义。

进入一个节点

选择使用31000这个节点配置咯,注意,新开一个命令窗口,刚才那个狂滚动的窗口不要管咯~:

C:\MongoDB\bin>mongo localhost:31000

输入后

C:\MongoDB\bin>mongo localhost:31000
MongoDB shell version: 2.6.5
connecting to: localhost:31000/test
Server has startup warnings:
2015-03-03T22:46:07.930+0800 ** WARNING: --rest is specified without --httpinter
face,
2015-03-03T22:46:07.930+0800 **          enabling http interface
>

OK,已经进入和mongo的shell模式。

配置Replica的config

下一步干啥呢,下一步要定义一个config

config = {_id: ‘testReplSet‘, members: [ 
{_id: 0, host: ‘localhost:31000‘},   
{_id: 1, host: ‘localhost:31001‘}, 
{_id: 2, host: ‘localhost:31002‘},
{_id: 3, host: ‘localhost:31003‘},
{_id: 4, host: ‘localhost:31004‘}] }

第一行的_id意思是我们要指定配置的Replica哪一个。
然后跟随的就是5个节点,按照_id + host的模式。
其中,host:’localhost:31000’ 中前面是hostname,后面是端口号,如果不是hostname是ip地址的话也没有问题,看网络的设置了。
把这个config写入到mongo的shell环境中

> config = {_id: ‘testReplSet‘, members: [
... {_id: 0, host: ‘localhost:31000‘},
... {_id: 1, host: ‘localhost:31001‘},
... {_id: 2, host: ‘localhost:31002‘},
... {_id: 3, host: ‘localhost:31003‘},
... {_id: 4, host: ‘localhost:31004‘}] }
{
        "_id" : "testReplSet",
        "members" : [
                {
                        "_id" : 0,
                        "host" : "localhost:31000"
                },
                {
                        "_id" : 1,
                        "host" : "localhost:31001"
                },
                {
                        "_id" : 2,
                        "host" : "localhost:31002"
                },
                {
                        "_id" : 3,
                        "host" : "localhost:31003"
                },
                {
                        "_id" : 4,
                        "host" : "localhost:31004"
                }
        ]
}
>

config这个属性已经被定义了
然后,把config运用到Replica中即可

进行初始化
> rs.initiate(config)

执行上面这个命令,把我们的config进行初始化

> rs.initiate(config)
{
        "info" : "Config now saved locally.  Should come online in about a minut
e.",
        "ok" : 1
}
>

info中的内容告诉我们已经成功保存,要同步需要一会会,并且返回ok。

check心跳和log

这个时候看看我们刚才那个狂滚动的窗口,貌似不那么疯狂了,好像平息下来了
技术分享
仔细看看上面的log,其实可以看出,这个是每个节点互相在ping的一些log,也就是节点已经配置ok了,在心跳哦????~

查看Replia的详细
> rs.isMaster()

回到刚才我们localhost:31000的操作命令行输入上面的命令后

> rs.isMaster()
{
        "setName" : "testReplSet",
        "setVersion" : 1,
        "ismaster" : true,
        "secondary" : false,
        "hosts" : [
                "localhost:31000",
                "localhost:31004",
                "localhost:31003",
                "localhost:31002",
                "localhost:31001"
        ],
        "primary" : "localhost:31000",
        "me" : "localhost:31000",
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : ISODate("2015-03-03T15:13:44.230Z"),
        "maxWireVersion" : 2,
        "minWireVersion" : 0,
        "ok" : 1
}
testReplSet:PRIMARY>

解释几个重要的属性。
“ismaster” : true 表示此节点是master节点

“hosts” : [
“localhost:31000”,
“localhost:31004”,
“localhost:31003”,
“localhost:31002”,
“localhost:31001”
], 表示这个Replica集群都有什么host

“primary” : “localhost:31000” 现在集群中的Primary是谁。
因为当前的31000这个几点被选举成为了Primary,那么命令行也相应的变为了下面酱:

testReplSet:PRIMARY>

到这里为止,一个简单的Test演示模式的Replica宣告初步搭建完毕。但是没完哦。

查看Secondary Replia的详细

我们进入一个Secondary的节点再来看看

C:\MongoDB\bin>mongo localhost:31001
MongoDB shell version: 2.6.5
connecting to: localhost:31001/test
Server has startup warnings:
2015-03-03T22:46:08.477+0800 ** WARNING: --rest is specified without --httpinter
face,
2015-03-03T22:46:08.477+0800 **          enabling http interface
testReplSet:SECONDARY>

OK,从命令行的最后一行可以看出这个节点貌似是Secondary咯。
执行以下rs.isMaster()后

testReplSet:SECONDARY> rs.isMaster()
{
        "setName" : "testReplSet",
        "setVersion" : 1,
        "ismaster" : false,
        "secondary" : true,
        "hosts" : [
                "localhost:31001",
                "localhost:31004",
                "localhost:31003",
                "localhost:31002",
                "localhost:31000"
        ],
        "primary" : "localhost:31000",
        "me" : "localhost:31001",
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : ISODate("2015-03-03T15:19:26.231Z"),
        "maxWireVersion" : 2,
        "minWireVersion" : 0,
        "ok" : 1
}
testReplSet:SECONDARY>

嗯,的确没有问题。

写数据实验

OK,貌似一个最最简单的Replica已经起来了,那么我们写入个数据试试看?
首先进入localhost:31000,因为写入必须要从Primary写入,我们不采用外部程序driver的写入方式,直接在命令行写命令写入。

Primary写入
C:\MongoDB\bin>mongo localhost:31000
MongoDB shell version: 2.6.5
connecting to: localhost:31000/test
Server has startup warnings:
2015-03-03T22:46:07.930+0800 ** WARNING: --rest is specified without --httpinter
face,
2015-03-03T22:46:07.930+0800 **          enabling http interface
testReplSet:PRIMARY> use testrepl //←①
switched to db testrepl //←②
testReplSet:PRIMARY> show collections //←③
testReplSet:PRIMARY>

①:这个地方采用了一个shell命令,use xxx ,其中xxx指的是mongoDB的db,类似与rdb中的schema。
②:mongoDB表示已经切换到这个db
③:这个show collections的命令是显示出这个db下面的所有的collection,类似与rdb的所有的schema下面的所有的表的意思,因为还没有任何的collection,所以没有显示结果

然后我们采用最基本的mongoDB的写入命令写入一个”testrepl”:”yes”的document,collection的名字也定义为:testrepl(注意,collection和db不是同一个东东,名字可以不一样,我这里懒了。。。)

testReplSet:PRIMARY> db.testrepl.insert({"testrepl":"yes"})
WriteResult({ "nInserted" : 1 })
testReplSet:PRIMARY>

上面执行完毕,之前说过,mongo现在的写操作都是自带Write Concern的,所以返回了一个WriteResult表示写入成功(一个返回1代表)。

testReplSet:PRIMARY> db.testrepl.insert({"testrepl":"yes"})
WriteResult({ "nInserted" : 1 })
testReplSet:PRIMARY> show collections
system.indexes
testrepl
testReplSet:PRIMARY>

再执行一下show collections可以看到已经有了testrepl这个collection,还有自动产生的system.indexes。
我们来检索一下数据:

testReplSet:PRIMARY> db.testrepl.insert({"testrepl":"yes"})
WriteResult({ "nInserted" : 1 })
testReplSet:PRIMARY> show collections
system.indexes
testrepl
testReplSet:PRIMARY> db.testrepl.find()
{ "_id" : ObjectId("54f5d3164cfd2afe862669f8"), "testrepl" : "yes" }
testReplSet:PRIMARY>

可以看到被插入的数据已经可以检索出来。

Secondary查看

那么,Primary写入了,集群中的其他Secondary应该也同步了吧?赶紧去看看。。

C:\MongoDB\bin>mongo localhost:31001
MongoDB shell version: 2.6.5
connecting to: localhost:31001/test
Server has startup warnings:
2015-03-03T22:46:08.477+0800 ** WARNING: --rest is specified without --httpinter
face,
2015-03-03T22:46:08.477+0800 **          enabling http interface
testReplSet:SECONDARY> db //←①
test db //←②
testReplSet:SECONDARY> use testrepl
switched to db testrepl
testReplSet:SECONDARY> show collections
2015-03-03T23:35:00.810+0800 error: { "$err" : "not master and slaveOk=false", "
code" : 13435 } at src/mongo/shell/query.js:131 db //←③
testReplSet:SECONDARY> db.testrepl.find() db //←④
error: { "$err" : "not master and slaveOk=false", "code" : 13435 } db //←⑤
testReplSet:SECONDARY>

嗯。。貌似不对啊。
①:用db命令先看看有什么db
②:只有一个自动生成的test,没有我们在Primary中新做的testrepl啊
③:调用show collection 果然也没有我们的collection
④:直接调用find
⑤:出来的错误信息。。。

其实直接看⑤这个信息的话,指明这个节点既不是master(Primary)且slaveOk=false。
原因在于,这个节点是一个Secondary,对于Secondary节点来说,如果想开始同步Primary的数据,或者说想让这个节点开始工作,首先需要设定一个命令:

testReplSet:SECONDARY> rs.slaveOk()

使用上面这个命令,告诉集群这个Secondary节点已经OK,可以参与工作啦啦啦。
然后我们再看看:

testReplSet:SECONDARY> rs.slaveOk()
testReplSet:SECONDARY> show collections
system.indexes
testrepl
testReplSet:SECONDARY> db.testrepl.find()
{ "_id" : ObjectId("54f5d3164cfd2afe862669f8"), "testrepl" : "yes" }
testReplSet:SECONDARY>

执行完rs.slaveOk()后,马上collection的testrepl就被同步过来,并且find也可以直接有数据返回了。
至此,一个基本的Replica才算配置完毕,其余的3个节点也都需要都设置一下rs.slaveOk()后方可同步Primary的数据了。在这以后,Primary进行写操作,所有的Secondary节点就都可以进行同步了。

つづく???

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。