0%

MongoDB副本集

关于副本集的理论我就不介绍了。下面说下如何实现副本集的操作。

前提

  1. 首先就是要安装mongoDB服务器了。我建议按照我之前写的这篇文章进行安装。
  2. 准备三台以上的服务器。然后同时安装MongoDB。我们三台服务器的IP分别是(10.55.160.91,10.55.160.92,10.55.160.93)

部署一个副本集

  1. 修改配置文件。
    首先我们打开配置文件。

    1
    vim /etc/mongod.conf

    找到bindIp: 127.0.0.1这行,我们需要对这行进行注释。变成如下这样:

    1
    #bindIp: 127.0.0.1  # Listen to local interface only, comment to listen on all interfaces.

    因为这个bindIp代表只允许本机进行连接,然后不允许其他服务器进行连接,那么,下面就没有办法继续执行了。

    找到#replication:这行我们将其注释去掉,然后下面增加一行,变成下面这样:

    1
    replication:
    2
      replSetName: test

    replSetName表示副本集组的名字(test是我自己写的,你们也可以写你们自己的喜欢的名字),比如,我们要将三台服务器进行关联,那么我们就要将三台服务器都设置为相同的名字。

    然后如果三台服务器的MongoDB都已经启动了,那么就执行以下命令:

    1
    service mongod restart

    如果没有启动就执行以下命令:

    1
    service mongod start
  2. 链接到任意一台服务器。
    我选择的是链接到10.55.160.91。也就是我现在正在操作的这一台服务器。然后登录:

    1
    mongo
  3. 初始化副本集。
    初始化副本集,我们需要使用rs.initiate()方法。
    我现在需要添加的是三台服务器,我们可以执行以下方法:

    1
    rs.initiate({
    2
        _id: "test",
    3
        version: 1,
    4
        members: [
    5
            { _id: 0, host : "10.55.160.91:27017" },
    6
            { _id: 1, host : "10.55.160.92:27017" },
    7
            { _id: 2, host : "10.55.160.93:27017" }
    8
        ]
    9
    })

    当返回值显示为如下的时候,就代表成功了:

    1
    { "ok" : 1 }
  4. 这样就完成了,是不是很简单。哈哈。

然后你就发现你的输入命令的标题就变了。变成如下这样了:

1
test:OTHER>

不管它,我们继续执行操作,执行rs.status(),查看当前状态。

1
rs.status()

查看返回值:

1
{
2
	"set" : "test",
3
	"date" : ISODate("2016-09-22T08:08:36.607Z"),
4
	"myState" : 1,
5
	"term" : NumberLong(1),
6
	"heartbeatIntervalMillis" : NumberLong(2000),
7
	"members" : [
8
		{
9
			"_id" : 0,
10
			"name" : "10.55.160.91:27017",
11
			"health" : 1,
12
			"state" : 1,
13
			"stateStr" : "PRIMARY",
14
			"uptime" : 154,
15
			"optime" : {
16
				"ts" : Timestamp(1474531710, 1),
17
				"t" : NumberLong(1)
18
			},
19
			"optimeDate" : ISODate("2016-09-22T08:08:30Z"),
20
			"infoMessage" : "could not find member to sync from",
21
			"electionTime" : Timestamp(1474531709, 1),
22
			"electionDate" : ISODate("2016-09-22T08:08:29Z"),
23
			"configVersion" : 1,
24
			"self" : true
25
		},
26
		{
27
			"_id" : 1,
28
			"name" : "10.55.160.92:27017",
29
			"health" : 1,
30
			"state" : 2,
31
			"stateStr" : "SECONDARY",
32
			"uptime" : 17,
33
			"optime" : {
34
				"ts" : Timestamp(1474531710, 1),
35
				"t" : NumberLong(1)
36
			},
37
			"optimeDate" : ISODate("2016-09-22T08:08:30Z"),
38
			"lastHeartbeat" : ISODate("2016-09-22T08:08:35.966Z"),
39
			"lastHeartbeatRecv" : ISODate("2016-09-22T08:08:32.078Z"),
40
			"pingMs" : NumberLong(0),
41
			"syncingTo" : "10.55.160.91:27017",
42
			"configVersion" : 1
43
		},
44
		{
45
			"_id" : 2,
46
			"name" : "10.55.160.93:27017",
47
			"health" : 1,
48
			"state" : 2,
49
			"stateStr" : "SECONDARY",
50
			"uptime" : 17,
51
			"optime" : {
52
				"ts" : Timestamp(1474531710, 1),
53
				"t" : NumberLong(1)
54
			},
55
			"optimeDate" : ISODate("2016-09-22T08:08:30Z"),
56
			"lastHeartbeat" : ISODate("2016-09-22T08:08:35.966Z"),
57
			"lastHeartbeatRecv" : ISODate("2016-09-22T08:08:32.078Z"),
58
			"pingMs" : NumberLong(0),
59
			"syncingTo" : "10.55.160.91:27017",
60
			"configVersion" : 1
61
		}
62
	],
63
	"ok" : 1
64
}

我们主要是看members字段里面的stateStr的值。

很幸运,我当前执行命令的服务器被推举为主服务器。

如果你们现在服务器显示当前的服务器的状态是:SECONDARY。表示该服务器是从服务器,我们需要查看哪台服务器为主服务器,也就是"stateStr" : "PRIMARY"。我们需要在主服务器才进行进行操作,当然,也有强行在从服务器进行操作的办法。这里先不说。

这样我们就可以在主服务器进行操作了。比如存储数据。

添加成员

比如现在又有了一台服务器(10.55.160.94)需要加入到这个副本集中。我们可以使用rs.add()进行添加服务器。

首先我们还是别忘了修改配置文件的步骤。。。。。。修改完成配置文件之后重启Mongod,然后在主服务器执行如下命令:

1
rs.add("10.55.160.94:27017")

在执行该命令之后,可能会出现主服务器的选择,我们要注意主服务器是否已经变成了别的服务器。我们可以使用rs.status()查看新的主服务器是什么。

1
{
2
	"set" : "test",
3
	"date" : ISODate("2016-09-22T09:28:53.913Z"),
4
	"myState" : 1,
5
	"term" : NumberLong(6),
6
	"heartbeatIntervalMillis" : NumberLong(2000),
7
	"members" : [
8
		{
9
			"_id" : 0,
10
			"name" : "10.55.160.91:27017",
11
			"health" : 1,
12
			"state" : 2,
13
			"stateStr" : "SECONDARY",
14
			"uptime" : 1202,
15
			"optime" : {
16
				"ts" : Timestamp(1474536460, 1),
17
				"t" : NumberLong(6)
18
			},
19
			"optimeDate" : ISODate("2016-09-22T09:27:40Z"),
20
			"lastHeartbeat" : ISODate("2016-09-22T09:28:52.089Z"),
21
			"lastHeartbeatRecv" : ISODate("2016-09-22T09:28:52.095Z"),
22
			"pingMs" : NumberLong(0),
23
			"syncingTo" : "10.55.160.93:27017",
24
			"configVersion" : 6
25
		},
26
		{
27
			"_id" : 1,
28
			"name" : "10.55.160.92:27017",
29
			"health" : 1,
30
			"state" : 2,
31
			"stateStr" : "SECONDARY",
32
			"uptime" : 1202,
33
			"optime" : {
34
				"ts" : Timestamp(1474536460, 1),
35
				"t" : NumberLong(6)
36
			},
37
			"optimeDate" : ISODate("2016-09-22T09:27:40Z"),
38
			"lastHeartbeat" : ISODate("2016-09-22T09:28:52.089Z"),
39
			"lastHeartbeatRecv" : ISODate("2016-09-22T09:28:52.095Z"),
40
			"pingMs" : NumberLong(0),
41
			"syncingTo" : "10.55.160.93:27017",
42
			"configVersion" : 6
43
		},
44
		{
45
			"_id" : 2,
46
			"name" : "10.55.160.93:27017",
47
			"health" : 1,
48
			"state" : 1,
49
			"stateStr" : "PRIMARY",
50
			"uptime" : 1207,
51
			"optime" : {
52
				"ts" : Timestamp(1474536460, 1),
53
				"t" : NumberLong(6)
54
			},
55
			"optimeDate" : ISODate("2016-09-22T09:27:40Z"),
56
			"electionTime" : Timestamp(1474536383, 1),
57
			"electionDate" : ISODate("2016-09-22T09:26:23Z"),
58
			"configVersion" : 6,
59
			"self" : true
60
		},
61
		{
62
			"_id" : 3,
63
			"name" : "10.55.160.94:27017",
64
			"health" : 1,
65
			"state" : 2,
66
			"stateStr" : "SECONDARY",
67
			"uptime" : 71,
68
			"optime" : {
69
				"ts" : Timestamp(1474536460, 1),
70
				"t" : NumberLong(6)
71
			},
72
			"optimeDate" : ISODate("2016-09-22T09:27:40Z"),
73
			"lastHeartbeat" : ISODate("2016-09-22T09:28:52.089Z"),
74
			"lastHeartbeatRecv" : ISODate("2016-09-22T09:28:52.059Z"),
75
			"pingMs" : NumberLong(0),
76
			"configVersion" : 6
77
		}
78
	],
79
	"ok" : 1
80
}

修改服务器的优先级

比如我们新添加的服务器(10.55.160.94),这个服务器的配置较高。我希望优先让它成为主服务器。我们可以通过如下方式进行修改:

首先我们可以通过rs.conf来查看是第几个游标。

1
rs.conf()

返回值如下:

1
{
2
	"_id" : "test",
3
	"version" : 6,
4
	"protocolVersion" : NumberLong(1),
5
	"members" : [
6
		{
7
			"_id" : 0,
8
			"host" : "10.55.160.91:27017",
9
			"arbiterOnly" : false,
10
			"buildIndexes" : true,
11
			"hidden" : false,
12
			"priority" : 1,
13
			"tags" : {
14
				
15
			},
16
			"slaveDelay" : NumberLong(0),
17
			"votes" : 1
18
		},
19
		{
20
			"_id" : 1,
21
			"host" : "10.55.160.92:27017",
22
			"arbiterOnly" : false,
23
			"buildIndexes" : true,
24
			"hidden" : false,
25
			"priority" : 1,
26
			"tags" : {
27
				
28
			},
29
			"slaveDelay" : NumberLong(0),
30
			"votes" : 1
31
		},
32
		{
33
			"_id" : 2,
34
			"host" : "10.55.160.93:27017",
35
			"arbiterOnly" : false,
36
			"buildIndexes" : true,
37
			"hidden" : false,
38
			"priority" : 1,
39
			"tags" : {
40
				
41
			},
42
			"slaveDelay" : NumberLong(0),
43
			"votes" : 1
44
		},
45
		{
46
			"_id" : 3,
47
			"host" : "10.55.160.94:27017",
48
			"arbiterOnly" : false,
49
			"buildIndexes" : true,
50
			"hidden" : false,
51
			"priority" : 1,
52
			"tags" : {
53
				
54
			},
55
			"slaveDelay" : NumberLong(0),
56
			"votes" : 1
57
		}
58
	],
59
	"settings" : {
60
		"chainingAllowed" : true,
61
		"heartbeatIntervalMillis" : 2000,
62
		"heartbeatTimeoutSecs" : 10,
63
		"electionTimeoutMillis" : 10000,
64
		"getLastErrorModes" : {
65
			
66
		},
67
		"getLastErrorDefaults" : {
68
			"w" : 1,
69
			"wtimeout" : 0
70
		},
71
		"replicaSetId" : ObjectId("57e391736b7581c82cc75a83")
72
	}
73
}

我们可以看到它的游标是第3个(从0开始计算)。
我们可以这样进行修改:

1
cfg = rs.conf()
2
cfg.members[3].priority = 10
3
rs.reconfig(cfg)

过了一会,我们就看到主服务器变成(10.55.160.94)了。

1
{
2
	"set" : "test",
3
	"date" : ISODate("2016-09-22T10:18:48.348Z"),
4
	"myState" : 2,
5
	"term" : NumberLong(7),
6
	"syncingTo" : "10.55.160.94:27017",
7
	"heartbeatIntervalMillis" : NumberLong(2000),
8
	"members" : [
9
		{
10
			"_id" : 0,
11
			"name" : "10.55.160.91:27017",
12
			"health" : 1,
13
			"state" : 2,
14
			"stateStr" : "SECONDARY",
15
			"uptime" : 4197,
16
			"optime" : {
17
				"ts" : Timestamp(1474539241, 2),
18
				"t" : NumberLong(7)
19
			},
20
			"optimeDate" : ISODate("2016-09-22T10:14:01Z"),
21
			"lastHeartbeat" : ISODate("2016-09-22T10:18:46.676Z"),
22
			"lastHeartbeatRecv" : ISODate("2016-09-22T10:18:46.535Z"),
23
			"pingMs" : NumberLong(0),
24
			"syncingTo" : "10.55.160.94:27017",
25
			"configVersion" : 7
26
		},
27
		{
28
			"_id" : 1,
29
			"name" : "10.55.160.92:27017",
30
			"health" : 1,
31
			"state" : 2,
32
			"stateStr" : "SECONDARY",
33
			"uptime" : 4197,
34
			"optime" : {
35
				"ts" : Timestamp(1474539241, 2),
36
				"t" : NumberLong(7)
37
			},
38
			"optimeDate" : ISODate("2016-09-22T10:14:01Z"),
39
			"lastHeartbeat" : ISODate("2016-09-22T10:18:46.676Z"),
40
			"lastHeartbeatRecv" : ISODate("2016-09-22T10:18:46.674Z"),
41
			"pingMs" : NumberLong(0),
42
			"syncingTo" : "10.55.160.94:27017",
43
			"configVersion" : 7
44
		},
45
		{
46
			"_id" : 2,
47
			"name" : "10.55.160.93:27017",
48
			"health" : 1,
49
			"state" : 2,
50
			"stateStr" : "SECONDARY",
51
			"uptime" : 4202,
52
			"optime" : {
53
				"ts" : Timestamp(1474539241, 2),
54
				"t" : NumberLong(7)
55
			},
56
			"optimeDate" : ISODate("2016-09-22T10:14:01Z"),
57
			"syncingTo" : "10.55.160.94:27017",
58
			"configVersion" : 7,
59
			"self" : true
60
		},
61
		{
62
			"_id" : 3,
63
			"name" : "10.55.160.94:27017",
64
			"health" : 1,
65
			"state" : 1,
66
			"stateStr" : "PRIMARY",
67
			"uptime" : 3066,
68
			"optime" : {
69
				"ts" : Timestamp(1474539241, 2),
70
				"t" : NumberLong(7)
71
			},
72
			"optimeDate" : ISODate("2016-09-22T10:14:01Z"),
73
			"lastHeartbeat" : ISODate("2016-09-22T10:18:46.676Z"),
74
			"lastHeartbeatRecv" : ISODate("2016-09-22T10:18:47.546Z"),
75
			"pingMs" : NumberLong(0),
76
			"electionTime" : Timestamp(1474539241, 1),
77
			"electionDate" : ISODate("2016-09-22T10:14:01Z"),
78
			"configVersion" : 7
79
		}
80
	],
81
	"ok" : 1
82
}

添加仲裁者服务器

仲裁者服务器只参与投票,而不是进行数据的存储。别忘了定义副本集名称。

我们可以使用rs.addArb()来进行添加一台新的服务器(10.55.160.95)为仲裁服务器。

命令如下:

1
rs.addArb('10.55.160.95')

返回{ "ok" : 1 }就正常执行了。这时我们通过rs.status()来看一下服务器的状态。

1
{
2
	"set" : "test",
3
	"date" : ISODate("2016-09-23T02:54:44.854Z"),
4
	"myState" : 2,
5
	"term" : NumberLong(9),
6
	"syncingTo" : "10.55.160.94:27017",
7
	"heartbeatIntervalMillis" : NumberLong(2000),
8
	"members" : [
9
		{
10
			"_id" : 0,
11
			"name" : "10.55.160.91:27017",
12
			"health" : 1,
13
			"state" : 2,
14
			"stateStr" : "SECONDARY",
15
			"uptime" : 141,
16
			"optime" : {
17
				"ts" : Timestamp(1474599221, 1),
18
				"t" : NumberLong(9)
19
			},
20
			"optimeDate" : ISODate("2016-09-23T02:53:41Z"),
21
			"syncingTo" : "10.55.160.94:27017",
22
			"configVersion" : 8,
23
			"self" : true
24
		},
25
		{
26
			"_id" : 1,
27
			"name" : "10.55.160.92:27017",
28
			"health" : 1,
29
			"state" : 2,
30
			"stateStr" : "SECONDARY",
31
			"uptime" : 95,
32
			"optime" : {
33
				"ts" : Timestamp(1474599221, 1),
34
				"t" : NumberLong(9)
35
			},
36
			"optimeDate" : ISODate("2016-09-23T02:53:41Z"),
37
			"lastHeartbeat" : ISODate("2016-09-23T02:54:43.113Z"),
38
			"lastHeartbeatRecv" : ISODate("2016-09-23T02:54:44.091Z"),
39
			"pingMs" : NumberLong(0),
40
			"syncingTo" : "10.55.160.94:27017",
41
			"configVersion" : 8
42
		},
43
		{
44
			"_id" : 2,
45
			"name" : "10.55.160.93:27017",
46
			"health" : 1,
47
			"state" : 2,
48
			"stateStr" : "SECONDARY",
49
			"uptime" : 86,
50
			"optime" : {
51
				"ts" : Timestamp(1474599221, 1),
52
				"t" : NumberLong(9)
53
			},
54
			"optimeDate" : ISODate("2016-09-23T02:53:41Z"),
55
			"lastHeartbeat" : ISODate("2016-09-23T02:54:43.113Z"),
56
			"lastHeartbeatRecv" : ISODate("2016-09-23T02:54:43.121Z"),
57
			"pingMs" : NumberLong(0),
58
			"syncingTo" : "10.55.160.94:27017",
59
			"configVersion" : 8
60
		},
61
		{
62
			"_id" : 3,
63
			"name" : "10.55.160.94:27017",
64
			"health" : 1,
65
			"state" : 1,
66
			"stateStr" : "PRIMARY",
67
			"uptime" : 83,
68
			"optime" : {
69
				"ts" : Timestamp(1474599221, 1),
70
				"t" : NumberLong(9)
71
			},
72
			"optimeDate" : ISODate("2016-09-23T02:53:41Z"),
73
			"lastHeartbeat" : ISODate("2016-09-23T02:54:43.113Z"),
74
			"lastHeartbeatRecv" : ISODate("2016-09-23T02:54:43.134Z"),
75
			"pingMs" : NumberLong(0),
76
			"electionTime" : Timestamp(1474599220, 1),
77
			"electionDate" : ISODate("2016-09-23T02:53:40Z"),
78
			"configVersion" : 8
79
		},
80
		{
81
			"_id" : 4,
82
			"name" : "10.55.160.95:27017",
83
			"health" : 1,
84
			"state" : 7,
85
			"stateStr" : "ARBITER",
86
			"uptime" : 79,
87
			"lastHeartbeat" : ISODate("2016-09-23T02:54:43.113Z"),
88
			"lastHeartbeatRecv" : ISODate("2016-09-23T02:54:42.775Z"),
89
			"pingMs" : NumberLong(0),
90
			"configVersion" : 8
91
		}
92
	],
93
	"ok" : 1
94
}

我们可以看到IP为10.55.160.95这台服务器,它的stateStr的值是ARBITER。这个就代表是仲裁者的角色。

移除成员

移除成员我们使用rs.remove()方法就可以了。

比如我们要移除10.55.160.93。我们可以使用如下命令:

1
rs.remove('10.55.160.93:27017')

我们可以使用rs.status()查看一下返回值:

1
{
2
	"set" : "test",
3
	"date" : ISODate("2016-09-23T03:15:21Z"),
4
	"myState" : 2,
5
	"term" : NumberLong(9),
6
	"syncingTo" : "10.55.160.94:27017",
7
	"heartbeatIntervalMillis" : NumberLong(2000),
8
	"members" : [
9
		{
10
			"_id" : 0,
11
			"name" : "10.55.160.91:27017",
12
			"health" : 1,
13
			"state" : 2,
14
			"stateStr" : "SECONDARY",
15
			"uptime" : 1377,
16
			"optime" : {
17
				"ts" : Timestamp(1474600512, 1),
18
				"t" : NumberLong(9)
19
			},
20
			"optimeDate" : ISODate("2016-09-23T03:15:12Z"),
21
			"syncingTo" : "10.55.160.94:27017",
22
			"configVersion" : 9,
23
			"self" : true
24
		},
25
		{
26
			"_id" : 1,
27
			"name" : "10.55.160.92:27017",
28
			"health" : 1,
29
			"state" : 2,
30
			"stateStr" : "SECONDARY",
31
			"uptime" : 1331,
32
			"optime" : {
33
				"ts" : Timestamp(1474600512, 1),
34
				"t" : NumberLong(9)
35
			},
36
			"optimeDate" : ISODate("2016-09-23T03:15:12Z"),
37
			"lastHeartbeat" : ISODate("2016-09-23T03:15:20.593Z"),
38
			"lastHeartbeatRecv" : ISODate("2016-09-23T03:15:20.592Z"),
39
			"pingMs" : NumberLong(0),
40
			"syncingTo" : "10.55.160.94:27017",
41
			"configVersion" : 9
42
		},
43
		{
44
			"_id" : 3,
45
			"name" : "10.55.160.94:27017",
46
			"health" : 1,
47
			"state" : 1,
48
			"stateStr" : "PRIMARY",
49
			"uptime" : 1319,
50
			"optime" : {
51
				"ts" : Timestamp(1474600512, 1),
52
				"t" : NumberLong(9)
53
			},
54
			"optimeDate" : ISODate("2016-09-23T03:15:12Z"),
55
			"lastHeartbeat" : ISODate("2016-09-23T03:15:20.595Z"),
56
			"lastHeartbeatRecv" : ISODate("2016-09-23T03:15:20.582Z"),
57
			"pingMs" : NumberLong(0),
58
			"electionTime" : Timestamp(1474599220, 1),
59
			"electionDate" : ISODate("2016-09-23T02:53:40Z"),
60
			"configVersion" : 9
61
		},
62
		{
63
			"_id" : 4,
64
			"name" : "10.55.160.95:27017",
65
			"health" : 1,
66
			"state" : 7,
67
			"stateStr" : "ARBITER",
68
			"uptime" : 1315,
69
			"lastHeartbeat" : ISODate("2016-09-23T03:15:20.596Z"),
70
			"lastHeartbeatRecv" : ISODate("2016-09-23T03:15:17.585Z"),
71
			"pingMs" : NumberLong(0),
72
			"configVersion" : 9
73
		}
74
	],
75
	"ok" : 1
76
}

发现10.55.160.93这个服务器已经从副本集中消失了。

更换副本集成员

我们可以使用如下办法进行快速更换成员:

1
cfg = rs.conf()
2
cfg.members[0].host = "10.55.160.93"
3
rs.reconfig(cfg)

我们看之前被替换走的成员,它的状态已经变成这样了:

1
{
2
	"state" : 10,
3
	"stateStr" : "REMOVED",
4
	"uptime" : 3162,
5
	"optime" : {
6
		"ts" : Timestamp(1474602195, 1),
7
		"t" : NumberLong(9)
8
	},
9
	"optimeDate" : ISODate("2016-09-23T03:43:15Z"),
10
	"ok" : 0,
11
	"errmsg" : "Our replica set config is invalid or we are not a member of it",
12
	"code" : 93
13
}