深夜博文,满满干活
- MongoDB概述
- 1.MongoDB的优点
- 2.MongoDB主要特性
- 3.MongoDB 使用场景
- MongoDB基础操作
- 1.安装MongoDB
- 2.单台服务器配置多实例
- 3.MongoDB基本操作
- 3.1进入数据库
- 3.2创建表 (db.createCollection命令创建)
- 3.3插入数据(可以for循环)
- 3.4设置别名【count()统计】
- 3.5修改值,删表,删库
- MongoDB升级操作
- 1.数据导出与导出
- 1.1导出MongoDB中的数据(mongoexport命令)
- 1.2导入数据到MongoDB(mongoimport 命令)
- 1.3根据条件导出数据(mongoexport命令)
- 2.备份与恢复(mongodump,mongorestore)
- 3.复制数据库(db.copyDatabase)
- 4.克隆集合(db.runCommand)
- 5.创建多实列(4台)另一种方法
- 6.创建管理用户(admin库中)
- 进程管理
MongoDB概述
MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统。没错MongoDB就是数据库,是NoSQL类型的数据库
1.MongoDB的优点
- MongoDB提出的是文档、集合的概念,使用BSON(类JSON)作为其数据模型结构,其结构是面向对象的而不是二维表,存储一个用户在MongoDB中是这样子的
{username:'123',password:'123'
}
使用这样的数据模型,使得MongoDB能在生产环境中提供高读写的能力,吞吐量较于mysql等SQL数据库大大增强
-
易伸缩,自动故障转移。易伸缩指的是提供了分片能力,能对数据集进行分片,数据的存储压力分摊给多台服务器。自动故障转移是副本集的概念,MongoDB能检测主节点是否存活,当失活时能自动提升从节点为主节点,达到故障转移
-
数据模型因为是面向对象的,所以可以表示丰富的、有层级的数据结构,比如博客系统中能把“评论”直接怼到“文章“的文档中,而不必像myqsl一样创建三张表来描述这样的关系
2.MongoDB主要特性
-
(1)文档数据类型:
可以让数据的存储数据结构更灵活,存储速度更加快 -
(2)即时查询能力:
MongoDB保留了关系型数据库即时查询的能力,保留了索引(底层是基于B tree)的能力 -
(3)复制能力:
MongoDB自身提供了副本集能将数据分布在多台机器上实现冗余,目的是可以提供自动故障转移、扩展读能力 -
(4)
速度与持久性:MongoDB的驱动实现一个写入语义:发射后不管 ,即通过驱动调用写入时,可以立即得到返回得到成功的结果(即使是报错),这样让写入的速度更加快,当然会有一定的不安全。
MongoDB提供了Journaling日志的概念,实际上像mysql的bin-log日志,当需要插入的时候会先往日志里面写入记录,再完成实际的数据操作,这样如果出现停电,进程突然中断的情况,可以保障数据不会错误,可以通过修复功能读取Journaling日志进行修复 -
(5)数据扩展:
MongoDB使用分片技术对数据进行扩展,MongoDB能自动分片、自动转移分片里面的数据块,让每一个服务器里面存储的数据都是一样大小 -
(6)C/S服务模型:
MongoDB核心服务器主要是通过mongod程序启动的,而且在启动时不需对MongoDB使用的内存进行配置,因为其设计哲学是内存管理最好是交给操作系统,缺少内存配置是MongoDB的设计亮点,另外,还可通过mongos路由服务器使用分片功能。
MongoDB的主要客户端是可以交互的js shell 通过mongo启动,使用js shell能使用js直接与MongoDB进行交流,像使用sql语句查询mysql数据一样使用js语法查询MongoDB的数据,另外还提供了各种语言的驱动包,方便各种语言的接入
3.MongoDB 使用场景
-
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
-
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB
内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。 -
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
-
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
-
视频直播,使用 MongoDB 存储用户信息、礼物信息等
可以用以下几个选择题来辅助决策:
应用不需要事务及复杂 join 支持 必须 Yes |
---|
新应用,需求会变,数据模型无法确定,想快速迭代开发 ? |
应用需要2000-3000以上的读写QPS(更高也可以) ? |
应用需要TB甚至 PB 级别数据存储 ? |
应用发展迅速,需要能快速水平扩展 ? |
应用要求存储的数据不丢失 ? |
应用需要99.999%高可用 ? |
应用需要大量的地理位置查询、文本查询 ? |
MongoDB基础操作
1.安装MongoDB
##配置MongoDB安装的yum源
[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost etc]# vi Mongo.repo
[mongodb-org]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc[root@localhost etc]# yum clean all
[root@localhost etc]# yum list##yum安装
[root@localhost etc]# yum install -y mongodb-org
###修改配置文件###
[root@localhost etc]# vi /etc/mongodb.confsystemLog: ##系统日志文件存放位置destination: filelogAppend: truepath: /var/log/mongodb/mongod.log ##日志文件位置storage: ##存储引擎dbPath: /var/lib/mongo ##数据存储文件位置enabled: trueprocessManagement: ##进程管理fork: true # fork and run in backgroundpidFilePath: /var/run/mongodb/mongod.pid ##PID文件位置timeZoneInfo: /usr/share/zoneinfonet: ##网络接口port: 27017 ##端口号bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces.##绑定的监听IP,修改成任意都能访问[root@localhost ~]# systemctl start mongod
[root@localhost ~]# netstat -anpt |grep 27017
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 1210/mongod ##进入数据库
[root@localhost ~]# mongo
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> exit
bye
2.单台服务器配置多实例
##可以使用cp -p /etc/mongod.conf /etc/mongod{1..n}.conf 的方式创建n个实例配置文件进行修改,这里就创建一个做示范[root@localhost ~]# cp -p /etc/mongod.conf /etc/mongod2.conf ## cp配置第二实例
[root@localhost ~]# vim /etc/mongod2.conf ##对实例2进行配置修改
systemLog:destination: filelogAppend: truepath: /data/mongodb/mongod2.log ##修改实例2的日志文件位置storage:dbPath: /data/mongodb/mongo ##修改实例2的数据存放目录journal:enabled: truenet:port: 27018 ##修改端口号,与实例一区分开[root@localhost ~]# mkdir -p /data/mongodb/
[root@localhost ~]# cd /data/mongodb/
[root@localhost mongodb]# mkdir mongo ##创建数据存放目录
[root@localhost mongodb]# touch mongod2.log ##创建日志文件
[root@localhost mongodb]# chmod 777 mongod2.log ##给予最高权限,权限一定要给,否则服务无法启动###启动实例2,mongod这个命令就在/usr/bin下面###
[root@localhost mongodb]# mongod -f /etc/mongod2.conf
about to fork child process, waiting until server is ready for connections.
forked process: 2226
child process started successfully, parent exiting[root@localhost mongodb]# netstat -anpt |grep 27017
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 2335/mongod
[root@localhost mongodb]# netstat -anpt |grep 27018
tcp 0 0 0.0.0.0:27018 0.0.0.0:* LISTEN 2226/mongod ##进入实例2,如果直接用mongo会进27017###
[root@localhost mongodb]# mongo --port 27018
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> db.version() ###这条命令可以查看版本
3.6.20
> exit
bye
3.MongoDB基本操作
3.1进入数据库
##use命令
##注意:在MySQL中,创建表需要先建立库,而在MongoDB中,不需要创建库,直接就可以进入库。但是必须在库中建立集合(相当于表),该库才会真正存在,否则空库不会被创建。
[root@localhost ~]# mongo --port 27018
> use school ##进入school库
switched to db school
> show dbs ##查看所有库(school并没有被真正创建,只是在一个缓存空间中被使用)
admin 0.000GB
config 0.000GB
local 0.000GB
3.2创建表 (db.createCollection命令创建)
> db.createCollection('info') ##创建info集合,说白了就是表
{ "ok" : 1 }
> show dbs ##再次查看库,此时school库在真正创建了
admin 0.000GB
config 0.000GB
local 0.000GB
school 0.000GB查看所有集合(show collections命令)
> use school ##进入库
switched to db school
> show collections ##查看集合(也就是表的意思)
info
3.3插入数据(可以for循环)
##格式:("db.集合名.insert({"键名1":值1,"键2":值2,...})"命令),"键":["值1","值2"],这个称为字符串数组
##MongoDB支持给键赋值数组,以[]的形式(常规数组中的值必须是同类型的,但是在MongoDB中,数组内的值类型可以不一致,可以有整形也可以有字符串)> db.info.insert({"id":1,"name":"zhangsan","score":78,"hobby":["sport","game"]})
WriteResult({ "nInserted" : 1 }) ##一条数据插入成功##查看数据,查看数据用的“杰克瑞”,可以看到它自动给了你一个id:5fa6cc0d3f6b41cab5f918f6
> db.info.find()
{ "_id" : ObjectId("5fa6cc0d3f6b41cab5f918f6"), "id" : 1, "name" : "zhangsan", "score" : 78, "hobby" : [ "sport", "game" ] }##利用for循环,批量插入数据
> for(var i=2;i<=50;i++)db.info.insert({"id":i,"name":"test"+i})
WriteResult({ "nInserted" : 1 })##查看集合数据信息 (使用"db.集合名.find()"命令)
> db.info.find()
{ "_id" : ObjectId("5fa66e2b2f7e809adf86d554"), "id" : 1, "name" : "zhangsan", "score" : 78, "hobby" : [ "sport", "game" ] }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce2"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce3"), "id" : 3, "name" : "test3" }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce4"), "id" : 4, "name" : "test4" }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce5"), "id" : 5, "name" : "test5" }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce6"), "id" : 6, "name" : "test6" }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce7"), "id" : 7, "name" : "test7" }
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce8"), "id" : 8, "name" : "test8" }
……//“_id”是数据库分配的id,值是密文//##最多可以看20条,如果你想看更多的,输入it
3.4设置别名【count()统计】
##给info表设置别名,指定记录设置别名(“别名=”的方式设置别名)>a=db.info.findOne()
{"_id" : ObjectId("5fa6cc0d3f6b41cab5f918f6"),"id" : 1,"name" : "zhangsan","score" : 78,"hobby" : ["sport","game"]
}##()内结合{}可以进行精确查找
> a=db.info.findOne({"id":30})
{ "_id" : ObjectId("5fa6881bbdb71a8082419cfe"), "id" : 30, "name" : "test30" }##查看数值属性类型
> typeof(a.id)
number ##数据类型
> typeof(a.name)
string ##字符串类型
> typeof(a.hobby)
object ##数组类型> db.info.findOne({"name":"test5"}) ##同样是精确查找
{ "_id" : ObjectId("5fa6881bbdb71a8082419ce5"), "id" : 5, "name" : "test5" }##统计集合中的记录("db.集合名.count()"命令)
> db.info.count()
50
3.5修改值,删表,删库
## 修改值("db.集合名.update({$set:键:新值})"命令修改)##
##查看info集合数据
> db.info.find({"id":10})
{ "_id" : ObjectId("5fa693f7767390befaef3f9b"), "id" : 10, "name" : "test10" }##修改更新数据##
> db.info.update({"id":10},{$set:{"name":"ZHANGSAN"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })##再次查看##
> db.info.find({"id":10})
{ "_id" : ObjectId("5fa693f7767390befaef3f9b"), "id" : 10, "name" : "ZHANGSAN" }##删除集合(“db.集合名.drop”)##
> db.info.drop()
true##删除库("db.集合名.drop()"命令)##
>use school ##首先要进入school库
>db.dropDatabase() ##删除school库
{ "dropped" : "school", "ok" : 1 }##退出数据库(exit命令)##
> exit
bye
MongoDB升级操作
1.数据导出与导出
1.1导出MongoDB中的数据(mongoexport命令)
[root@localhost ~]# mongo
> use school
switched to db school
> for(var i=2;i<=50;i++)db.info.insert({"id":i,"name":"test"+i})
WriteResult({ "nInserted" : 1 })
> exit
bye##要导入到出,首先退出数据库,注意导出的文件必须死.json格式,否则无法将数据导回去
[root@localhost ~]# mongoexport -d school -c info -o /opt/school.json
2020-11-07T22:03:13.007+0800 connected to: localhost
2020-11-07T22:03:13.008+0800 exported 49 records
#### mongoexport命令参数含义如下 #############
-d :指定数据库
-c :指定集合
-o :输出到文件中
#############################################[root@localhost ~]# cd /opt
[root@localhost opt]# ls ##查看输出的文件
rh school.json
[root@localhost opt]# vi school.json ##可以查看到MongoDB集合中的信息
{"_id":{"$oid":"5fa6a8ef8d1138e3f30deb8b"},"id":2.0,"name":"test2"}
{"_id":{"$oid":"5fa6a8ef8d1138e3f30deb8c"},"id":3.0,"name":"test3"}
{"_id":{"$oid":"5fa6a8ef8d1138e3f30deb8d"},"id":4.0,"name":"test4"}
{"_id":{"$oid":"5fa6a8ef8d1138e3f30deb8e"},"id":5.0,"name":"test5"}
{"_id":{"$oid":"5fa6a8ef8d1138e3f30deb8f"},"id":6.0,"name":"test6"}
……省略部分
1.2导入数据到MongoDB(mongoimport 命令)
##注意,文件必须是.json格式,导入数据可以自动创建新库新集合
[root@localhost opt]# mongoimport -d sco -c stu --file school.json
2020-11-07T22:14:39.490+0800 connected to: localhost
2020-11-07T22:14:39.509+0800 imported 49 documents[root@localhost ~]# mongo
> show dbs ##查看所有库
admin 0.000GB
config 0.000GB
local 0.000GB
school 0.000GB
sco 0.000GB> use sco
switched to db sco##查看所有集合
> show collections
stu##查看stu集合中的数据
> db.stu.find()
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8b"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8c"), "id" : 3, "name" : "test3" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8d"), "id" : 4, "name" : "test4" }
……省略部分
1.3根据条件导出数据(mongoexport命令)
##mongoexport结合-q指定条件,-q可以指定行
##eq:等于 gt:大于 lt:小于[root@localhost opt]# mongoexport -d school -c info -q '{"id":{"$eq":10}}' -o /opt/list.json
2020-11-07T22:35:42.703+0800 connected to: localhost
2020-11-07T22:35:42.703+0800 exported 1 record[root@localhost opt]# ls
list.json rh school.json##导出来一条符合条件的数据
[root@localhost opt]# vim list.json
{"_id":{"$oid":"5fa6a8ef8d1138e3f30deb93"},"id":10.0,"name":"test10"}
2.备份与恢复(mongodump,mongorestore)
##备份库##
[root@localhost opt]# mkdir backup[root@localhost opt]# mongodump -d school -o backup/
2020-11-07T23:07:57.457+0800 writing school.info to
2020-11-07T23:07:57.457+0800 done dumping school.info (49 documents)[root@localhost opt]# cd backup/
[root@localhost backup]# ls
school##里面有json文件
[root@localhost backup]# ls school/
info.bson info.metadata.json## 模拟故障,删除school库 ##
[root@localhost ~]# mongo
> use school
switched to db school
> db.dropDatabase()
{ "dropped" : "school", "ok" : 1 }## 恢复库, 还原数据(库不一定必须是原来的库名,可以重新指定)##
[root@localhost ~]# mongorestore -d school --dir=/backup/school
2020-11-07T23:16:28.647+0800 the --db and --collection args should only be used when restoring from ...
2020-11-07T23:16:28.648+0800 building a list of collections to restore from /backup/school dir
2020-11-07T23:16:28.648+0800 reading metadata for school.info from /backup/school/info.metadata.json
2020-11-07T23:16:28.653+0800 restoring school.info from /backup/school/info.bson
2020-11-07T23:16:28.655+0800 no indexes to restore
2020-11-07T23:16:28.655+0800 finished restoring school.info (49 documents)
2020-11-07T23:16:28.655+0800 done##进入库中查看数据##
[root@localhost school]# mongo
> show dbs
……省略部分
school 0.000GB
sco 0.000GB
> use school
switched to db school
> db.info.find()
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8b"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8c"), "id" : 3, "name" : "test3" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8d"), "id" : 4, "name" : "test4" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8e"), "id" : 5, "name" : "test5" }
……省略部分
3.复制数据库(db.copyDatabase)
##复制school库数据到school-bak库[root@localhost ~]# mongo
> db.copyDatabase("school","school-bak")
{ "ok" : 1 }##进入school-bak 备份库
> use school-bak
switched to db school-bak
> show collections ##查看集合,无误
info
> db.info.find()
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8b"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8c"), "id" : 3, "name" : "test3" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8d"), "id" : 4, "name" : "test4" }
……省略部分
4.克隆集合(db.runCommand)
##进入实例mongodb2
[root@localhost ~]# mongo -port 27018
> show dbs ##查看库,现在只有三个库
admin 0.000GB
config 0.000GB
local 0.000GB##从20.0.0.21:27017那里school库中克隆info集合
> db.runCommand ({"cloneCollection":"school.info","from":"192.168.10.10:27017"})
{ "ok" : 1 }##再次查看,多出了school库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
school 0.000GB> use school
switched to db school## 看看集合
> show collections
info##查看数据,数据完整
> db.info.find()
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8b"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5fa6a8ef8d1138e3f30deb8c"), "id" : 3, "name" : "test3" }
……省略部分
5.创建多实列(4台)另一种方法
####因为我现在已经有1和2了,所以只需要创建3和4就行了#######创建数据目录
[root@localhost ~]# mkdir -p /data/mongodb/mongodb{3,4}
[root@localhost ~]# cd /data/mongodb/
[root@localhost mongodb]# ls
mongodb mongodb2 mongodb3 mongodb4##创建日志目录
[root@localhost mongodb]# mkdir logs
[root@localhost mongodb]# touch logs/mongodb{3,4}.log
[root@localhost mongodb]# cd logs/
[root@localhost logs]# ls
mongodb3.log mongodb4.log##赋予权限
[root@localhost logs]# chmod 777 *.log ###复制配置文件#####
[root@localhost etc]# cp -p mongod.conf mongod3.conf
[root@localhost etc]# cp -p mongod.conf mongod4.conf ####进入配置文件修改:日志文件路径,数据路径,端口号,修改的路径是你上面创建好的####
####首先修改mongod3的#####
[root@localhost etc]# vim mongod3.conf
10 path: /data/mongodb/logs/mongodb3.log
14 dbPath: /data/mongodb/mongodb3
29 port: 27019###开启mongod3实列####
[root@localhost etc]# mongod -f /etc/mongod3.conf
about to fork child process, waiting until server is ready for connections.
forked process: 43804
child process started successfully, parent exiting####修改mongod4的#####
[root@localhost etc]# vim mongod4.conf
10 path: /data/mongodb/logs/mongodb4.log
14 dbPath: /data/mongodb/mongodb4
29 port: 27020###开启mongod4实列####
[root@localhost etc]# mongod -f /etc/mongod4.conf
about to fork child process, waiting until server is ready for connections.
forked process: 43804
child process started successfully, parent exiting###依次进入mongod实列####
[root@localhost etc]# mongo ##MongoDB1
[root@localhost etc]# mongo --port 27018 ##MongoDB2
[root@localhost etc]# mongo --port 27019 ##MongoDB3
[root@localhost etc]# mongo --port 27020 ##MongoDB4
6.创建管理用户(admin库中)
##管理用户默认存放在admin库中> use admin
switched to db admin##创建管理用户,roles表示指定角色
> db.createUser({"user":"root","pwd":"123456","roles":["root"]})
Successfully added user: { "user" : "root", "roles" : [ "root" ] }##使用密码认证,正确返回值为1(前提是配置文件中要开启验证功能,否则无意义)
> db.auth("root","123456")
1##密码错误会返回值0
> db.auth("root","1234")
Error: Authentication failed.
0
进程管理
###current表示当前,可以查看当前进程(显示信息中的opid记录)> db.currentOp()
{ "inprog" : [……省略部分"opid" : 7926, ##主要关注的就是这个PID号进程……省略部分
}##这条命令可以关闭进程,()中填刚刚查询到的opid号
##注意,这并不是关闭数据库,只是关闭当前进程,关闭后还会生成新的进程的,针对当前处理量过大时采用的应急措施,相当于清空垃圾进程
> db.killOp(7926)
{ "info" : "attempting to kill op", "ok" : 1 }