前言
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: 仲裁者
复制集架构
实验拓扑
#系统环境: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等无法满足需求,就需要将数据分片存放,减缓服务器压力。
分片架构
实验拓扑
配置过程
因为以上做过实验我们首先来清理一下数据
[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