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

来源:互联网 发布:linux输入命令 编辑:程序博客网 时间:2024/05/12 19:38

在NoSQL数据库中,复制功能是作为一项最基本的特性存在的。复制为数据提供了冗余,提高了数据可用性。在多台服务器拥有相同数据集的情况下,复制可以防止因一台机器故障导致数据丢失。如果拥有相同数据集的服务器分布在不同的数据中心,复制还可以提供灾难备份功能。另外,我们还可以将复制功能用于备份、报表、读写分离场景。
MongoDB作为NoSQL数据库的典型代表,既提供简单的主从式复制,也提供具有灵活的复制集功能。MongoDB复制集具有数据冗余、分离读压力、自动恢复、维护简单、支持灾难恢复等特性。

 

一、基本概念

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

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

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

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

 

二、复制集常见架构

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

 

 

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

 

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

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

在考虑成员的分布时,为灾难时能够恢复数据,至少应将一个成员分布在另一个数据中心。当复制集成员分布在多个数据中心时,应保证大多数参与选举主机的成员在一个物理数据中心,以防止网络通讯故障。

 

三、搭建复制集

 

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
}

 

 

 

 

 

 

原创粉丝点击