MongoDB
noSQL数据库
特点
- 数据文件存储格式为 BSON (JSON 的扩展)
{“name”:“joe”}这是 BSON 的例子,其中"name"是键,"joe"是值。键值对组成了 BSON 格式。 - 面向集合存储,易于存储对象类型和 JSON 形式的数据
所谓集合(collection)有点类似一张表格,区别在于集合没有固定的表头。 - 模式自由
一个集合中可以存储一个键值对的文档,也可以存储多个键值对的文档,还可以存储键不一样
的文档,而且在生产环境下可以轻松增减字段而不影响现有程序的运行。 - 支持动态查询
MongoDB 支持丰富的查询表达式,查询语句使用 JSON 形式作为参数,可以很方便地查询内嵌
文档和对象数组 - 完整的索引支持
- 支持复制和故障恢复
MongoDB 数据库从节点可以复制主节点的数据,主节点所有对数据的操作都会同步到从节点,
从节点的数据和主节点的数据是完全一样的,以作备份。当主节点发生故障之后,从节点可以升级
为主节点,也可以通过从节点对故障的主节点进行数据恢复 - 二进制数据存储
MongoDB 使用传统高效的二进制数据存储方式,可以将图片文件甚至视频转换成二进制的数据
存储到数据库中 - 自动分片
自动分片功能支持水平的数据库集群,可动态添加机器。分片的功能实现海量数据的分布式存
储,分片通常与复制集配合起来使用,实现读写分离、负载均衡,当然如何选择片键是实现分片功
能的关键。 - MongoDB 使用的是内存映射存储引擎。
MongoDB 会把磁盘 IO 操作转换成内存操作,如果是读操作,内存中的数据起到缓存的作用:
如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。但坏
处是没有办法很方便地控制 MongoDB 占多大内存,MongoDB 会占用所有能用的内存,所以最好不
要把别的服务和 MongoDB 放在同一台服务器部署
原理简介
MongoDB 存取读写速度快,甚至可以用来当作缓存数据库。但是在使用过程中会发现 MongoDB
服务非常占内存,几乎是服务器有多少内存就会占用多少内存。为什么会出现这种情况呢?我们要
从 MongoDB 的读写工作流程和对内存的使用方式说起
MongoDB 在存取工作流程上有一个设计决策,MongoDB 的所有数据实际上是存放在硬盘的,然后把部分或者全部要操作的数据通过内存映射存储引擎映射到内存中。 即是:虚拟内存+持久化的存储方式
如果是读操作,直接从内存中取数据,如果是写操作,就会修改内存中对应的数据,然后就不
需要管了。操作系统的虚拟内存管理器会定时把数据刷新保存到硬盘中。 内存中的数据什么时候写
到硬盘中,则是操作系统的事情了。
MongoDB 的存取工作流程区别于一般硬盘数据库在于两点:
- 读:一般硬盘数据库在需要数据时才去硬盘中读取请求数据, MongoDB 则是尽可能地放入内
存中。 - 写:一般硬盘数据库在有数据需要修改时会马上写入刷新到硬盘,MongoDB 只是修改内存中的
数据就不管了,写入的数据会排队等待操作系统的定时刷新保存到硬盘。
mongoDB的设计思路有两个好处:
- 将什么时候调用 IO 操作写入硬盘这样的内存管理工作交给操作系统的虚拟内存管理
器来完成,大大简化了 MongoDB 的工作。 - 把随机的写操作转换成顺序的写操作,顺其自然地写入,而不是有数据修改就调 IO 操
作去写入,这样减少了 IO 操作,避免了零碎的硬盘操作,大幅度提升性能。
当然也有坏处
- 如果 MongoDB 在内存中修改了数据,在数据刷新到硬盘之前,停电了或者系统岩机
了,就会丢失数据了。
针对这样的问题, MongoDB 设计了 Journal 模式, Journal 是服务器意外岩机的情况下,将数据库操作进行重演的日志(类似redolog)。如果打开 Journal ,默认情况下 MongoDB 100 毫秒(这是在数据文件和 Journal 文件处于同磁盘卷上的情况,而如果数据文件和 Journal 文件不在同磁盘卷上时,默认刷新输出时间是 30 毫秒)往 Journal 文件中 flush 次数据,那么即使断电也只会丢失 100ms 的数据,这对大多数应用来说都可以容忍了。从版 1.9.2+, MongoDB 默认打开 Journal 功能,以确保数据安全。而且 Journal 的刷新时间是可以改变的,使用–journalCommitInterval 命令修改,范围是2~300ms 值越低,刷新输出频率越高,数据安全度也就越高,但磁盘性能上的开销也更高。MongoDB 存取工作流程的实现关键在于通过内存映射存储引擎把数据映射到内存中。
存储引擎
MongoDB 目前支持的 MMAP,MMAPV1,WiredTiger 以及 In-Memory 存储引擎。目前主要流行 WiredTiger
引擎。官方讲解:wireTiger存储引擎
测试
docker部署单机mongo
拉取镜像
docker pull mongo:latest
运行容器
docker run -itd --name mongo -p 27017:27017 mongo --auth
# --auth 需要认证才能访问
创建用户设置密码
docker exec -it mongo mongo admin
docker exec -it mongo mongosh admin (5.0版本以上连接mongo使用命令mongosh)
创建一个名为 admin,密码为 test123456的用户
db.createUser({ user:'admin',pwd:'test123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]});
尝试使用上面创建的用户信息进行连接
db.auth('admin', 'test123456');
talenty@k8smaster:~$ docker exec -it mongo mongo admin
MongoDB shell version v5.0.5
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("23af949c-008d-4963-9136-7240ad487a9d") }
MongoDB server version: 5.0.5
================
Warning: the "mongo" shell has been superseded by "mongosh",
which delivers improved usability and compatibility.The "mongo" shell has been deprecated and will be removed in
an upcoming release.
For installation instructions, see
https://docs.mongodb.com/mongodb-shell/install/
================
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
https://community.mongodb.com
>
> db.createUser({ user:'admin',pwd:'test123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]});
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
},
"readWriteAnyDatabase"
]
}
>
> db.auth('admin','test123456')
1
> exit
bye
用户权限
权限 说明
read 允许用户读取指定数据库
readWrite 允许用户读写指定数据库
dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin 允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户
clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
root 只在admin数据库中可用。超级账号,超级权限