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

MongoDB复制集简介(一)--初步认识

2013-10-12 10:57 344 查看
在NoSQL数据库中,复制功能是作为一项最基本的特性存在的。复制为数据提供了冗余,提高了数据可用性。在多台服务器拥有相同数据集的情况下,复制可以防止因一台机器故障导致数据丢失。如果拥有相同数据集的服务器分布在不同的数据中心,复制还可以提供灾难备份功能。另外,我们还可以将复制功能用于备份、报表、读写分离场景。

MongoDB作为NoSQL数据库的典型代表,既提供简单的主从式复制,也提供具有灵活的复制集功能。MongoDB复制集具有数据冗余、分离读压力、自动恢复、维护简单、支持灾难恢复等特性。

 

一、基本概念

主机:从客户端接收所有的写请求,同时在local数据库中oplog.rs文档集中记录所有数据变化日志。一个复制集只能有一个主机。

从机:复制主机的日志并应用到本机数据集上,以保证数据与主机同步。当主机不可用时,复制集自动选择一个从机做主机。

仲裁者:不存储数据,不能成为主机,仅仅用于有偶数个复制集,也仅仅在投票产生主机时发挥作用。

隐藏成员:具有主机数据的完整复制,但是对客户端不可见的成员。隐藏成员优先级为0,不能成为主机,但可以参与投票。

 

二、复制集常见架构

复制集的架构将直接影响复制集的容量和性能。一个标准的复制集一般为三个成员,具有数据冗余和容错能力,如下图所示。

 



 

当然,我们也可以搭建一个只有一个主机、一个从机、一个仲裁者的架构,如下图所示。



 

考虑复制集中成员个数时,一般需要考虑以下几个因素:

成员个数应为奇数,奇数个成员能够保证复制集选出一个主机。如果成员个数为偶数,应需要增加一个仲裁器。
需要考虑容错性。容错性是指复制集中最多允许几个成员不可用,但是这时复制集依然能够选出主机。拥有不同数量复制集中具有不同的容错性。

成员个数选举主机需要的个数容错性
321
431
532
642
为读压力准备专门成员
在考虑成员的分布时,为灾难时能够恢复数据,至少应将一个成员分布在另一个数据中心。当复制集成员分布在多个数据中心时,应保证大多数参与选举主机的成员在一个物理数据中心,以防止网络通讯故障。

 

三、搭建复制集

 

1、启动三个节点,复制集名称为test

 

在shell下执行下面命令启动三个mongod进程

./mongod --dbpath /mongodb/data/db_1 --port 27117 --replSet test --logpath /mongodb/log/mongod_1.log  --fork

./mongod --dbpath /mongodb/data/db_2 --port 27217 --replSet test --logpath /mongodb/log/mongod_2.log  --fork

./mongod --dbpath /mongodb/data/db_3 --port 27317 --replSet test --logpath /mongodb/log/mongod_3.log  --fork

使用命令ps -ef|grep mongodb,得到以下结果,确保三个mongod进程已经启动。

root      2311     1 91 05:42 ?        00:02:37 ./mongod --dbpath /mongodb/data/db_1 --port 27117 --replSet test --logpath /mongodb/log/mongod_1.log --fork

root      3244     1 39 05:44 ?        00:00:08 ./mongod --dbpath /mongodb/data/db_2 --port 27217 --replSet test --logpath /mongodb/log/mongod_2.log --fork

root      3368     1 26 05:44 ?        00:00:02 ./mongod --dbpath /mongodb/data/db_3 --port 27317 --replSet test --logpath /mongodb/log/mongod_3.log --fork

2、 初始化复制集

 

使用mongo shell工具连接到端口号27117的mongod:

[root@localhost bin]# ./mongo --port  27117

MongoDB shell version: 2.5.2

connecting to: 127.0.0.1:27117/test

>

执行rs.initiate()初始化复制集:

> rs.initiate()

{

        "info2" : "no configuration explicitly specified -- making one",

        "me" : "localhost.localdomain:27117",

        "info" : "Config now saved locally.  Should come online in about a minute.",

        "ok" : 1

}

test:SECONDARY>

 

我们注意到执行完rs.initiate后,shell的提示符发生了变化,表示当前shell连接的是test的从机。使用rs.conf()查看复制集当前配置:

 test:SECONDARY> rs.conf()

{

        "_id" : "test",

        "version" : 1,

        "members" : [

                {

                        "_id" : 0,

                        "host" : "localhost.localdomain:27117"

                }

        ]

}

根据rs.conf()的输出看出,当前复制集合只有一个成员,我们使用命令将其他两个成员增加进入复制集:

test:PRIMARY> rs.add("localhost.localdomain:27217")

{ "ok" : 1 }

test:PRIMARY> rs.add("localhost.localdomain:27317")

{ "ok" : 1 }

test:PRIMARY>

 

我们再使用rs.conf()查看一下复制集的配置,可以看到复制集合的三个成员都已经加入。

test:PRIMARY> rs.conf()

{

        "_id" : "test",

        "version" : 3,

        "members" : [

                {

                        "_id" : 0,

                        "host" : "localhost.localdomain:27117"

                },

                {

                        "_id" : 1,

                        "host" : "localhost.localdomain:27217"

                },

                {

                        "_id" : 2,

                        "host" : "localhost.localdomain:27317"

                }

        ]

}

我们使用rs.status()查看一下复制集的状态,可以观察到端口号为27117的mongod进程为主机,其他两个为从机。

test:PRIMARY> rs.status()

{

        "set" : "test",

        "date" : ISODate("2013-10-12T10:16:57Z"),

        "myState" : 1,

        "members" : [

                {

                        "_id" : 0,

                        "name" : "localhost.localdomain:27117",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 1053,

                        "optime" : Timestamp(1381572862, 1),

                        "optimeDate" : ISODate("2013-10-12T10:14:22Z"),

                        "self" : true

                },

                {

                        "_id" : 1,

                        "name" : "localhost.localdomain:27217",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 167,

                        "optime" : Timestamp(1381572862, 1),

                        "optimeDate" : ISODate("2013-10-12T10:14:22Z"),

                        "lastHeartbeat" : ISODate("2013-10-12T10:16:56Z"),

                        "lastHeartbeatRecv" : ISODate("2013-10-12T10:16:56Z"),

                        "pingMs" : 0,

                        "syncingTo" : "localhost.localdomain:27117"

                },

                {

                        "_id" : 2,

                        "name" : "localhost.localdomain:27317",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 155,

                        "optime" : Timestamp(1381572862, 1),

                        "optimeDate" : ISODate("2013-10-12T10:14:22Z"),

                        "lastHeartbeat" : ISODate("2013-10-12T10:16:57Z"),

                        "lastHeartbeatRecv" : ISODate("2013-10-12T10:16:56Z"),

                        "pingMs" : 0,

                        "syncingTo" : "localhost.localdomain:27117"

                }

        ],

        "ok" : 1

}

 

 3、手工控制切换主机

 

当我们给不同的复制成员设置上优先级后,mongodb复制集将按照优先级的大小顺序选择主机,优先级数字越大,表示越有可能成为主机。我们将端口号为27317的对应成员的优先级设置为3,端口号为27217对应的成员优先级设置为2,端口号27117的对应成员优先级设置为1。

cfg = rs.conf()

cfg.members[0].priority = 1

cfg.members[1].priority = 2

cfg.members[2].priority = 3

rs.reconfig(cfg)

 

执行rs.status()查看复制集优先级配置变化后的复制集状态,发现端口号为27317的对应成员变为主机了,实现了按照优先级控制主机切换。

rs.status()

{

        "set" : "test",

        "date" : ISODate("2013-10-12T10:38:02Z"),

        "myState" : 2,

        "syncingTo" : "localhost.localdomain:27317",

        "members" : [

                {

                        "_id" : 0,

                        "name" : "localhost.localdomain:27117",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 2318,

                        "optime" : Timestamp(1381574271, 1),

                        "optimeDate" : ISODate("2013-10-12T10:37:51Z"),

                        "errmsg" : "syncing to: localhost.localdomain:27317",

                        "self" : true

                },

                {

                        "_id" : 1,

                        "name" : "localhost.localdomain:27217",

                        "health" : 1,

                        "state" : 2,

                        "stateStr" : "SECONDARY",

                        "uptime" : 11,

                        "optime" : Timestamp(1381574271, 1),

                        "optimeDate" : ISODate("2013-10-12T10:37:51Z"),

                        "lastHeartbeat" : ISODate("2013-10-12T10:38:01Z"),

                        "lastHeartbeatRecv" : ISODate("2013-10-12T10:38:01Z"),

                        "pingMs" : 1,

                        "lastHeartbeatMessage" : "syncing to: localhost.localdomain:27317",

                        "syncingTo" : "localhost.localdomain:27317"

                },

                {

                        "_id" : 2,

                        "name" : "localhost.localdomain:27317",

                        "health" : 1,

                        "state" : 1,

                        "stateStr" : "PRIMARY",

                        "uptime" : 10,

                        "optime" : Timestamp(1381574271, 1),

                        "optimeDate" : ISODate("2013-10-12T10:37:51Z"),

                        "lastHeartbeat" : ISODate("2013-10-12T10:38:02Z"),

                        "lastHeartbeatRecv" : ISODate("2013-10-12T10:38:01Z"),

                        "pingMs" : 0

                }

        ],

        "ok" : 1

}

 

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息