MongoDB非关系型数据库

    MongoDB是有C++语言编写的,是一个基于分布式文件存储的开源数据库系统,属于NoSQL。在高负载的情况下,可以添加更多的节点,可以保证服务器的性能。

    MongoDB旨在为WEB应用提供可扩展的高性能数据存储解决方案。

    MongoDB将数据存储为一个文档,数据结构由键值(key-->value)对组成。MongoDB文档类似于JSON对象,字段值可以包含其他文档,数组及文档数组。


MongoDB和关系型数据库对比

SQL术语概念 MongoDB术语概念 解释/说明
database database 数据库
table collection

数据库表/集合

row document

数据记录/文档

column field 数据字段/域
index index 索引
table joins
表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键


MongoDB安装

  • 搭建yum源

# vim /etc/yum.repos.d/mongodb-org-3.0.repo
[mongodb-org-3.0]
name=MongoDB Repository
baseurl=http://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/x86_64/
gpgcheck=0
enabled=1

1、安装mongodb-org

# yum install mongodb-org

Dependencies Resolved

=======================================================================================
 Package                  Arch         Version             Repository             Size
=======================================================================================
Installing:
 mongodb-org              x86_64       3.0.11-1.el6        mongodb-org-3.0       5.8 k
Installing for dependencies:
 mongodb-org-mongos       x86_64       3.0.11-1.el6        mongodb-org-3.0       4.7 M
 mongodb-org-server       x86_64       3.0.11-1.el6        mongodb-org-3.0       9.8 M
 mongodb-org-shell        x86_64       3.0.11-1.el6        mongodb-org-3.0       5.0 M
 mongodb-org-tools        x86_64       3.0.11-1.el6        mongodb-org-3.0        34 M

Transaction Summary
=======================================================================================
Install       5 Package(s)

Total download size: 53 M
Installed size: 166 M
Is this ok [y/N]: y


/etc/init.d/mongod  /etc/mongod.conf  /var/lib/mongo/


/etc/mongod.conf配置文件

processManagement:
  fork: true  
  pidFilePath: /var/run/mongodb/mongod.pid

# network interfaces
net:
  port: 27017
  bindIp:


启动mongodb

# /etc/init.d/mongod start


echo never > /sys/kernel/mm/transparent_hugepage/enabled

echo never > /sys/kernel/mm/transparent_hugepage/defrag

vim /etc/security/limits.conf //加入

mongodb soft nofile 64000

mongodb hard nofile 64000

mongodb soft nproc 32000

mongodb hard nproc 32000

启动:mongodb

启动过程会比较慢,这是它在写数据/var/lib/mongodb


[root@3f63e6ba4d83 ~]# du -sh /var/lib/mongo/

81M/var/lib/mongo/


使用mongod -f /etc/mongod.conf启动方式

[root@3f63e6ba4d83 ~]# /etc/init.d/mongod stop

[root@3f63e6ba4d83 ~]# kill -9 mongodb_pid

[root@3f63e6ba4d83 ~]# ps -ef


root@3f63e6ba4d83 ~]# mongod -f /etc/mongod.conf 

about to fork child process, waiting until server is ready for connections.

forked process: 510

child process started successfully, parent exiting


[root@3f63e6ba4d83 ~]# ps -ef |grep mongo
mongod      546      1  1 00:59 ?        00:00:04 /usr/bin/mongod -f /etc/mongod.conf

[root@3f63e6ba4d83 ~]# netstat -nlp | grep mongo
unix  2      [ ACC ]     STREAM     LISTENING     99391  -                   /tmp/mongodb-27017.sock



连接mongodb

1、在本机可以直接运行命令mongo进入到mongodb shell中

2、如果mongodb监听的端口并不是默认的27017,则在连接的时候加上--port选项,如:

    mongo --port 27018

3、远程连接mongodb,需要加--host,如:mongo --host 127.0.0.1

4、如果设置了验证,则在连接的时候加用户名和密码mongo -uusername -ppasswd

    


mongodb用户管理

  • 首先mongodb用户是针对库来的,建立用户时要先进入傲对应的库里

  • use test   #切换到test库下

  • db.createUser({user:"admin",pwd:"123456",roles:[{role:'dbOwner',db:'userdb'}]})

  • use admin  #切换到admin库

  • db.system.users.find()   #列出所有用户,需要切换到admin库

  • show users   #查看当前库下的所有用户

  • db.dorpUser('admin')   #删除用户

  • 关于用户角色,参考文档http://bbs.51cto.com/thread-1146654-1.html



> use test
switched to db test
> db.createUser({user:"admin",pwd:"123456",roles:[{role:'dbOwner',db:'userdb'}]})
Successfully added user: {
	"user" : "admin",
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "userdb"
		}
	]
}
>


列出所有用户

> use admin
switched to db admin
> db.system.users.find()
{ "_id" : "test.admin", "user" : "admin", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "pMWz7+kTk9/cs/L4BHHT9Q==", "storedKey" : "Hhq0U71m7WhJlg7+s36fTWHl3x0=", "serverKey" : "9lPAV69Kgn3s4GHpQ4qMsFd/7KY=" } }, "roles" : [ { "role" : "dbOwner", "db" : "userdb" } ] }


删除用户,需要切换到对应的库

> use test
switched to db test
> show users;
{
	"_id" : "test.admin",
	"user" : "admin",
	"db" : "test",
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "userdb"
		}
	]
}

> show users;
>


MongoDB库和集合管理


查看版本

> db.version()
3.0.11

查看数据库

> show dbs
admin  0.078GB
local  0.078GB


创建库

switched to db userdb
> show dbs
admin  0.078GB
local  0.078GB
> db.createCollection('name')
{ "ok" : 1 }
> show dbs
admin   0.078GB
local   0.078GB
userdb  0.078GB


删除库

> db.dropDatabase()
{ "dropped" : "userdb", "ok" : 1 }


查看状态

> db.stats()
{
	"db" : "admin",
	"collections" : 5,
	"objects" : 13,
	"avgObjSize" : 67.6923076923077,
	"dataSize" : 880,
	"storageSize" : 36864,
	"numExtents" : 5,
	"indexes" : 4,
	"indexSize" : 32704,
	"fileSize" : 67108864,
	"nsSizeMB" : 16,
	"extentFreeList" : {
		"num" : 0,
		"totalSize" : 0
	},
	"dataFileVersion" : {
		"major" : 4,
		"minor" : 22
	},
	"ok" : 1
}
>



MongoDB创建集合

  • db.createCollection("mycol",{capped:true,autoindexID:true,size:6142800,max:10000})

    #语法:db.createCollection(name,options)

  • name就是集合的名字,options可选,用来配置集合的参数,参数如下:

  • capped true/false(可选)如果为true,则启用封顶集合。封顶集合是固定大小的集合,当它达到其最大大小,会自动覆盖最早的条目。如果指定true,则也需要指定尺寸参数

  • autoindexID true/false(可选)如果为true,自动创建索引_id字段的默认值是false

  • size(可选),指定最大大小字节封顶集合。如果封顶是true,那么还需要指定这个字段。单位B

  • max(可选),指定封顶集合允许在文件的最大数量


1、

> use mydb
switched to db mydb
> db.createCollection("mycol",{capped:true,autoindexID:true,size:6142800,max:10000})
{ "ok" : 1 }


MongoDB数据管理

  • show collections  #查看集合,或者使用show tables

  • db.Account.insert({AccoutID:1,UserName:"123",password:"123456"}) 

#如果集合不存在,直接插入数据,则mongodb会自动创建集合db.Account.update({AccountID:1},{"$set":{"Age":20}})  #更新db.Account.find()   #查看所有文档db.Account.find({AccountID:1})   #根据条件查询db.Account.remove({AccountID:1})  #根据条件删除db.Account.drop()  #删除所有文档,即删除集合use dbname  #先进入对应的库db.printCollectionStats()   #然后查看集合状态



MongoDB副本集搭建

实验准备:三台机器

dnode1:172.17.0.2(primary)

dnode2:172.17.0.3(secondary)

dnode3:172.17.0.4(secondary)



编辑三台机器的配置文件,增加:

replication:
##oplog大小
  oplogSizeMB: 20
##复制集名称
  replSetName: vnode

分别重启三台机器


连接主,在主上运行命令mongo

> use admin

> config={_id:"vnode",members:[{_id:0,host:"172.17.0.2:27017"},{_id:1,host:"172.17.0.3:27017"},{_id:2,host:"172.17.0.4:27017"}]}

> rs.initiate(config)

> rs.add("172.17.0.3")  #手动添加

> rs.add("172.17.0.4")

> rs.status()    #查看状态

如果两个从上的状态为stateStr:"STARTUP",则需要进行如下操作

> var

config={_id:"vnode",members:[{_id:0,host:"172.17.0.2:27017"},{_id:1,host:"172.17.0.3:27017"},{_id:2,host:"172.17.0.4:27017"}]}

> rs.reconfig(config)

此时再次查看rs.status()会发现从的状态变为SECONDARY


> use admin
switched to db admin
> config={_id:"vnode",members:[{_id:0,host:"172.17.0.2:27017"},{_id:1,host:"172.17.0.3:27017"},{_id:2,host:"172.17.0.4:27017"}]}
{
	"_id" : "vnode",
	"members" : [
		{
			"_id" : 0,
			"host" : "172.17.0.2:27017"
		},
		{
			"_id" : 1,
			"host" : "172.17.0.3:27017"
		},
		{
			"_id" : 2,
			"host" : "172.17.0.4:27017"
		}
	]
}


> rs.initiate(config)
{ "ok" : 1 }
vnode:SECONDARY>


查看集群状态:

de:SECONDARY> rs.status()
{
	"set" : "vnode",
	"date" : ISODate("2016-04-04T09:17:10.703Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "172.17.0.2:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 262,
			"optime" : Timestamp(1459761332, 1),
			"optimeDate" : ISODate("2016-04-04T09:15:32Z"),
			"electionTime" : Timestamp(1459761334, 1),
			"electionDate" : ISODate("2016-04-04T09:15:34Z"),
			"configVersion" : 1,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "172.17.0.3:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 97,
			"optime" : Timestamp(1459761332, 1),
			"optimeDate" : ISODate("2016-04-04T09:15:32Z"),
			"lastHeartbeat" : ISODate("2016-04-04T09:17:08.859Z"),
			"lastHeartbeatRecv" : ISODate("2016-04-04T09:17:08.859Z"),
			"pingMs" : 0,
			"configVersion" : 1
		},
		{
			"_id" : 2,
			"name" : "172.17.0.4:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 97,
			"optime" : Timestamp(1459761332, 1),
			"optimeDate" : ISODate("2016-04-04T09:15:32Z"),
			"lastHeartbeat" : ISODate("2016-04-04T09:17:08.861Z"),
			"lastHeartbeatRecv" : ISODate("2016-04-04T09:17:08.861Z"),
			"pingMs" : 0,
			"lastHeartbeatMessage" : "could not find member to sync from",
			"configVersion" : 1
		}
	],
	"ok" : 1
}
vnode:PRIMARY>




vnode:PRIMARY> rs.config()
{
	"_id" : "vnode",
	"version" : 1,
	"members" : [
		{
			"_id" : 0,
			"host" : "172.17.0.2:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : 0,
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "172.17.0.3:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : 0,
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "172.17.0.4:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : 0,
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatTimeoutSecs" : 10,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		}
	}
}
vnode:PRIMARY>



查看从上,变成了SECONDARY状态

root@99caf161a55c ~]# mongo
MongoDB shell version: 3.0.11
connecting to: test
Welcome to the MongoDB shell.
vnode:SECONDARY> 


[root@f3eaa845de59 ~]# mongo
MongoDB shell version: 3.0.11
connecting to: test
Welcome to the MongoDB shell.
vnode:SECONDARY>


MongoDB副本集测试


vnode:PRIMARY> use testdb
switched to db testdb
vnode:PRIMARY> show dbs
admin  0.078GB
local  0.078GB
mydb   0.078GB
vnode:PRIMARY> db.createCollection('test')
{ "ok" : 1 }
vnode:PRIMARY> show dbs
admin   0.078GB
local   0.078GB
mydb    0.078GB
testdb  0.078GB


在从上查看

vnode:SECONDARY> rs.slaveOk()
vnode:SECONDARY> show dbs;
admin   0.078GB
local   0.078GB
mydb    0.078GB
testdb  0.078GB
vnode:SECONDARY> show tables
vnode:SECONDARY> use testdb
switched to db testdb
vnode:SECONDARY> show tables
system.indexes
test


MongoDB副本集更改权重模拟主宕机

默认三台机器权重都为1,如果任何一个权重设置为比其他的高,则该台机器马上切换为primary角色,所以我们预设三台集群的权重分别为:

172.17.0.2:3

172.17.0.3:2

172.17.0.4:1

在主上执行:

cfg=rs.conf()

cfg.members[0].priority=3

cfg.members[1].priority=2

cfg.members[2].priority=1

rs.reconfig(cfg)

这样的话,第二个节点将会成为候选主节点

主上执行:iptables -I INPUT -p tcp --dport 27017 -j DROP



vnode:PRIMARY> cfg=rs.conf()
vnode:PRIMARY> cfg.members[0].priority=3
3
vnode:PRIMARY> cfg.members[1].priority=2
2
vnode:PRIMARY> cfg.members[2].priority=1
1
vnode:PRIMARY> rs.reconfig(cfg)
{ "ok" : 1 }



查看权重

vnode:PRIMARY> rs.config()
{
	"_id" : "vnode",
	"version" : 2,
	"members" : [
		{
			"_id" : 0,
			"host" : "172.17.0.2:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 3,
			"tags" : {
				
			},
			"slaveDelay" : 0,
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "172.17.0.3:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 2,
			"tags" : {
				
			},
			"slaveDelay" : 0,
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "172.17.0.4:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : 0,
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatTimeoutSecs" : 10,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		}
	}
}


测试模拟主节点故障

[root@3f63e6ba4d83 ~]# /etc/init.d/mongod stop
Stopping mongod:

dnode2自动切换为主

vnode:SECONDARY> 
vnode:PRIMARY>


查看状态:

vnode:PRIMARY> rs.status()
{
	"set" : "vnode",
	"date" : ISODate("2016-04-04T09:50:29.433Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "172.17.0.2:27017",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : Timestamp(0, 0),
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2016-04-04T09:50:27.462Z"),
			"lastHeartbeatRecv" : ISODate("2016-04-04T09:46:14.237Z"),
			"pingMs" : 0,
			"lastHeartbeatMessage" : "Failed attempt to connect to 172.17.0.2:27017; couldn't connect to server 172.17.0.2:27017 (172.17.0.2), connection attempt failed",
			"configVersion" : -1
		},
		{
			"_id" : 1,
			"name" : "172.17.0.3:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 2247,
			"optime" : Timestamp(1459763046, 1),
			"optimeDate" : ISODate("2016-04-04T09:44:06Z"),
			"electionTime" : Timestamp(1459763179, 1),
			"electionDate" : ISODate("2016-04-04T09:46:19Z"),
			"configVersion" : 2,
			"self" : true
		},
		{
			"_id" : 2,
			"name" : "172.17.0.4:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2096,
			"optime" : Timestamp(1459763046, 1),
			"optimeDate" : ISODate("2016-04-04T09:44:06Z"),
			"lastHeartbeat" : ISODate("2016-04-04T09:50:29.331Z"),
			"lastHeartbeatRecv" : ISODate("2016-04-04T09:50:29.267Z"),
			"pingMs" : 0,
			"configVersion" : 2
		}
	],
	"ok" : 1
}
vnode:PRIMARY>



MongoDB备份与恢复

mongodb的命令

root@99caf161a55c ~]# mongo

mongo         mongodump     mongofiles    mongooplog    mongorestore  mongostat

mongod        mongoexport   mongoimport   mongoperf     mongos        mongotop


备份


1、备份指定库

  • mongodump -h ip -d dbname -o dir  

   #-h后面跟服务器ip,-d后面跟database名字,不加则备份所有库,-o后指定备份到哪个目录

2、备份所有库

  • mongodump -h ip -o dir

3、备份指定集合

  • mongodump -d mydb -c testc -o /tmp/testc  #-c指定集合名字

4、导出集合为json文件

  • mongoexport -d mydb -c testc -o /tmp/testc.json  #-o后面跟的是一个文件名



创建一个库表,并插入数据

vnode:PRIMARY> use testdb
switched to db testdb
vnode:PRIMARY> show tables
system.indexes
test
vnode:PRIMARY> db.testc.find()
vnode:PRIMARY> db.testc.insert({id:1,name:"dime",age:20})
WriteResult({ "nInserted" : 1 })
vnode:PRIMARY> db.testc.find()
{ "_id" : ObjectId("57023d2df247977956fa195b"), "id" : 1, "name" : "dime", "age" : 20 }
vnode:PRIMARY> 
vnode:PRIMARY> db.testc.insert({id:2,name:"hosx",age:21})
WriteResult({ "nInserted" : 1 })
vnode:PRIMARY> db.testc.find()
{ "_id" : ObjectId("57023d2df247977956fa195b"), "id" : 1, "name" : "dime", "age" : 20 }
{ "_id" : ObjectId("57023d75f247977956fa195c"), "id" : 2, "name" : "hosx", "age" : 21 }
vnode:PRIMARY>


备份testdb库

[root@3f63e6ba4d83 ~]# mongodump -d testdb -o /root/mongodbbak
2016-04-04T06:10:53.652-0400	writing testdb.system.indexes to /root/mongodbbak/testdb/system.indexes.bson
2016-04-04T06:10:53.653-0400	writing testdb.testc to /root/mongodbbak/testdb/testc.bson
2016-04-04T06:10:53.654-0400	writing testdb.test to /root/mongodbbak/testdb/test.bson
2016-04-04T06:10:53.679-0400	writing testdb.test metadata to /root/mongodbbak/testdb/test.metadata.json
2016-04-04T06:10:53.680-0400	writing testdb.testc metadata to /root/mongodbbak/testdb/testc.metadata.json
2016-04-04T06:10:53.684-0400	done dumping testdb.test (0 documents)
2016-04-04T06:10:53.685-0400	done dumping testdb.testc (2 documents)
[root@3f63e6ba4d83 ~]# ls
mongodbbak  nginx-1.8.1.tar.gz

[root@3f63e6ba4d83 ~]# ls mongodbbak/testdb/
system.indexes.bson  test.bson  testc.bson  testc.metadata.json  test.metadata.json


备份所有的库

[root@3f63e6ba4d83 ~]# mongodump -o /root/mongodbbak2


备份一个表

[root@3f63e6ba4d83 ~]# mongoexport -d testdb -c test -o /root/testdb/test.json
[root@3f63e6ba4d83 ~]# ls testdb/
test.json


删除

vnode:PRIMARY> use testdb
switched to db testdb
vnode:PRIMARY> db.dropDatabase()
{ "dropped" : "testdb", "ok" : 1 }


恢复

[root@3f63e6ba4d83 ~]# mongorestore -d testdb /root/mongodbbak/testdb

vnode:PRIMARY> show dbs
admin   0.078GB
local   0.078GB
mydb    0.078GB
testdb  0.078GB

恢复所有

[root@3f63e6ba4d83 ~]# mongorestore /root/mongodbbak2/

[root@3f63e6ba4d83 ~]# mongorestore --dorp /root/mongodbbak2/  #--dorp完全覆盖



PHP连接MongoDB

1、安装PHP的mongo扩展

2、测试mongo扩展


下载mongo扩展

http://pecl.php.net/get/mongo-1.6.13.tgz


安装

[root@3f63e6ba4d83 ~]# tar zxf mongo-1.6.13.tgz 
[root@3f63e6ba4d83 ~]# cd mongo-1.6.13
[root@3f63e6ba4d83 mongo-1.6.13]# /usr/local/php/bin/phpize 
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226

[root@3f63e6ba4d83 mongo-1.6.13]# ./configure --with-php-config=/usr/local/php/bin/php-config 
[root@3f63e6ba4d83 mongo-1.6.13]# make
[root@3f63e6ba4d83 mongo-1.6.13]# make install
Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/

[root@3f63e6ba4d83 mongo-1.6.13]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
mongo.so  opcache.a  opcache.so


[root@3f63e6ba4d83 mongo-1.6.13]# cp /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/mongo.so /usr/local/php/ext/

ls /usr/local/php/ext/
mongo.so


[root@3f63e6ba4d83 html]# vim /usr/local/php/etc/php.ini 
extension_dir = "/usr/local/php/ext"
extension = mongo.so
extension = opcache.so

[root@3f63e6ba4d83 html]# mkdir /usr/local/php/ext


查看

[root@3f63e6ba4d83 mongo-1.6.13]# /usr/local/php/bin/php -m |grep mongo
mongo


[root@3f63e6ba4d83 ~]# /etc/init.d/php-fpm restart
Gracefully shutting down php-fpm . done
Starting php-fpm  done


创建测试文件

[root@3f63e6ba4d83 ~]# vim /usr/local/nginx/html/mongo.php
testdb;
echo "Database testdb selected";

?>


访问

[root@dime ~]# curl http://192.168.1.15:32770/mongo.php
Connection to database successfullyDatabase testdb selected