MongoDB复制集及数据分片详解

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

前言

MongoDB是一个由C++语言编写的基于分布式文件存储的数据库,是当前NoSQL数据库中比较热门的一种,旨在为Web应用提供可扩展的高性能数据存储解决方案。本文介绍MongoDB复制集及数据分片。

MongoDB

简介

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。支持的数据结构非常松散,因此可以存储比较复杂的数据类型。最大的特点是其支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

特点及功能特性

特点:高性能、易部署、易使用,存储数据非常方便

主要功能特性有:

面向集合存储,易存储对象类型的数据

模式自由

支持动态查询

支持完全索引,包含内部对象

支持查询

支持复制和故障恢复

使用高效的二进制数据存储,包括大型对象(如视频等)

自动处理碎片,以支持云计算层次的扩展性

支持Ruby,Python,Java,C++,PHP等多种语言

文件存储格式为Bson(一种Json的扩展)

可通过网络访问

优缺点

与关系型数据库相比,MongoDB的优点:

弱一致性(最终一致),更能保证用户的访问速度

文档结构的存储方式,能够更便捷的获取数据

内置GridFS,支持大容量的存储

内置Sharding

第三方支持丰富(这是与其他的NoSQL相比,MongoDB也具有的优势)

性能优越

与关系型数据库相比,MongoDB的缺点:

不支持事务操作

占用空间过大

没有成熟的维护工具

MongoDB复制集

复制集

工作特性:

至少三个,且应该为奇数个节点,可使用arbiter(仲裁者)来参与选举

复制集可实现失效自动转移(通过选举方式实现)

复制集的中特殊类型的节点:

0优先级的节点:冷备节点,不会被选举成为主节点,但可以参与选举

被隐藏的从节点:首先是一个0优先级的从节点,且对客户端不可见

延迟复制的从节点:首先是一个0优先级的从节点,且复制时间落后于主节点一个固定时长

arbiter: 仲裁者

复制集架构

wKiom1WjeEzBZzG-AAFIL7klLVc870.jpg

实验拓扑

wKiom1WjiuDwGwjbAAB4f8khcgU434.jpg

1
2
#系统环境:CentOS6.6
#各节点时间已同步

配置过程

安装所需软件

1
2
3
4
5
6
7
[root@node1 ~] # cd mongodb/
[root@node1 mongodb] # ls
mongodb-org-server-2.6.10-1.x86_64.rpm  mongodb-org-tools-2.6.10-1.x86_64.rpm
mongodb-org-shell-2.6.10-1.x86_64.rpm
[root@node1 mongodb] # yum install *.rpm -y      #3个包都安装
 
#所有节点都执行以上安装操作

编辑配置文件

1
2
3
4
5
6
7
8
9
10
11
12
[root@node1 ~] # vim /etc/mongod.conf 
 
logpath= /var/log/mongodb/mongod .log
logappend= true
fork= true
dbpath= /mongodb/data                         #数据位置
pidfilepath= /var/run/mongodb/mongod .pid
#bind_ip=127.0.0.1                          #默认监听本机,注释掉监听所有
httpinterface= true                           #开放web
rest= true
replSet=testSet                              #复制集名,可自定义
replIndexPrefetch=_id_only

同步配置文件至各节点

1
2
3
4
5
6
[root@node1 ~] # scp /etc/mongod.conf node3:/etc
root@node3's password: 
mongod.conf                                             100% 1567     1.5KB /s    00:00    
[root@node1 ~] # scp /etc/mongod.conf node4:/etc
root@node4's password: 
mongod.conf                                             100% 1567     1.5KB /s    00:00

创建数据目录

1
2
3
4
5
6
[root@node1 ~] # mkdir /mongodb/data -pv
mkdir : created directory ` /mongodb '
mkdir : created directory ` /mongodb/data '
[root@node1 ~] # chown -R mongod.mongod /mongodb
 
#各节点都执行以上操作

启动服务

1
2
3
4
5
6
[root@node1 ~] # service mongod start
Starting mongod:                                           [  OK  ]
[root@node1 mongodb] # ss -tnl | grep 27017
LISTEN     0      128                       *: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
[root@node1 ~] # mongo
MongoDB shell version: 2.6.10
connecting to:  test
Welcome to the MongoDB shell.
For interactive help,  type  "help" .
For  more  comprehensive documentation, see
     http: //docs .mongodb.org/
Questions? Try the support group
     http: //groups .google.com /group/mongodb-user
> rs.initiate()
{
     "info2"  "no configuration explicitly specified -- making one" ,
     "me"  "node1.scholar.com:27017" ,
     "info"  "Config now saved locally.  Should come online in about a minute." ,
     "ok"  : 1
}
 
#初始化成功,查看状态信息
> rs.status()
{
     "set"  "testSet" ,
     "date"  : ISODate( "2015-07-13T12:33:27Z" ),
     "myState"  : 1,
     "members"  : [
         {
             "_id"  : 0,
             "name"  "node1.scholar.com:27017" ,
             "health"  : 1,
             "state"  : 1,
             "stateStr"  "PRIMARY" ,
             "uptime"  : 1111,
             "optime"  : Timestamp(1436790736, 1),
             "optimeDate"  : ISODate( "2015-07-13T12:32:16Z" ),
             "electionTime"  : Timestamp(1436790737, 1),
             "electionDate"  : ISODate( "2015-07-13T12:32:17Z" ),
             "self"  true
         }
     ],
     "ok"  : 1
}
testSet:PRIMARY> 
 
#已成为主节点

添加节点

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
testSet:PRIMARY> rs.add( "172.16.10.125" )
"ok"  : 1 }
testSet:PRIMARY> rs.add( "172.16.10.126" )
"ok"  : 1 }
 
#查看各节点状态
testSet:PRIMARY> rs.status()
{
     "set"  "testSet" ,
     "date"  : ISODate( "2015-07-13T12:41:07Z" ),
     "myState"  : 1,
     "members"  : [
         {
             "_id"  : 0,
             "name"  "node1.scholar.com:27017" ,
             "health"  : 1,
             "state"  : 1,
             "stateStr"  "PRIMARY" ,
             "uptime"  : 1571,
             "optime"  : Timestamp(1436791178, 1),
             "optimeDate"  : ISODate( "2015-07-13T12:39:38Z" ),
             "electionTime"  : Timestamp(1436790737, 1),
             "electionDate"  : ISODate( "2015-07-13T12:32:17Z" ),
             "self"  true
         },
         {
             "_id"  : 1,
             "name"  "172.16.10.125:27017" ,
             "health"  : 1,
             "state"  : 2,
             "stateStr"  "SECONDARY" ,
             "uptime"  : 98,
             "optime"  : Timestamp(1436791178, 1),
             "optimeDate"  : ISODate( "2015-07-13T12:39:38Z" ),
             "lastHeartbeat"  : ISODate( "2015-07-13T12:41:06Z" ),
             "lastHeartbeatRecv"  : ISODate( "2015-07-13T12:41:05Z" ),
             "pingMs"  : 1,
             "syncingTo"  "node1.scholar.com:27017"
         },
         {
             "_id"  : 2,
             "name"  "172.16.10.126:27017" ,
             "health"  : 1,
             "state"  : 2,
             "stateStr"  "SECONDARY" ,
             "uptime"  : 89,
             "optime"  : Timestamp(1436791178, 1),
             "optimeDate"  : ISODate( "2015-07-13T12:39:38Z" ),
             "lastHeartbeat"  : ISODate( "2015-07-13T12:41:06Z" ),
             "lastHeartbeatRecv"  : ISODate( "2015-07-13T12:41:06Z" ),
             "pingMs"  : 1,
             "syncingTo"  "node1.scholar.com:27017"
         }
     ],
     "ok"  : 1
}

创建数据,验证是否同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#主节点
testSet:PRIMARY> use testdb
switched to db testdb
testSet:PRIMARY> db.students.insert({name:  "ZhangSan" ,age:  "21" })
WriteResult({  "nInserted"  : 1 })
 
#从节点
testSet:SECONDARY> rs.slaveOk()      #每个从节点首先申明从节点准备完毕才可同步
testSet:SECONDARY> use testdb
switched to db testdb
testSet:SECONDARY> show collections
students
system.indexes
testSet:SECONDARY> db.students.findOne()
{
     "_id"  : ObjectId( "55a3b494ebcafd9edbdfce4d" ),
     "name"  "ZhangSan" ,
     "age"  "21"
}
#验证从节点是否可写
testSet:SECONDARY> db.classes.insert({class:  "2" ,numstu:  "50" })
WriteResult({  "writeError"  : {  "code"  : undefined,  "errmsg"  "not master"  } })
 
#由此可见,只有主节点才可写

以上便是复制集的相关配置,如果主节点故障,从节点会自动选举出新的主节点,这里就不再演示

数据分片

分片缘由

分片(sharding)是MongoDB用来将大型集合分割到不同服务器(集群)上所采用的方法。当单台服务器CPU,Memory,IO等无法满足需求,就需要将数据分片存放,减缓服务器压力。

分片架构

wKioL1WjvPuQ0HVeAAG3WbZrFqw217.jpg

实验拓扑

wKioL1WjwLeTs5aJAACNKqEdgL8258.jpg

配置过程

因为以上做过实验我们首先来清理一下数据

1
2
3
4
5
[root@node1 ~] # service mongod stop
Stopping mongod:                                           [  OK  ]
[root@node1 ~] # rm -rf /mongodb/data/*
 
#各节点都执行以上操作,若第一次做可忽略

Config Server配置

1
2
3
4
5
#安装所需包
[root@node2 mongodb] # ls
mongodb-org-server-2.6.10-1.x86_64.rpm  mongodb-org-tools-2.6.10-1.x86_64.rpm
mongodb-org-shell-2.6.10-1.x86_64.rpm
[root@node2 mongodb] # yum install *.rpm -y

修改配置文件

1
2
3
4
5
6
7
8
9
10
11
[root@node2 ~] # vim /etc//mongod.conf 
 
logpath= /var/log/mongodb/mongod .log
logappend= true
fork= true
dbpath= /mongodb/data  
configsvr= true                                #开启config server                  
pidfilepath= /var/run/mongodb/mongod .pid
#bind_ip=127.0.0.1                          
httpinterface= true                         
rest= true

创建数据目录

1
2
3
4
[root@node2 ~] # mkdir /mongodb/data -pv
mkdir : created directory ` /mongodb '
mkdir : created directory ` /mongodb/data '
[root@node2 ~] # chown -R mongod.mongod /mongodb

启动服务

1
2
3
4
5
6
[root@node2 ~] # service mongod start
Starting mongod:                                           [  OK  ]
[root@node2 ~] # ss -tnl | grep 27019
LISTEN     0      128                       *:27019                    *:*     
 
#监听端口已发生改变,不再是27017

Mongos配置

1
2
#安装所需包,Mongos节点只装此包即可,无需装第一次实验中的mongod的相关包
[root@node1 ~] # yum install mongodb-org-mongos-2.6.10-1.x86_64.rpm -y

启动服务

1
2
3
4
5
6
7
8
[root@node1 ~] # mongos --configdb=172.16.10.124 --fork --logpath=/var/log/mongodb/mongos.log
2015-07-13T22:22:47.404+0800 warning: running with 1 config server should be  done  only fo
r testing purposes and is not recommended  for  production
about to fork child process, waiting  until  server is ready  for  connections.
forked process: 3583
child process started successfully, parent exiting
 
#--configdb指定config server --logpath指定日志位置 --fork后台运行

Shard配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#以为我们第一次实验安装过软件了,下面直接修改配置文件
[root@node3 ~] # vim /etc/mongod.conf 
 
logpath= /var/log/mongodb/mongod .log
logappend= true
fork= true
dbpath= /mongodb/data                      
pidfilepath= /var/run/mongodb/mongod .pid
#bind_ip=127.0.0.1                          
httpinterface= true                         
rest= true
 
[root@node3 ~] # service mongod start
Starting mongod:                                           [  OK  ]
 
#两个shard节点都执行以上操作

Mongos节点添加Shard节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@node1 ~] # mongo --host 172.16.10.123
MongoDB shell version: 2.6.10
connecting to: 172.16.10.123:27017 /test
mongos> sh.addShard( "172.16.10.125" )
"shardAdded"  "shard0000" "ok"  : 1 }
mongos> sh.addShard( "172.16.10.126" )
"shardAdded"  "shard0001" "ok"  : 1 }
mongos> sh.status()
--- Sharding Status --- 
   sharding version: {
     "_id"  : 1,
     "version"  : 4,
     "minCompatibleVersion"  : 4,
     "currentVersion"  : 5,
     "clusterId"  : ObjectId( "55a3c9ba131b83ff44e19435" )
}
   shards:
     {   "_id"  "shard0000" ,   "host"  "172.16.10.125:27017"  }
     {   "_id"  "shard0001" ,   "host"  "172.16.10.126:27017"  }
   databases:
     {   "_id"  "admin" ,   "partitioned"  false ,   "primary"  "config"  }

对所需对象启用分片功能

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
#对数据库启用sharding功能
mongos> sh.enableSharding( "testdb" )
"ok"  : 1 }
mongos> sh.status()
--- Sharding Status --- 
   sharding version: {
     "_id"  : 1,
     "version"  : 4,
     "minCompatibleVersion"  : 4,
     "currentVersion"  : 5,
     "clusterId"  : ObjectId( "55a3c9ba131b83ff44e19435" )
}
   shards:
     {   "_id"  "shard0000" ,   "host"  "172.16.10.125:27017"  }
     {   "_id"  "shard0001" ,   "host"  "172.16.10.126:27017"  }
   databases:
     {   "_id"  "admin" ,   "partitioned"  false ,   "primary"  "config"  }
     {   "_id"  "test" ,   "partitioned"  false ,   "primary"  "shard0000"  }
     {   "_id"  "testdb" ,   "partitioned"  true ,   "primary"  "shard0000"  }
 
#指定需要分片的Collection及索引
mongos> sh.shardCollection( "testdb.students" ,{ "age" : 1})
"collectionsharded"  "testdb.students" "ok"  : 1 }
mongos> sh.status()
--- Sharding Status --- 
   sharding version: {
     "_id"  : 1,
     "version"  : 4,
     "minCompatibleVersion"  : 4,
     "currentVersion"  : 5,
     "clusterId"  : ObjectId( "55a3c9ba131b83ff44e19435" )
}
   shards:
     {   "_id"  "shard0000" ,   "host"  "172.16.10.125:27017"  }
     {   "_id"  "shard0001" ,   "host"  "172.16.10.126:27017"  }
   databases:
     {   "_id"  "admin" ,   "partitioned"  false ,   "primary"  "config"  }
     {   "_id"  "test" ,   "partitioned"  false ,   "primary"  "shard0000"  }
     {   "_id"  "testdb" ,   "partitioned"  true ,   "primary"  "shard0000"  }
         testdb.students
             shard key: {  "age"  : 1 }
             chunks:
                 shard0000   1
             "age"  : {  "$minKey"  : 1 } } -->> {  "age"  : {  "$maxKey"  : 1 } }
on : shard0000 Timestamp(1, 0)

分片功能已开启,接下来我们手动创建数据来验证是否会分片

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
mongos> use testdb
switched to db testdb
mongos>  for  (i=1;i<=100000;i++) db.students.insert({name: "student" +i,age:(i%120),address: "China" })
WriteResult({  "nInserted"  : 1 })
mongos> db.students. find ().count()
100000
mongos> sh.status()
--- Sharding Status --- 
   sharding version: {
     "_id"  : 1,
     "version"  : 4,
     "minCompatibleVersion"  : 4,
     "currentVersion"  : 5,
     "clusterId"  : ObjectId( "55a3c9ba131b83ff44e19435" )
}
   shards:
     {   "_id"  "shard0000" ,   "host"  "172.16.10.125:27017"  }
     {   "_id"  "shard0001" ,   "host"  "172.16.10.126:27017"  }
   databases:
     {   "_id"  "admin" ,   "partitioned"  false ,   "primary"  "config"  }
     {   "_id"  "test" ,   "partitioned"  false ,   "primary"  "shard0000"  }
     {   "_id"  "testdb" ,   "partitioned"  true ,   "primary"  "shard0000"  }
         testdb.students
             shard key: {  "age"  : 1 }
             chunks:
                 shard0001   1
                 shard0000   2
             "age"  : {  "$minKey"  : 1 } } -->> {  "age"  : 1 } on : shard0001 Timestamp(2, 0) 
             "age"  : 1 } -->> {  "age"  : 119 } on : shard0000 Timestamp(2, 2) 
             "age"  : 119 } -->> {  "age"  : {  "$maxKey"  : 1 } } on : shard0000 Timestamp(2, 3)

查看数据状态会发现数据已被分到不同shard上,至此,数据分片成功实现

The end

MongoDB复制集及数据分片就先说到这里了,通过以上简单应用可以看出,MongoDB在大数据处理方面比关系型数据库略胜一筹,但由于MongoDB目前还处在发展阶段,在实际生产环境中还有许多问题有待解决,不过相信在未来MongoDB会更加出色。以上仅为个人学习整理,如有错漏,大神勿喷~~~



本文转自 北城书生  51CTO博客,原文链接:http://blog.51cto.com/scholar/1673939


相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
2月前
|
存储 NoSQL MongoDB
数据的存储--MongoDB文档存储(二)
数据的存储--MongoDB文档存储(二)
72 2
|
4月前
|
运维 监控 NoSQL
【MongoDB 复制集秘籍】Secondary 同步慢怎么办?深度解析与实战指南,让你的数据库飞速同步!
【8月更文挑战第24天】本文通过一个具体案例探讨了MongoDB复制集中Secondary成员同步缓慢的问题。现象表现为数据延迟增加,影响业务运行。经分析,可能的原因包括硬件资源不足、网络状况不佳、复制日志错误等。解决策略涵盖优化硬件(如增加内存、升级CPU)、调整网络配置以减少延迟以及优化MongoDB配置(例如调整`oplogSize`、启用压缩)。通过这些方法可有效提升同步效率,保证系统的稳定性和性能。
108 4
|
2月前
|
存储 NoSQL 前端开发
MongoDB 分片
10月更文挑战第17天
40 2
|
1月前
|
存储 NoSQL MongoDB
【赵渝强老师】部署MongoDB复制集
本文介绍了如何在单个节点上搭建MongoDB复制集环境,通过监听不同端口实现多节点配置。详细步骤包括创建数据目录、编辑配置文件、启动节点、初始化复制集、查看状态以及测试主从库的读写操作。文中还提供了视频讲解和代码示例,帮助读者更好地理解和操作。
|
1月前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB复制集的体系架构
MongoDB的复制集是一种集群技术,由一个Primary节点和多个Secondary节点组成,实现数据的高可用性。Primary节点处理写入请求,Secondary节点同步数据。当Primary节点故障时,Secondary节点可通过选举成为新的Primary节点。视频讲解和示意图详见正文。
|
2月前
|
NoSQL MongoDB 数据库
使用NimoShake将数据从AWS DynamoDB迁移至阿里云MongoDB
使用NimoShake将数据从AWS DynamoDB迁移至阿里云MongoDB
|
2月前
|
存储 NoSQL 关系型数据库
数据的存储--MongoDB文档存储(一)
数据的存储--MongoDB文档存储(一)
99 3
|
3月前
|
存储 监控 NoSQL
*MongoDB的水平扩展主要通过分片技术实
*MongoDB的水平扩展主要通过分片技术实
52 5
|
3月前
|
存储 NoSQL 前端开发
MongoDB 分片总结
这篇文章总结了MongoDB分片的概念、集群结构、分片实例、配置和测试过程。
84 6
|
4月前
|
C# UED 开发者
WPF与性能优化:掌握这些核心技巧,让你的应用从卡顿到丝滑,彻底告别延迟,实现响应速度质的飞跃——从布局到动画全面剖析与实例演示
【8月更文挑战第31天】本文通过对比优化前后的方法,详细探讨了提升WPF应用响应速度的策略。文章首先分析了常见的性能瓶颈,如复杂的XAML布局、耗时的事件处理、不当的数据绑定及繁重的动画效果。接着,通过具体示例展示了如何简化XAML结构、使用后台线程处理事件、调整数据绑定设置以及利用DirectX优化动画,从而有效提升应用性能。通过这些优化措施,WPF应用将更加流畅,用户体验也将得到显著改善。
301 1
下一篇
DataWorks