MongoDB介绍
业务应用场景
传统的关系型数据库(如MySQL),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。
解释:“三高”需求:
High performance - 对数据库高并发读写的需求。
Huge Storage - 对海量数据的高效率存储和访问的需求。
High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求。
具体的应用场景如:
1) 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
2) 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储, 方便查询、高效率存储和访问。
3) 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将 订单所有的变更读取出来。
4) 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
5) 视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。
什么时候选择MongoDB?
在架构选型上,除了上述的三个特点外,如果你还犹豫是否要选择它?可以考虑以下的一些问题: 应用不需要事务及复杂 join 支持
新应用,需求会变,数据模型无法确定,想快速迭代开发
应用需要2000-3000以上的读写QPS(更高也可以) 应用需要TB甚至 PB 级别数据存储应用发展迅速,需要能快速水平扩展
应用要求存储的数据不丢失应用需要99.999%高可用
应用需要大量的地理位置查询、文本查询
如果上述有1个符合,可以考虑 MongoDB,2个及以上的符合,选择 MongoDB 绝不会后悔。
什么是MongoDB?
MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展, 是NoSQL数据库产品中的一种。是最 像关系型数据库(MySQL)的非关系型数据库。
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认 为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。
体系结构
MySQL和MongoDB的对比
![]() |
| MySQL术语/概念 | MongoDB术语/概念 | 解释、说明 |
|---|---|---|
| database | database | 数据库 |
| table | collection | 数据库表/集合 |
| row | document | 数据记录行/文档 |
| column | field | 数据字段/域 |
| index | index | 索引 |
| table join | 表连接,MongoDB不支持 | |
| primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
数据类型
| 数据类型 | 描述 | 举例 |
|---|---|---|
| 字符串 | utf8字符串都可以表示为字符串类型的数据 | {“x”:”foobar”} |
| 对象id | 对象id是文档的12字节的唯一ID | {“X”:Objectid()} |
| 布尔值 | 真或者假:true或者false | {“x”:true} |
| 数组 | 值的集合或者列表都可以表示成数组 | {“x”:[“a”,”b”,”c”]} |
| 整数 | (Int32 Int64 你们就知道有个Int就行了,一般我们用Int32) | {“age”:18} |
| null | 表示空值或者未定义的对象 | {“x”:null} |
| undefined | 文档中也可以使用未定义类型 | {“x”:undefined} |
MongoDB特点
(1) 高性能: MongoDB提供高性能的数据持久性。特别是, 对嵌入式数据模型的支持减少了数据库系统上的I/O活动。 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地 理位置索引可用于构建各种 O2O 应用) mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求。Gridfs解决文件存储的需求。
(2) 高可用性: MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。
(3) 高扩展性: MongoDB提供了水平可扩展性作为其核心功能的一部分。 分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展) 从3.4开始,MongoDB支持基于片键创建数据区域。在一个平衡的集群中,MongoDB将一个区域所覆盖的读写只定向到该区域内的那些 片。
(4) 丰富的查询支持: MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。
(5) 其他特点:如无模式(动态模式)、灵活的文档模型
部署安装以及基本命令
二进制安装
准备软件包,上官网下载软件包
[root@server1 ~]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.4.tgz
关闭防火墙和selinux
[root@server1 ~]# systemctl stop firewalld[root@server1 ~]# setenforce 0[root@server1 ~]# vi /etc/selinux/config
关闭大叶内存机制
[root@server1 ~]# sudo mkdir /etc/tuned/virtual-guest-no-thp[root@server1 ~]# vim /etc/tuned/virtual-guest-no-thp/tuned.conf[main]include=virtual-guest[vm]transparent_hugepages=never[root@server1 ~]# sudo tuned-adm profile virtual-guest-no-thp[root@server1 ~]# cat /sys/kernel/mm/transparent_hugepage/enabledalways madvise [never][root@server1 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag[always] madvise never参考文档:https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
准备用户
[root@server1 ~]# useradd mongod[root@server1 ~]# passwd mongod更改用户 mongod 的密码 。新的 密码:无效的密码: 密码是一个回文重新输入新的密码:passwd:所有的身份验证令牌已经成功更新。
- 准备目录结构
[root@server1 ~]# mkdir -p /mongodb/{conf,log,data}
- 解压压缩包,并将bin目录复制到/mongodb/下
[root@server1 ~]# tar xvf mongodb-linux-x86_64-rhel70-4.4.4.tgz[root@server1 ~]# cp -r mongodb-linux-x86_64-rhel70-4.4.4/bin /mongodb/
- 移动解压后的文件夹到指定的目录中
[root@server1 ~]# mkdir /usr/local/mongodb[root@server1 ~]# mv mongodb-linux-x86_64-rhel70-4.4.4/* /usr/local/mongodb/
设置目录结构权限
[root@server1 ~]# chown -R mongod:mongod /mongodb
- 设置新用户环境变量
[root@server1 ~]# su - mongod[mongod@server1 ~]$ vim .bash_profileexport PATH=/mongodb/bin:$PATH[mongod@server1 ~]$ source .bash_profile[mongod@server1 ~]$ mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork刷新一下配置文件
- 启动mongodb
[mongod@server1 ~]$ mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork
- 登陆mongodb
[mongod@localhost ~]$ mongo
- 关闭
[mongod@localhost ~]$ mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --shutdown
配置文件解释
YAML模式NOTE:YAML does not support tab characters for indentation: use spaces instead.--系统日志有关systemLog:destination: filepath: "/mongodb/log/mongodb.log" --日志位置logAppend: true --日志以追加模式记录--数据存储有关storage:journal:enabled: truedbPath: "/mongodb/data" --数据路径的位置-- 进程控制processManagement:fork: true --后台守护进程pidFilePath: <string> --pid文件的位置,一般不用配置,可以去掉这行,自动生成到data中--网络配置有关net:bindIp: <ip> -- 监听地址port: <port> -- 端口号,默认不配置端口号,是27017-- 安全验证有关配置security:authorization: enabled --是否打开用户名密码验证------------------以下是副本集与分片集群有关----------------------replication:oplogSizeMB: <NUM>replSetName: "<REPSETNAME>"secondaryIndexPrefetch: "all"sharding:clusterRole: <string>archiveMovedChunks: <boolean>---for mongos onlyreplication:localPingThresholdMs: <int>sharding:configDB: <string>---
使用配置文件启动服务
[root@server1 ~]# vim /mongodb/conf/mongo.confsystemLog:destination: filepath: "/mongodb/log/mongodb.log"logAppend: truestorage:journal:enabled: truedbPath: "/mongodb/data/"processManagement:fork: truenet:port: 27017bindIp: 192.168.80.151,127.0.0.1[mongod@server1 ~]$ mongod -f /mongodb/conf/mongo.conf #启动服务about to fork child process, waiting until server is ready for connections.forked process: 1676child process started successfully, parent exiting[mongod@server1 ~]$ mongod -f /mongodb/conf/mongo.conf --shutdown #关闭服务
yum安装(不建议)
准备yum仓库
[mngodb-org]name=MongoDB Repositorybaseurl=http://mirrors.aliyun.com/mongodb/yum/redhat/7Server/mongodborg/4.0/x86_64/gpgcheck=0enabled=1
更新yum仓库
[root@localhost ~]# yum update
使用yum安装
[root@localhost ~]# yum install mongodb-org
数据库命令
数据库:articledb

数据库操作
数据库名可以是满足以下条件的任意UTF-8字符串。
不能是空字符串(””)。
不得含有’ ‘(空格)、.、$、/、\和\0 (空字符)。
全部小写。
最多64字节。
选择和创建数据库
# 选择数据库,如果数据库不存在则自动创建use 数据库名称> use articledbswitched to db articledb
查看所有数据库
show dbsshow databases> show dbsadmin 0.000GBconfig 0.000GBlocal 0.000GB> show databasesadmin 0.000GBconfig 0.000GBlocal 0.000GB有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
查看当前所在数据库
# 如果没有创建出数据库,默认的数据库为test> dbarticledb
- 删除当前所在数据库
> db.dropDatabase()
集合操作
集合的命名规范:
- 集合名不能是空字符串””。
- 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
- 集合名不能以”system.”开头,这是为系统集合保留的前缀。用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些 系统生成的集合中包含该字符。除 非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
创建一个名为 mycollection 的普通集合
> db.createCollection("mycollection")
查看当前所在库的所有集合
> show collections;mycollection> show tables;mycollection
删除mycollection集合
删除成功返回结果为true,删除失败返回结果为false> db.mycollection.drop()true
文档操作
文档(document)的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。
JSON示例:
{"employees": [{ "firstName":"Bill" , "lastName":"Gates" }{ "firstName":"George" , "lastName":"Bush" },{ "firstName":"Thomas" , "lastName":"Carter" }]}
单个文档插入,使用insert或者save方法插入文档
db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Rose","createdatetime":newDate(),"likenum":NumberInt(10),"state":null})WriteResult({ "nInserted" : 1 })解释说明1. 如果插入数据的集合不存在,则会隐式地创建出此集合2. mongo中的数字,默认情况下是double类型,如果要存整型,必须使用函数NumberInt(整型数字)3. 插入当前日期使用 new Date()4. 插入的数据没有指定 _id ,会自动生成主键值5. 如果某字段没值,可以赋值为null,或不写该字段
文档内容相关
文档中的键/值对是有序的。
文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个 嵌入的文档)。
MongoDB区分类型和大小写。MongoDB的文档不能有重复的键。
文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。键不能含有\0 (空字符)。这个字符用来表示键的结尾。
.和$有特别的意义,只有在特定环境下才能使用。以下划线”_”开头的键是保留的(不是严格要求的)。
批量插入多行数据
db.comment.insertMany([{"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":newDate("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"},{"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"},{"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"},{"_id":"4","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"}]);提示插入时指定了 _id ,则主键就是该值。如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。
- 查询所有数据
> db.comment.find()> db.comment.find({})
- 查询指定文档
> db.comment.find({userid:'1003'})
- 转换为JSON格式输出
> db.comment.find().pretty()
- 投影查询
> db.comment.find({userid:"1003"},{userid:1,nickname:1})> db.comment.find({},{userid:1,nickname:1})> db.comment.find({},{userid:1,nickname:1,_id:0})
- 覆盖修改
> db.comment.update({_id:"1"},{userid:"10000"})> db.comment.find({userid:"10000"}){ "_id" : "1", "userid" : "10000" }
- 局部修改
为了只修改部分数据需要使用$set修改器> db.comment.update({_id:"2"},{$set:{likenum:NumberInt(889)}})
- 批量修改
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒大帝"}},{multi:true})
- 删除文档
# 删除全部文档db.comment.remove({})# 删除指定文档db.comment.remove({_id:"1"})
文档的更多查询
统计所有记录数量
按条件统计记录
分页查询
![]() |
排序查询

正则表达式查询
![]() |
比较查询
![]() |
包含查询
![]() |
条件连接查询
![]() |
命令小结

索引管理
概述
索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句 匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非 常致命的。
如果查询存在适当的索引,MongoDB可以使用该索引限制必须检查的文档数。 索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排 序。索引项的排 序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序结果
索引类型
单字段索引
MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(Single Field Index)。
复合索引

MongoDB还支持多个字段的用户定义索引,即复合索引(Compound Index)。其他索引
地理空间索引(Geospatial Index)、文本索引(Text Indexes)、哈希索引(Hashed Indexes)。
索引的管理操作
查看索引
![]() |
创建但字段索引
![]() |
创建复合索引
![]() |
删除所有索引
![]() |
删除指定索引

副本集
简介
MongoDB中的副本集(Replica Set)是一组维护相同数据集的mongod服务。 副本集可提供冗余和高可用性,是所有生产部署的基础。
也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异 步同步,从而使多台机器拥有同一数据的多个副本,并且当主库当掉时在不需要用户干预的情况下自动 切换其他备份服务器做主库。而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载。
(1) 冗余和数据可用性
复制提供冗余并提高数据可用性。 通过在不同数据库服务器上提供多个数据副本,复制可提供一定级别的容错功能,以防止丢失单个数据库服务器。 在某些情况下,复制可以提供增加的读取性能,因为客户端可以将读取操作发送到不同的服务上, 在不 同数据中心维护数据副本可以增加分布式应用程序的数据位置和可用性。 您还可以为专用目的维护其他 副本,例如灾难恢复,报告或备份。
(2) MongoDB中的复制
副本集是一组维护相同数据集的mongod实例。 副本集包含多个数据承载节点和可选的一个仲裁节点。在承载数据的节点中,一个且仅一个成员被视为主节点,而其他节点被视为次要(从)节点。 主节点接收所有写操作。 副本集只能有一个主要能够确认具有{w:“most”}写入关注的写入; 虽然在某 些情况
下,另一个mongod实例可能暂时认为自己也是主要的。主要记录其操作日志中的数据集的所有 更改, 即oplog。
(3) 主从复制和副本集区别
主从集群和副本集最大的区别就是副本集没有固定的“主节点”;整个集群会选出一个“主节点”,当其挂 掉后,又在剩下的从节点中选中其他节点为“主节点”,副本集总有一个活跃点(主、primary)和一个或多 个备份节点(从、secondary)。
副本集的三个角色
主要成员(Primary):主要接收所有写操作。就是主节点。
副本成员(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作, 但可 以读操作(但需要配置)。是默认的一种从节点类型。
仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护 为副 本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。
关于仲裁者的额外说明:
您可以将额外的mongod实例添加到副本集作为仲裁者。 仲裁者不维护数据集。 仲裁者的目的是通过响应其他副本集成员的心跳和选举请求来维护副本集中的仲裁。 因为它们不存储数据集,所以仲裁器可以是提供副本集仲裁功能的好方法,其资源成本比具有数据集的全功能副本集成员更便宜。
如果您的副本集具有偶数个成员,请添加仲裁者以获得主要选举中的“大多数”投票。 仲裁者不需要专用硬件。
仲裁者将永远是仲裁者,而主要人员可能会退出并成为次要人员,而次要人员可能成为选举期间的主要 人员。
如果你的副本+主节点的个数是偶数,建议加一个仲裁者,形成奇数,容易满足大多数的投票。 如果你的副本+主节点的个数是奇数,可以不加仲裁者。
![]() |
副本集搭建
准备三台节点
![]() |
副本集初始化
![]() |


查看副本节点配置
![]() |

另外两台机器也如上述操作一样添加副本集
![]() |
设置从节点可读
![]() |
分片集群
概念
分片(sharding)是一种跨多台机器分布数据的方法, MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署。
换句话说:分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程。有时也用分区
(partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存更多的数据,处理更多的负载。
具有大型数据集或高吞吐量应用程序的数据库系统可以会挑战单个服务器的容量。例如,高查询率会耗 尽服务器的CPU容量。工作集大小大于系统的RAM会强调磁盘驱动器的I / O容量。
有两种解决系统增长的方法:垂直扩展和水平扩展。
垂直扩展意味着增加单个服务器的容量,例如使用更强大的CPU,添加更多RAM或增加存储空间量。可 用技术的局限性可能会限制单个机器对于给定工作负载而言足够强大。此外,基于云的提供商基于可用 的硬件配置具有硬性上限。结果,垂直缩放有实际的最大值。 水平扩展意味着划分系统数据集并加载多个服务器,添加其他服务器以根据需要增加容量。虽然单个机 器的总体速度或容量可能不高,但每台机器处理整个工作负载的子集,可能提供比单个高速大容量服务 器更高的效率。扩展部署容量只需要根据需要添加额外的服务器,这可能比单个机器的高端硬件的总体 成本更低。权衡是基础架构和部署维护的复杂性增加。
MongoDB支持通过分片进行水平扩展。
分片集群包含的组件
分片(存储):每个分片包含分片数据的子集。 每个分片都可以部署为副本集。
mongos(路由):mongos充当查询路由器,在客户端应用程序和分片集群之间提供接口。
config servers(“调度”的配置):配置服务器存储群集的元数据和配置设置。 从MongoDB 3.4开始,必须将配置服务器部署为副本集(CSRS)。

集群部署
规划
![]() |
分片节点准备
目录准备
![]() |
第一组副本集搭建:端口号21-23,一主一从一监控
![]() |
| \cp | /mongodb/38021/conf/mongodb.conf | /mongodb/38022/conf/ |
|---|---|---|
| \cp | /mongodb/38021/conf/mongodb.conf | /mongodb/38023/conf/ |

第一组副本集搭建:端口号24-26,一主一从一监控
![]() |

启动所有节点,并搭建副本集
![]() |
config节点配置
目录创建
![]() |
配置文件准备
![]() |

启动所有节点
![]() |
mongos节点配置
目录创建
![]() |
准备配置文件
![]() |
启动mongos
![]() |
使用分片
分片集群添加节点
![]() |
激活数据库分片功能
![]() |
指定分片键对集合分片

分片验证
![]() |
用户管理
注意
![]() |
用户创建语法
![]() |

创建超级管理员
![]() |
验证用户
![]() |
配置文件开启用户认证
![]() |
登录验证
![]() |
查看用户
![]() |
删除用户
![]() |
用户角色
数据库用户角色:read、readWrite;
所有数据库用户角色:readAnyDatabase、readWriteAnyDatabase、
userAdminAnyDatabase、dbAdminAnyDatabase
数据库管理角色:dbAdmin、dbOwner、userAdmin;

集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager; 备份恢复角色:backup、restore;

超级用户角色:root 内部角色:system













![文本框: my_repl:PRIMARY> rs.conf() { "_id" : "my_repl", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "127.0.0.1:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("5f883f6730b7d82e37e0dcca") } } 1) "_id" : "my_repl" :副本集的配置数据存储的主键值,默认就是副本集的名字 2) "members" :副本集成员数组,此时只有一个: "host" : "127.0.0.1:27017" ,该成员不是仲裁节点: "arbiterOnly" : false ,优先级(权重值): "priority" : 1, 3) "settings" :副本集的参数配置。](file:///C:/Users/26976/AppData/Local/Temp/msohtmlclip1/01/clip_image091.gif)
























