前言
MongoDB是一个开源的文档型数据库,介于关系数据库和非关系数据库之间,是非关系数据库中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
存储引擎
存储引擎是MongoDB的核心组件,负责管理数据如何存储在硬盘和内存上。从MongoDB3.0版本开始,MongoDB支持多数据存储引擎,如WiredTiger,MMAPv1,In-Memory等,每个存储引擎都有自己的优势,percona版本还支持RocksDB引擎。从3.2版本开始,WiredTiger成为了默认的存储引擎,在之前版本MMAPv1为默认存储引擎。这两种引擎在目前的使用量占比最大。
WiredTiger、MMAPv1对比
性能、性能
MMAPv1引擎使用的是表级锁,当单个集合上有并发操作时,吞吐会受限制。
Wiredtiger引擎使用文档级锁,通过多版本并发控制,带来并发和吞吐的提高。
压缩、加密
MMAPv1引擎要求数据在内存和在磁盘的形式一致(map磁盘内存映射),因此不支持压缩和加密。
Wiredtiger引擎支持对所有集合和索引进行Block压缩和前缀压缩,可以大大节省存储空间。但是消耗额外的CPU执行数据压缩和解压缩的操作。
存储方式
MMAPv1引擎在数据库级别配置文件,数据库中的所有集合和索引都混合存储在数据库文件中,即使删掉了某个集合或者索引,占用的磁盘空间也很难回收。
WiredTiger引擎在集合和索引级别分配文件,数据库中的所有集合和索引都存储在单独的文件中,集合或者索引删除后,磁盘空间方便回收。
内存使用
MMAPv1引擎消耗内存大,无有效控制手段。
WiredTiger引擎支持内存使用空间配置,可通过storage.wiredTiger.engineConfig.cacheSizeGB参控制MongoDB所能使用的最大内存。
准备
操作系统:centos 6.5 x86_64
迁移
变更存储引擎的常见方式有2种,分别是停机和不停机。本文只介绍在不停机的情况下从MMAPv1引擎副本集迁移至WiredTiger引擎副本集。
安装
注意:
迁移的成功取决于oplog的大小是否能够满足从库完全初始化数据。
首先安装好mongodb,并依次启动,实例以3.4.4版本为例,端口分别是27017/28017/29017,部署在一台服务器,具体安装步骤省略。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19[root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongod -f /hwdata/data/mongodb1/conf/mongodb.conf
note: noprealloc may hurt performance in many applications
about to fork child process, waiting until server is ready for connections.
forked process: 14873
child process started successfully, parent exiting
[root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb2/bin/mongod -f /hwdata/data/mongodb2/conf/mongodb.conf
note: noprealloc may hurt performance in many applications
about to fork child process, waiting until server is ready for connections.
forked process: 14894
child process started successfully, parent exiting
[root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb3/bin/mongod -f /hwdata/data/mongodb3/conf/mongodb.conf
note: noprealloc may hurt performance in many applications
about to fork child process, waiting until server is ready for connections.
forked process: 14919
child process started successfully, parent exiting
[root@iZuf6c08fdv8duubho2b0rZ ~]# netstat -tunlp|grep mongo
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 14873/mongod
tcp 0 0 0.0.0.0:28017 0.0.0.0:* LISTEN 14894/mongod
tcp 0 0 0.0.0.0:29017 0.0.0.0:* LISTEN 14919/mongod
配置文件
详情的配置文件如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45[root@iZuf6c08fdv8duubho2b0rZ ~]# cat /hwdata/data/mongodb1/conf/mongodb.conf
dbpath=/hwdata/data/mongodb1/data
logpath=/hwdata/data/mongodb1/logs/mongodb.log
pidfilepath=/hwdata/data/mongodb1/logs/mongodb.pid
directoryperdb=true
logappend=true
port=27017
fork=true
noprealloc=true
maxConns=10000
profile=1
slowms=100
journal=true
replSet=jiessie
storageEngine=mmapv1
[root@iZuf6c08fdv8duubho2b0rZ ~]# cat /hwdata/data/mongodb2/conf/mongodb.conf
dbpath=/hwdata/data/mongodb2/data
logpath=/hwdata/data/mongodb2/logs/mongodb.log
pidfilepath=/hwdata/data/mongodb2/logs/mongodb.pid
directoryperdb=true
logappend=true
port=28017
fork=true
noprealloc=true
maxConns=10000
profile=1
slowms=100
journal=true
replSet=jiessie
storageEngine=mmapv1
[root@iZuf6c08fdv8duubho2b0rZ ~]# cat /hwdata/data/mongodb3/conf/mongodb.conf
dbpath=/hwdata/data/mongodb3/data
logpath=/hwdata/data/mongodb3/logs/mongodb.log
pidfilepath=/hwdata/data/mongodb3/logs/mongodb.pid
directoryperdb=true
logappend=true
port=29017
fork=true
noprealloc=true
maxConns=10000
profile=1
slowms=100
journal=true
replSet=jiessie
storageEngine=mmapv1
搭建副本集
登录其中一个实例,这里以27017为例子,搭建副本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118[root@iZuf6c08fdv8duubho2b0rZ ~]
MongoDB shell version v3.4.4
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.4
> cfg = {_id: "jiessie", members: [{_id: 0, host: "192.168.7.50:27017",priority:3},{_id: 1, host: "192.168.7.50:28017",priority:2},{_id: 2, host: "192.168.7.50:29017",priority:3}]};
{
"_id" : "jiessie",
"members" : [
{
"_id" : 0,
"host" : "192.168.7.50:27017",
"priority" : 3
},
{
"_id" : 1,
"host" : "192.168.7.50:28017",
"priority" : 2
},
{
"_id" : 2,
"host" : "192.168.7.50:29017",
"priority" : 3
}
]
}
> rs.initiate(cfg);
{ "ok" : 1 }
jiessie:SECONDARY>
jiessie:PRIMARY> rs.status();
{
"set" : "jiessie",
"date" : ISODate("2017-07-21T09:47:24.215Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.7.50:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1056,
"optime" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-07-21T09:47:16Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1500630354, 1),
"electionDate" : ISODate("2017-07-21T09:45:54Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.7.50:28017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 99,
"optime" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-07-21T09:47:16Z"),
"optimeDurableDate" : ISODate("2017-07-21T09:47:16Z"),
"lastHeartbeat" : ISODate("2017-07-21T09:47:22.597Z"),
"lastHeartbeatRecv" : ISODate("2017-07-21T09:47:23.554Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.7.50:29017",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.7.50:29017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 99,
"optime" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1500630436, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-07-21T09:47:16Z"),
"optimeDurableDate" : ISODate("2017-07-21T09:47:16Z"),
"lastHeartbeat" : ISODate("2017-07-21T09:47:22.597Z"),
"lastHeartbeatRecv" : ISODate("2017-07-21T09:47:23.527Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.7.50:27017",
"configVersion" : 1
}
],
"ok" : 1
}
jiessie:PRIMARY>
查看存储引擎
登录其中一个实例,这里以27017为例子,当出现mmapv1时,代表当前使用存储引擎为mmapv11
2
3[root@iZuf6c08fdv8duubho2b0rZ ~]
"name" : "mmapv1",
[root@iZuf6c08fdv8duubho2b0rZ ~]
测试副本集
登录27017的主库,插入数据,在其他节点上查看1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36[root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo
MongoDB shell version v3.4.4
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.4
jiessie:PRIMARY> show dbs;
admin 0.078GB
local 12.072GB
jiessie:PRIMARY> use test11;
switched to db test11
jiessie:PRIMARY> db.tmp11.insert({"id":"11"});
WriteResult({ "nInserted" : 1 })
jiessie:PRIMARY> db.tmp11.find();
{ "_id" : ObjectId("5971ced335d36a3364107ac7"), "id" : "11" }
jiessie:PRIMARY> exit
bye
[root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo localhost:28017
MongoDB shell version v3.4.4
connecting to: localhost:28017
MongoDB server version: 3.4.4
jiessie:SECONDARY> rs.slaveOk();
jiessie:SECONDARY> use test11;
switched to db test11
jiessie:SECONDARY> db.tmp11.find();
{ "_id" : ObjectId("5971ced335d36a3364107ac7"), "id" : "11" }
jiessie:SECONDARY> exit
bye
[root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo localhost:29017
MongoDB shell version v3.4.4
connecting to: localhost:29017
MongoDB server version: 3.4.4
jiessie:SECONDARY> use test11;
switched to db test11
jiessie:SECONDARY> rs.slaveOk();
jiessie:SECONDARY> db.tmp11.find();
{ "_id" : ObjectId("5971ced335d36a3364107ac7"), "id" : "11" }
jiessie:SECONDARY> exit
迁移步骤
1 | 将29017的从节点设置为隐藏节点,不再成为主,对应用不可见 |
详情请参考:http://docs.mongoing.com/manual-zh/tutorial/configure-a-hidden-replica-set-member.html
开始迁移
副本集的架构下,所有节点之间都是同步的,即使存储引擎不同也不受影响。
实验中的副本集端口分别为27017/28017/29017,其中主节点为27017,28017和29017为从节点。
27017权重为3,28017权重为2,29017权重为1。
步骤最后一项,将原主库引擎从MMAPv1设置为WiredTiger,可在原主库上执行rs.stepDown()触发选举,也可提高其他从节点的权重,需要高于主节点。
29017实例
设置节点隐藏
1 | [root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo |
修改引擎,删除原数据
1 | [root@iZuf6c08fdv8duubho2b0rZ ~] |
加入副本集
1 | [root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo |
28017实例
设置节点隐藏
1 | [root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo |
修改引擎,删除原数据
1 | [root@iZuf6c08fdv8duubho2b0rZ ~] |
加入副本集
1 | [root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo |
27017实例
设置节点隐藏
1 | [root@iZuf6c08fdv8duubho2b0rZ ~] |
修改引擎,删除原数据
1 | [root@iZuf6c08fdv8duubho2b0rZ ~] |
加入副本集
1 | [root@iZuf6c08fdv8duubho2b0rZ ~]# /usr/local/mongodb1/bin/mongo localhost:28017 |
结束语
mongodb作为发展迅速的开源数据库一员,版本迭代升级很快,目前使用旧引擎的公司不在小数,新引擎的优点足以促使其升级引擎。