首页 > 技术文章 > Mongodb数据库基础

xuhao0705 2020-12-15 19:45 原文

摘要

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB是一款跨平台、面向文档的数据库。可以实现高性能、高可用性,并且能够轻松扩展,是一个基于分布式文件存储的开源数据库系统,在高负载的情况下,添加更多的节点可以保证服务器的性能。

在大数据时代中,大数据量的处理已经成了考量一个数据库最重要的原因之一。MongoDB的一个主要目标就是尽可能的让数据库保持卓越的性能,这很大程度地决定了MongoDB的设计。MongoDB选择了最大程度而利用内存资源用作缓存来换取卓越的性能,并且会自动选择速度最快的索引来进行查询。MongoDB尽可能精简数据库,将尽可能多的操作交给客户端,这种方式也是MongoDB能够保持卓越性能的原因之一。

MongoDB是非关系性数据库(NoSQL)中功能最丰富,最像关系数据库的。不采用关系模型是为了获取更好的扩展性,MongoDB不在有“行”的概念,其运行方式主要基于两个概念:集合(collection)和文档(document)。

一、Mongodb概述

1.1、特点

Mongo是一个高性能,开源,无模式的文档型数据库,它在许多场景下可用于替代传统的关系型数据库或键/值存储方式。

①面向集合的存储:适合存储对象及JSON形式的数据。

②MongoDB安装简单,提供了面向文档的存储功能,操作起来比较容易。

③MongoDB提供了复制,高可用性和自动分片功能。如果负载增加(需要更多的存储空间和更强的处理能力),它可以分布在计算机网络中的其他节点上,这就是所谓的分片。

④MongoDB支持丰富的查询表达式。

⑤高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)。

1.2、适用场景

MongoDB可以为Web应用提供可扩展的高性能数据存储解决方案。MongoDB主要适用领域有网站数据、分布式场景、数据缓存和JSON文档格式存储。适合大数据量、高并发、弱事务的互联网应用,其内置的水平扩展机制提供了从几百万到十亿级别的数据处理能力,可以很好的满足Web2.0和移动互联网应用数据存储的要求。

1.3、redis和mongodb对比

MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于二者在内存映射的处理过程,持久化的处理方法不同。

MongoDB建议集群部署,更多的考虑到集群方案,Redis更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。

比较指标 MongoDB Redis 比较说明
实现语言 c++ c/c++ -
协议 BSON,自定义二进制 类telnet -
性能 依赖内存,TPS较高 依赖内存,TPS非常高 Redis优于MongoDB
可操作性 丰富的数据表达,索引;最类似于关系型数据库,支持丰富的查询语句 数据丰富,较少的IO MongoDB优于Redis
内存及存储 适合大数据量存储,依赖系统虚拟内存,采用镜像文件存储;内存占用率比较高,官方建议独立部署在64位系统 Redis2.0后支持虚拟内存特性(VM) 突破物理内存限制;数据可以设置时效性,类似于memcache 不同的应用场景,各有千秋
可用性 支持master-slave,replicatset(内部采用paxos选举算法,自动故障恢复),auto sharding机制,对客户端屏蔽了故障转移和切片机制 依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制;不支持auto sharding,需要依赖程序设定一致性hash机制 MongoDB优于Redis;单点问题上,MongoDB应用简单,相对用户透明,Redis比较复杂,需要客户端主动解决.(MongoDB一般使用replicasets和sharding相结合,replicasets侧重高可用性以及高可靠,sharding侧重性能,水平扩展)
可靠性 从1.8版本后,采用binlog方式(类似Mysql) 支持持久化 依赖快照进行持久化;AOF增强可靠性;增强性的同时,影响访问性能

 

一致性 不支持事务,靠客户端保证 支持事务,比较脆,仅能保证事务中的操作按顺序执行 Redis优于MongoDB
数据分析 内置数据分析功能(mapreduce) 不支持 MongoDB优于Redis
应用场景 海量数据的访问效率提升 较小数据量的性能和运算 MongoDB优于Redis

 

二、安装mongodb

2.1、配置官方yum源安装mongodb

 1 [root@server1 ~]# cd /etc/yum.repos.d/
 2 [root@server1 yum.repos.d]# vim mongodb-org.repo
 3 [mongodb]
 4 name=mongodb
 5 baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
 6 gpgcheck=1
 7 enabled=1
 8 gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc
 9 [root@server1 yum.repos.d]# yum list
10 [root@server1 yum.repos.d]# yum -y install mongodb-org

2.2、修改配置文件监听地址

1 [root@server1 ~]# vim /etc/mongod.conf
2 ...省略内容
3 net: 
4   port: 27017       #监听端口
5   bindIp: 0.0.0.0  #监听地址,原来是127.0.0.1,只能本地访问,换成0.0.0.0,任意都能访问

2.3、启动服务mongod.service

1 [root@server1 ~]# systemctl start mongod.service
2 [root@server1 ~]# systemctl stop firewalld.service
3 [root@server1 ~]# setenforce 0
4 [root@server1 ~]# mongo   #输入mongo就进入数据库了
5 ...省略内容
6 > show dbs    #查看有哪几个库
7 admin   0.000GB
8 config  0.000GB
9 local   0.000GB

三、如何配置多实例

3.1、复制配置文件以创建新实例

 1 [root@server1 ~]# cd /etc/
 2 [root@server1 etc]# cp -p mongod.conf mongod2.conf
 3 [root@server1 etc]# vim mongod2.conf
 4 ...省略内容
 5 path: /data/mongodb/mongod2.log
 6 dbPath: /data/mongodb/mongo
 7 port: 27018
 8 [root@server1 etc]# mkdir -p /data/mongodb
 9 [root@server1 etc]# cd /data/mongodb/
10 [root@server1 mongodb]# touch mongod2.log
11 [root@server1 mongodb]# mkdir mongo

3.2、启动创建的实例

1 [root@lserver1 mongodb]# mongod -f /etc/mongod2.conf   
2 about to fork child process, waiting until server is ready for connections.
3 forked process: 15821
4 child process started successfully, parent exiting
5 [root@server1 mongodb]# mongo --port 27018     #登录监听端口为27018的数据库
6 > db.version()    #可以查看版本
7 3.6.19

四、基本操作

4.1、增删改查操作实例

 1 > use school      #mongodb中无需创建,直接使用(在里面创建了集合show dbs才能看到)
 2 switched to db school
 3 > db.createCollection('info')   #在school库中创建集合info
 4 { "ok" : 1 }
 5 > db.info.insert({"id":1,"name":"zhangsan","score":78,"hobby":["game","sport"]})  #在集合中插入数据
 6 WriteResult({ "nInserted" : 1 })
 7 > db.info.find()        #查看info集合中的所有内容
 8 { "_id" : ObjectId("5f56e212cd5781b1ba9d5426"), "id" : 1, "name" : "zhangsan", "score" : 78, "hobby" : [ "game", "sport" ] }
 9 > a=db.info.find()    #创建a是db.info.find() 的别名
10 { "_id" : ObjectId("5f56e212cd5781b1ba9d5426"), "id" : 1, "name" : "zhangsan", "score" : 78, "hobby" : [ "game", "sport" ] }
11 
12 > for(var i=2;i<=100;i++)db.info.insert({"id":i,"name":"jack"+i})  #利用循环一次性创建多个数据
13 WriteResult({ "nInserted" : 1 })
14 > db.info.find()
15 { "_id" : ObjectId("5f56e212cd5781b1ba9d5426"), "id" : 1, "name" : "zhangsan", "score" : 78, "hobby" : [ "game", "sport" ] }
16 { "_id" : ObjectId("5f56e319cd5781b1ba9d5427"), "id" : 2, "name" : "jack2" }
17 { "_id" : ObjectId("5f56e319cd5781b1ba9d5428"), "id" : 3, "name" : "jack3" }
18 { "_id" : ObjectId("5f56e319cd5781b1ba9d5429"), "id" : 4, "name" : "jack4" }
19 ...省略内容
20 Type "it" for more
21 
22 > db.info.findOne({"id":3})     #利用关键字查找单条记录
23 { "_id" : ObjectId("5f56e319cd5781b1ba9d5428"), "id" : 3, "name" : "jack3" }
24 > a=db.info.findOne({"id":2})
25 { "_id" : ObjectId("5f56e319cd5781b1ba9d5427"), "id" : 2, "name" : "jack2" }
26 > typeof(a.id)
27 number
28 > typeof(a.name)     #查看某个字段的类型
29 string
30 > db.info.update({"id":10},{$set:{"name":"tom"}})   #对id=10的记录进行修改
31 WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
32 > a=db.info.findOne({"id":10})
33 { "_id" : ObjectId("5f56e319cd5781b1ba9d542f"), "id" : 10, "name" : "tom" }
34 > db.createCollection('test')
35 { "ok" : 1 }
36 > show collections
37 info
38 test
39 > db.test.drop()       #删除集合
40 true
41 > show collections   #查看集合;等于show tables
42 info
43 > use myscool
44 switched to db myscool
45 > db.createCollection('test')
46 { "ok" : 1 }
47 > show dbs
48 admin    0.000GB
49 config   0.000GB
50 local    0.000GB
51 myscool  0.000GB
52 school   0.000GB
53 > db.dropDatabase()     #删除库myschool,要先use myschool
54 { "dropped" : "myscool", "ok" : 1 }
55 > show dbs
56 admin   0.000GB
57 config  0.000GB
58 local   0.000GB
59 school  0.000GB

4.2、在同一实例中复制数据库

1 > db.copyDatabase("school","share")   #拷贝school库,新建库名为share
2 { "ok" : 1 }

4.3、进程管理

1 > db.currentOp()
2 ...省略内容
3  "opid" : 880,     #找到进程号
4 > db.killOp(880)

五、导出、导入操作

 1 导出操作:
 2 [root@server1 mongodb]# mongoexport -d school -c info -o /opt/school.json
 3 2020-12-12T10:10:38.155+0800    connected to: localhost
 4 2020-12-12T10:10:38.156+0800    exported 100 records
 5 -d:指定数据库
 6 -c:指定数据库中的集合
 7 文件名要以.json结尾
 8 
 9 导入操作:
10 [root@server1 mongodb]# mongoimport -d school -c test --file /opt/school.json 
11 2020-12-12T10:11:56.382+0800    connected to: localhost
12 2020-12-12T10:11:56.388+0800    imported 100 documents
13 
14 仅导出某一行:
15 [root@server1 mongodb]# mongoexport -d school -c info -q '{"id":{"$eq":10}}' -o /opt/test.json

六、备份与恢复数据库

6.1、备份库school

 1 [root@server1 mongodb]# mongodump -d school -o /backup/     
 2 2020-12-12T10:16:47.324+0800    writing school.info to
 3 2020-12-12T10:16:47.324+0800    writing school.test to
 4 2020-12-12T10:16:47.325+0800    done dumping school.test (100 documents)
 5 2020-12-12T10:16:47.325+0800    done dumping school.info (100 documents)
 6 [root@server1 mongodb]# cd /backup/
 7 [root@server1 backup]# ls
 8 school
 9 [root@server1 backup]# cd school/
10 [root@server1 school]# ls
11 info.bson  info.metadata.json  test.bson  test.metadata.json

6.2、恢复到abc库(如果库不存在则直接创建)

1 [root@server1 school]# mongorestore -d abc --dir /backup/school/   

七、实例间克隆集合

创建完27018端口的实例后进行克隆集合操作
27018端口的实例克隆2701端口的实例school库中的info集合

 1 [root@server1 etc]# mongo --port 27018
 2 > show dbs
 3 admin   0.000GB
 4 config  0.000GB
 5 local   0.000GB
 6 > db.runCommand({"cloneCollection":"school.info","from":"20.0.0.10:27017"})
 7 { "ok" : 1 }
 8 > show dbs
 9 admin   0.000GB
10 config  0.000GB
11 local   0.000GB
12 school  0.000GB
13 > use school
14 switched to db school
15 > show tables     #克隆成功
16 info

总结

通过Redis与Mongodb对比,可以了解非关系型数据库的优缺点,进行Mongodb的一些常规操作来快速了解Mongodb

推荐阅读