学习MongoDB--(9-4):复制(副本集)

先说一下副本集的概念:有自动故障恢复功能的主从结构!前面讲到的主从结构和副本集最大的区别就是:副本集没有固定的“主节点”,整个集群结构会动态选举出一个“主节点”,当其不能工作了,则会动态变更到其他节点。副本集对其节点又特殊的称呼:活跃节点(“主节点”)和 备份节点(“从节点”)。

副本集最美妙的地方是其自动化,在当前活跃节点因故障停止时,备份节点会自动升级为活跃节点!以维持系统的正常运行。

搭建副本集的过程为:我们首先需要为副本集起一个名称(试验名称为“yy”),然后使用选项--replSet来启动副本集的第一个服务:

C:\Documents and Settings\liuxjd>mongod --dbpath e:\mdbserver1 --port 10000 --lo
gpath e:\mdblog1\log.log --replSet yy/localhost:10001
all output going to: e:\mdblog1\log.log
上述我们通过--replSet yy/localhost:10001(这里有一点尤为注意:副本集名称yy后的分隔符必须为“/”,否则后面注册后失败!),这是指定了该副本集yy中的另外一个MongoDB服务,其监听的端口为本机的10001,但此时我们还并未启动该服务!

我们看一下第一个节点日志此时的输出包含如下语句:

Sun Sep 02 10:48:51 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)
Sun Sep 02 10:48:51 [rsStart] replSet info you may need to run replSetInitiate -- rs.initiate() in the shell -- if that is not already done

我们开始启动副本集的第二个服务:

C:\Documents and Settings\liuxjd>mongod --dbpath e:\mdbserver2 --port 10001 --lo
gpath e:\mdblog2\log.log --replSet yy/localhost:10000
all output going to: e:\mdblog2\log.log
我们还可以启动副本集的第三台服务,下面两种方式均可:
C:\Documents and Settings\liuxjd>mongod --dbpath e:\mdbserver3 --port 10002 --lo
gpath e:\mdblog3\log.log --replSet yy/localhost:10000
all output going to: e:\mdblog3\log.log

C:\Documents and Settings\liuxjd>mongod --dbpath e:\mdbserver3 --port 10002 --lo
gpath e:\mdblog3\log.log --replSet yy/localhost:10000,localhost:10001
all output going to: e:\mdblog3\log.log
即在启动第三台服务时,可以只指定副本集中的一个服务,或同时指定。副本集的一个特性为:自动检测,你仅指定单台服务器后,MongoDB会自动搜索并连接到同一副本集的其余的节点。
从第一台服务的启动日志中,我们看到,集合中local.system.replset中没有任何配置信息,并且副本集还需要在shell中运行replSetInitiate命令来进行初始化。我们通过其中任意一台服务器(试验中我们使用的第二台)运行命令初始化(注意该命令需要在admin数据库下执行),该集合中会自动插入配置信息,并且配置信息会在副本集内各个服务器间被复制:
C:\Documents and Settings\liuxjd>mongo localhost:10001
MongoDB shell version: 2.0.7
connecting to: localhost:10001/test
> use admin
switched to db admin
> db.runCommand({"replSetInitiate" : {
... "_id" : "yy",
... "members" : [
...     {
...         "_id" :1,
...         "host": "localhost:10000"
...     },
...     {
...         "_id" : 2,
...         "host" : "localhost:10001"
...     },
...     {
...         "_id" : 3,
...         "host" : "localhost:10002"
...     }
... ]}});
{
        "info" : "Config now saved locally.  Should come online in about a minut
e.",
        "ok" : 1
}
>
运行这个命令的文档稍显复杂,我们解释一下各个键的含义:

1》 “_id” : “yy”, 这个键指明了副本集的名称

2》 “members” :[...], 这个键指明服务器列表,我们以后还可以往副本集中加入服务器

3》 “_id” : N, 内嵌文档的键,用于唯一标示副本集中的某一台服务器

4》 “host”:host address, 指明服务器的主机和端口号 

通过命令初始化完毕后,我们查看日志:

Sun Sep 02 10:52:11 [rsHealthPoll] replSet member localhost:10001 is now in state PRIMARY
Sun Sep 02 10:52:25 [rsHealthPoll] replSet member localhost:10000 is now in state SECONDARY
Sun Sep 02 10:52:17 [rsHealthPoll] replSet member localhost:10002 is now in state SECONDARY

第二个服务器成为了活跃节点,其余两个服务器均是备份节点。备份节点会抽取活跃节点的oplog,来维持和活跃节点的数据同步!备份节点无法直接通过客户端进行些操作,查询操作也要指明“slaveok”(在shell进行查询,主从结构的从节点可以通过shell客户端查询数据,而副本集控制严一些,其备份节点通过shell客户端也无法直接查询,提示需要设置slaveok选项,但shell查询好像没有提供这种支持!

初始化会将副本集的信息保存在副本集各个节点的数据库local的集合system.replset中,我们到第一台服务器上查看一下该集合:

SECONDARY> use local;
switched to db local
SECONDARY> db.system.replset.find();
{ "_id" : "yy", "version" : 1, "members" : [    {       "_id" : 1,      "host" :
 "localhost:10000" },   {       "_id" : 2,      "host" : "localhost:10001" },
{       "_id" : 3,      "host" : "localhost:10002" } ] }
SECONDARY>
执行初始化命令时,键“members”的内嵌文档中,还有如下两个键可以使用:

1》 priority :N,优先级,指明一个服务器的优先级,默认为1,可以是[0,1000],通过这个我们可以指明副本集某台服务器节点初始为活跃节点

2》 arbiterOnly :true,仲裁节点,特定指明某个服务器节点为仲裁节点,仲裁节点不会复制数据,不会成为活跃节点,其存在的目的只有一个:当前活跃节点失效后,副本集内重新投票选活跃节点时,防止出现僵局!

【故障切换】

当当前活跃节点失效,包括两种情况:

1》 当前活跃节点宕机或本身异常

2》 当前活跃节点会通过心跳跟踪集群中多收节点对其可见,如果数量小于集群服务器数量的一半,会自动降级为备份节点

此时,集群会投票选举出一个新的活跃节点(新比较优先级,优先级相同的,各个节点判断哪个数据最新,就会投哪个),任何时候,活跃节点的数据会被认为是最新的。当重新确定了活跃节点后,所有其他节点都要重新进行完整同步!




你可能感兴趣的:(学习MongoDB--(9-4):复制(副本集))