MongoDB复制集及数据分片详解

前言

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

MongoDB

简介

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

特点及功能特性

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

主要功能特性有:

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

模式自由

支持动态查询

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

支持查询

支持复制和故障恢复

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

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

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

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

可通过网络访问

优缺点

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

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

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

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

内置Sharding

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

性能优越

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

不支持事务操作

占用空间过大

没有成熟的维护工具

MongoDB复制集

复制集

MongoDB有两种复制类型:Master/Slave主从和Replica Set副本集复制,由于MongoDB的特性,主从复制架构已基本不再使用,目前比较常见的是副本集复制方式

工作特性:

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

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

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

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

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

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

arbiter: 仲裁者

复制集架构

mongodb主从复制.jpg

实验拓扑

mongodb复制集.jpg

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

配置过程

安装所需软件

[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个包都安装

#所有节点都执行以上安装操作

编辑配置文件

[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

同步配置文件至各节点

[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

创建数据目录

[root@node1 ~]# mkdir /mongodb/data -pv
mkdir: created directory `/mongodb'
mkdir: created directory `/mongodb/data'
[root@node1 ~]# chown -R mongod.mongod /mongodb

#各节点都执行以上操作

启动服务

[root@node1 ~]# service mongod start
Starting mongod:                                           [  OK  ]
[root@node1 mongodb]# ss -tnl | grep 27017
LISTEN     0      128                       *:27017                    *:*   

#各节点启动服务,启动过程中需要初始化数据,故启动较慢

连接数据库做初始化

[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> 

#已成为主节点

添加节点

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
}

创建数据,验证是否同步

#主节点
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等无法满足需求,就需要将数据分片存放,减缓服务器压力。

分片架构

mongodb分片.jpg

实验拓扑

mongodb分片拓扑.jpg

配置过程

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

[root@node1 ~]# service mongod stop
Stopping mongod:                                           [  OK  ]
[root@node1 ~]# rm -rf /mongodb/data/*

#各节点都执行以上操作,若第一次做可忽略

Config Server配置

#安装所需包
[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

修改配置文件

[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

创建数据目录

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

启动服务

[root@node2 ~]# service mongod start
Starting mongod:                                           [  OK  ]
[root@node2 ~]# ss -tnl | grep 27019
LISTEN     0      128                       *:27019                    *:*     

#监听端口已发生改变,不再是27017

Mongos配置

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

启动服务

[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配置

#以为我们第一次实验安装过软件了,下面直接修改配置文件
[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节点

[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" }

对所需对象启用分片功能

#对数据库启用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)

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

mongos> use testdb
switched to db testdb
mongos> for (i=1;i<=100000;i++) db.students.insert({name:"student"+i,age:(i%120),addr:"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在无论大数据处理还是复制方面都有着比MySQL更加优秀的性能和更加简单的操作,但由于MongoDB目前还不是很成熟,在实际的应用中还有许多问题有待解决,相信在未来MongoDB会更加出色。以上仅为个人学习整理,如有错漏,大神勿喷~~~

原创文章,作者:书生,如若转载,请注明出处:http://www.178linux.com/6254

(0)
书生书生
上一篇 2015-07-15 22:27
下一篇 2015-07-16 22:25

相关推荐

  • Linux系统的软链接和硬链接

    Linux的链接是一种共享文件和访问它的用户的若干目录项之间建立联系的一种方法。一共分为两种链接,分别是软链接和硬链接。 一、硬链接 1、硬链接的本质上是一个文件,它们除了名字不一样,其他都一样,占用的空间是一个。硬链接会增加文件的链接数。如下图 (1)建立硬链集之前     (2)建立硬链接之后 2、删去一个链接名,链接数减一…

    Linux干货 2016-10-22
  • OPENSSL加密技术及私有CA的搭建

    加密方式有对称加密 非对称加密 单向加密 对称加密:     加密和加密都用同一个对称密钥,但是,这种加密方法存在一定问题,就是密钥传输时,容易被盗窃。还有密钥管理困难,对称加密的方法:DES、AES、Blowfish、Twofish、IDEA、RC6、CAST5。   非对称加密: 公钥…

    Linux干货 2015-08-17
  • httpd服务归纳:httpd简介与基本安装

    一、httpd 简介  1. httpd 历史: httpd daemon 最早诞生于1995年二月, 伊利诺伊大学香槟分校的美国国家超级计算应用中心(NCSA),由Rob McCool开发。当这个项目完成后,Rob 老兄离开RCSA以后,这个项目组就解散了,这个项目也随之终止。 但是,由Brian Behlendorf 和 Cliff …

    Linux干货 2015-05-07
  • rpm详解

    rpm详解 rpm详解 rpm使用方法 rpm起源 rpm是什么 rpm命名格式 rpm优缺点 rpm获取注意 rpm命令使用 rpm起源  由于在linux中安装应用程序需要源码包编译安装,对于非专业人员而言难度太大,因而出现一种将源码编译好的二进制程序,库文件,配置文件,帮助文件等打包成一个或多个特定格式的程序包,而管理这类包的工具之一,则称为…

    Linux干货 2016-12-23
  • locate,find文件查找

    locate | find *** locate 路径中包含字符串 即匹配;      -n#     指定显示结果前几个      -b      只匹配路径名中的基名      &nbs…

    Linux干货 2016-08-15
  • rsync+inotify实现数据的实时同步更新

      rsync可以实现触发式的文件同步,但是通过crontab守护进程方式进行触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rsync同步,这样就可以解决同步数据的实时性问题。 一、rsync的优点与不足 rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决对实时性要求不高的…

    2018-01-06