MongoDB从入门到优化

1、MongoDB 简介

本文的内容是基于 MongoDB 4.0 的。 参考于 MongoDB 4.0 官方文档。mysql

​ MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。属于 nosql 数据库。MongoDB 数据库中最小的数据单元是文档,它是由 key 和 value 组成的数据结构, MongoDB 文档相似于 JSON 对象。value 的值能够是数组、字符串、数值、文档。linux

image

主要优势

​ 支持多语言、高性能、丰富的查询语言、高可用性、可扩展、支持多个储存引擎、高效存储二进制大对象 (好比照片和视频)。git

4.0版本的优点:github

  • MongoDB 4.0版将文档模型的速度,灵活性和功能与ACID保证相结合。
  • MongoDB 4.0版借助事务特性,使得备节点再也不由于同步日志而阻塞读取请求。
  • MongoDB 4.0版提供并发的读取和写入能力,使得新增分片shard迁移性能提高了约 40%, 新增节点能更快的承载业务压力。

MongoDB 与 mysql 对比sql

SQL Terms/Concepts MongoDB Terms/Concepts
database database
table collection
row document or BSON document
column field
index index
table joins embedded documents and linking
primary keySpecify any unique column orcolumn combination asprimary key. primary keyIn MongoDB, the primary key isautomatically set to the _id field.
aggregation (e.g. group by) aggregation pipelineSee the SQL to Aggregation MappingChart.

应用场景

位置查询的移动类APP,储存数据结构易变化的数据。mongodb

电商后台(商品更新记录,会员天天虚拟币余额(定时获取),会员帐号信息,订单信息等等) 。docker

储存用户发表的朋友圈。shell

储存直播行业的用户信息、礼物信息以及日志等信息,同时可经过丰富的聚合查询来进行业务分析。数据库

2、MongoDB 的储存引擎

MongoDB 有三大储存引擎,分别是 WiredTiger 、In-Memory 、MMAPv1。

  • WiredTiger

    是MongoDB 3.2 中的默认储存引擎,是多线程的,它适合大多数的工程场景,支持文档级别的并发,压缩等功能,官方建议使用该储存引擎。在3.6版本后 WiredTiger 每60s将数据写入到磁盘,在下一次写入成功前,本次节点的数据仍然有效。当发生故障时,MongoDB 能够从最后的一次成功写入进行恢复。

  • In-Memory

    In-Memory 只能在 企业版本中使用,它不是将文档储存在磁盘上,而是保存在内存上,实现更快的检索。

  • MMAPv1

    是 MongoDB 3.0 以前的更早版本的默认储存引擎。从 MongoDB 4.0 开始官方不推荐使用该引擎。

MongoDB 如何保证数据的完整性 ,经过检查点(也就是每60s写入一次)和事务性日志来确保数据的完整性和持久性。

咱们接下来介绍下 咱们经常使用的引擎 WiredTiger 的相关信息:

WiredTiger

WiredTiger 日志

日志功能默认启用。 WiredTiger 日志会在检查点之间保留全部数据修改。若是 MongoDB 在检查点之间退出,它将使用日志重播自上一个检查点以来修改的全部数据。

咱们能够禁用日志功能,来减小开启日志功能所须要的开销。可是这样也就意味着,当MongoDB 非正常退出时,最后一个检查点以后的数据将会都丢失。

WiredTiger 日志默认启用数据压缩。此日志非 MongoDB 的日志文件,而是 WiredTiger 日志,经过该日志咱们能够获取上一个检查点以后发生的操做。

使用日志功能,恢复流程:

  1. 先查看数据文件查找最后一个检查点的位置的标识符。
  2. 在日志文件中搜索与检查点标识符相匹配的记录。
  3. 获取从上一个检查点以后的操做。

日志文件会在 dbpath 下以 journal 命名的子目录下,以形如 WiredTigerLog.0000000001 格式的文件名储存。

WiredTiger 的最小日志记录大小为128个字节。若是日志记录是128字节或更小,WiredTiger 不会压缩该记录。

日志文件包含每一个写操做的记录。每条记录都有惟一的标识符。MongoDB 将 WiredTiger 配置为对日记数据使用snappy压缩。

MongoDB 的 WiredTiger 日志文件的最大大小限制大约为100 MB。一旦文件超过该限制,WiredTiger就会建立一个新的日志文件。

WiredTiger 会自动删除旧日志文件,以仅维护从上一个检查点恢复所需的文件。

数据压缩

使用 WiredTiger,MongoDB支持对全部集合和索引进行压缩。压缩是以 CPU 为代价来减小磁盘的使用。默认状况下,WiredTiger 会对数据进行压缩。在大多数状况下,默认的压缩设置以及平衡了 储存空间和 CPU 使用率。

内存使用

从 MongoDB 3.4开始,默认WiredTiger内部缓存大小取值是取如下两个值中的较大者:

  • (totalRAM - 1G) 50%
  • 256MB

例如 一个主机的内存是 4G ,那么取值为 1.5G, 若是是 1.25G,那么取值为256M。

调整 内存使用,须要使用 storage.wiredTiger.engineConfig.cacheSizeGB内部缓存和 --wiredTigerCacheSizeGB。 两个参数。

3、mongodb 配置参数

Mongodb 建议使用 YAML 格式的配置文件,也支持 ini 格式的配置文件。

ini 配置文件参数解析

bind_ip=0.0.0.0  #绑定的 ip,若是是 0.0.0.0 就是绑定本地全部ip
port=27037  # 监听端口号,默认为27017。
dbpath=/opt/mongodb/data/ # 数据储存的位置 
logpath=/opt/mongodb/logs/mongodb.log # 日志储存的位置
pidfilepath=/opt/mongodb/logs/mongod.pid # pid文件储存的位置
logRotate= rename/reopen
    #3.0.0版中的新功能。能够取值为 rename 或 reopen:
        rename 重命名日志文件。每次重启都会重命名日志文件。
        reopen 按照典型的 Linux/Unix 日志循环行为关闭并从新打开日志文件。使用 reopen 使用的             Linux/Unix logrotate的工具时,以免日志的丢失。
        若是指定 reopen,则还必须使用 logappend
logappend= true # 当 MongoDB 实例从新启动时,将新的日志内容添加到现有日志文件的末尾。若是没有此选项,MongoDB 将备份现有日志并建立新文件。
listenBacklog= 128 #侦听队列中能够存在的最大链接数。取决于 /proc/sys/net/core/somaxconn 这个值
maxConns= 500  #最大链接数
directoryperdb=true # 将每一个数据库的数据分目录储存
# replS=fymongodb # 在配置副本集的时候设置副本集名称,单节点的不须要设置该参数
auth=true # 开启登陆验证
fork=true # 后台运行
journal=true # 开启预写日志

YAML 配置文件参数解析

systemLog:  # 日志配置 日志切割见文章:https://dwz.cn/VPxxTf38
   destination: file
   path: "/opt/mongodb/logs/mongodb.log"  
   logAppend: true
   timeStampFormat: "iso8601-local"  # 日志使用的时间格式,默认为iso8601-local,可选值 ctime、iso8601-utc、iso8601-local。
   # 还有更详细的组件、控制、索引、回滚等日志的输出等级配置见官网
processManagement: # 进程控制配置
   fork: true  #后台以守护进程运行
   pidFilePath: "/opt/mongodb/logs/mongod.pid"  # pid 文件路径
   timeZoneInfo: "/usr/share/zoneinfo/Asia/Shanghai"  #数据库使用的时区,未设置使用系统默认
net:
   bindIp: "0.0.0.0"  # 绑定的ip,127.0.0.1/0.0.0.0/::,0.0.0.0(绑定到全部IP地址),与bindIpAll 参数是互斥的
   bindIpAll: <boolean>  # 是否绑定本地全部ip,与bindIp 参数是互斥的
   port: 27017  # 绑定的端口,默认值27017
   maxIncomingConnections: 500 # 最大同时链接数,默认值为65536
   wireObjectCheck: <boolean>  # 对客户端的写入进行验证,会有较小的性能影响,默认为 True.
   ssl:  # ssl 的详细配置
      sslOnNormalPorts: <boolean>  # deprecated since 2.6
      certificateSelector: <string>
      clusterCertificateSelector: <string>
      mode: <string>
      PEMKeyFile: <string>
      PEMKeyPassword: <string>
      clusterFile: <string>
      clusterPassword: <string>
      CAFile: <string>
      clusterCAFile: <string>
      CRLFile: <string>
      allowConnectionsWithoutCertificates: <boolean>
      allowInvalidCertificates: <boolean>
      allowInvalidHostnames: <boolean>
      disabledProtocols: <string>
      FIPSMode: <boolean>
   compression:
      compressors: <string> # 通讯压缩器,可取值 snappy、zlib(版本3.6+可用)、disabled,默认值snappy,
   serviceExecutor: <string> #线程执行模型 3.6+版本使用,默认值: synchronous,可取值 adaptive、synchronous
storage: # 数据储存配置
   dbPath: "/opt/mongodb/data/"   #  mongod 数据储存的位置
   indexBuildRetry: <boolean> # mongod 在下次启动从新构建不完整索引,默认为True,不能与replication.replSetName 一块儿使用
   repairPath: <string>   
   journal: 
      enabled: <boolean> # 是否开启journal日志在64位系统默认为 true,在32位系统为false,建议启用
      commitIntervalMs: <num> # 设置日志储存到磁盘的间隔时间,默认为100毫秒,能够设置为1-500.
   directoryPerDB: <boolean>  # 是否开启分目录储存数据,默认值为 False,
   syncPeriodSecs: <int>  # MongoDB经过fsync操做将数据储存到磁盘的时间,默认值 60,单位秒,不建议更改此值
   engine: <string> # 储存引擎,默认值wiredTiger,MongoDB不推荐使用MMAPv1存储引擎
   wiredTiger:    # wiredTiger 储存引擎配置
      engineConfig:
         cacheSizeGB: <number>  # 内部缓存内存大小,默认是取50% of (RAM - 1 GB)和256 MB的最大者,可设置值为 0.25G-10000G,若是一台服务器有多个MongoDB实例或者运行在docker中,须要设置该值,避免多台实例占用完系统的全部内存,和mongodb在容器中获取不到实际内存大小。
         journalCompressor: <string> # WiredTiger日志数据的压缩类型 默认值 snappy,可选值 none、snappy、zlib.
         directoryForIndexes: <boolean> # 将index储存到一个目录,并软链接到数据目录,默认值为False,
      collectionConfig: 
         blockCompressor: <string>  # 集合数据的压缩类型,默认值 snappy,可选值 none、snappy、zlib.
      indexConfig:
         prefixCompression: <boolean> # 启用的索引的前缀压缩 默认值为 true
   inMemory:  # inmemory 引擎配置
      engineConfig:
         inMemorySizeGB: <number>  # 设置 inmemory 引擎分配的最大内存默认为50%(RAM - 1 GB)
security:
   keyFile: <string> #储存密钥文件的路径,用于存储MongoDB实例用于在分片集群或副本集中相互进行身份验证的共享密钥 
   clusterAuthMode: <string> #集群验证模式
   authorization: <string> #启用基于角色的访问控制,可选值enabled、disabled默认值为禁用,建议开启

operationProfiling:  # 开启慢查询
   mode: <string>  # 慢查询模式 可选值,off、slowOp、all,默认值off。建议开启
   slowOpThresholdMs: <int>  # 阈值,默认值100 毫秒
   slowOpSampleRate: <double> # 随机采集慢查询的百分比值,sampleRate 值默认为1,表示都采集,0.42 表示采集42%的内容
replication:  # 复制配置,副本集,indexBuildRetry与副本集互斥 Oplog 具体见文章: https://dwz.cn/98tUpUfu
   oplogSizeMB: <int> # Oplog 的最大大小,单位Mb ,
   replSetName: <string> # 副本集名称
   secondaryIndexPrefetch: <string> # 仅适用于mmapv1 存储引擎
   enableMajorityReadConcern: <boolean> # 开启 Majority 读取,默认为 True.
sharding: # 分片
   clusterRole: <string> # 设置该实例角色,可选值configsvr、shardsvr
   archiveMovedChunks: <boolean>   # 迁移过程块不保存 从3.2版本开始,默认为 False

示例配置文件

MongoDB 示例 ini 配置文件

github地址 : https://github.com/tobewithyou1996/LinuxGuide/blob/master/MongoDB/mongodb.conf

MongoDB 示例 YAML 配置文件

github地址 : https://github.com/tobewithyou1996/LinuxGuide/blob/master/MongoDB/mongodb.yaml

4、MongoDB 单节点搭建

单节点搭建

cd /tmp && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.8.tgz
tar -zxf mongodb-linux-x86_64-4.0.8.tgz 
mv  mongodb-linux-x86_64-4.0.8  /opt/mongodb
mkdir  /opt/mongodb/{data,logs}
touch  /opt/mongodb/mongodb.conf
useradd  mongodb 
# 添加配置文件
cat <<EOF  >> /opt/mongodb/mongodb.conf
bind_ip=0.0.0.0
port=27037
dbpath=/opt/mongodb/data/
logpath=/opt/mongodb/logs/mongodb.log
pidfilepath=/opt/mongodb/logs/mongod.pid
logRotate= reopen
logappend= true
listenBacklog= 128
maxConns= 500
directoryperdb=true
noauth=true
fork=true
journal=true
profile=2
slowms=200
EOF
# 更改 mongodb 的目录全部者
chown  -R mongodb:mongodb  /opt/mongodb
# 启动 MongoDB 服务
mongod -f /opt/mongodb/mongodb.conf
# 若是当前登陆的用户是 root 须要指定用户 mongodb 启动。
su - mongodb  -c "/opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.conf"
# 添加环境变量
echo "export PATH=$PATH:/opt/mongodb/bin" >>/etc/profile
source /etc/profile
# 暂停 MongoDB  服务
/opt/mongodb/bin/mongod --shutdown   --dbpath /opt/mongodb/data
#`mongod` 是服务端
#`mongo` 是客户端链接工具。

配置管理用户和普通用户

建立管理员用户:建立管理员用户 admin ,密码 9toc7ttpji8 ,拥有最高级权限。

> use admin
switched to db admin
> db.createUser({ user: "admin", pwd: "9toc7tpji8", roles: [{ role: "root", db: "admin" }] })
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}

建立普通用户 : 在数据库 djx, 建立用户名为 dd ,密码为 djx@123456,对数据库 djx 具备读写权限的用户。

> use djx
switched to db djx
> db.createUser({user: "dd",pwd: "djx@123456",roles:[{"role":"readWrite","db":"djx"}]});
Successfully added user: {
    "user" : "dd",
    "roles" : [
        {
            "role" : "readWrite",
            "db" : "djx"
        }
    ]
}

详细配置见本文后半部分的 MongoDB用户认证和 MongoDB 角色。

开启登录验证

mongodb.conf 文件中的 noauth=true 替换为 auth=true

sed -i s/noauth/auth/g /opt/mongodb/mongodb.conf

并重启MongoDB 才能生效

配置systemd 脚本

cat <<EOF >>/usr/lib/systemd/system/mongodb.service
[Unit]
Description= mongodb service manager
[Service]
# Other directives omitted
# (file size)
LimitFSIZE=infinity
# (cpu time)
LimitCPU=infinity
# (virtual memory size)
LimitAS=infinity
# (locked-in-memory size)
LimitMEMLOCK=infinity
# (open files)
LimitNOFILE=64000
# (processes/threads)
LimitNPROC=64000
Type=forking
User=mongodb
Group=mongodb
PIDFile=/opt/mongodb/logs/mongod.pid
ExecStart= /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb.conf
ExecStop= /opt/mongodb/bin/mongod --shutdown   --dbpath /opt/mongodb/data
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl status  mongodb # 查看 mongodb 状态
systemctl start mongodb # 启动 mongodb
systemctl enable  mongodb # 将 mongodb 添加到开机自启
systemctl stop mongodb # 暂停 mongodb

若是是在生产环境中使用,查看 MongoDB 生产环境笔记

5、MongoDB 链接

MongoDB 默认链接端口 27017 。

MongoDB shell 链接

指定端口:

mongo --port 27037

指定端口和主机

mongo --host mongodb0.example.com:28015

具备认证的 MongoDB 实例

mongo --host mongodb://alice@mongodb0.examples.com:28015/?authSource=admin
或者使用
 --username <user>  --password, --authenticationDatabase <db>

MongoDB 应用程序链接

链接到 MongoDB 的副本集

mongo mongodb://mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017/?replicaSet=replA

或者是
mongo --host replA/mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017

使用 TLS/SSL 链接

在链接后面加上&ssl = true 便可

MongoDB 设置链接池的链接数

最大链接数 &maxPoolSize=<integer>

mongo "mongodb://root:xxxxxx@dds-bpxxxxxxxx-pub.mongodb.rds.aliyuncs.com:3717,dds-bpxxxxxxxx-pub.mongodb.rds.aliyuncs.com:3717/admin?replicaSet=mgset-xxxxxx&maxPoolSize=10"

最小链接数 &minPoolSize=<integer>

6、MongoDB 经常使用命令

数据库级别经常使用命令

db.version() # 查看数据库版本
db  #查看当前所在的数据库
db.help() # 帮助
use databasename # 切换数据库
show dbs  # 列出当前用户可用的全部数据库
db.getSiblingDB() #不切换数据库,在别的数据库执行程序
db.stats()  # 查看当前所在数据库的状态
db.getMongo() # 查看当前 MongoDB 链接路径
use newdatabasename  # 建立数据库
db.dropDatabase()#  删除当前所在数据库
show profile # 打印最近执行花费1毫秒或更长时间的五个最近的操做。
db.serverStatus().connections #  查询当前链接数,以及最大链接数。
use admin , db.runCommand({currentOp: 1, $all:[{"active" : true}]}) # 查询每一个链接对应的来源IP地址。
db.currentOp() # 查看 MongoDB 当前正在执行的操做。
db.killOp(opid) # 终止请求执行
db.fsyncLock()# 刷新写入磁盘并锁定数据库
db.fsyncUnlock()# 解锁
db.serverStatus().storageEngine # 显示当前 MongoDB 所使用的储存引擎
db.runCommand( { "connPoolStats" : 1 } ) # 查询数据库当前的链接信息
db.runCommand({logRotate:1}) # mongodb 日志切割

集合级别经常使用命令

show collections #  查看当前数据库已有的集合
db.createCollection('name')#  建立集合
db.collectionname.drop()# 删除集合
db.collectionname.dataSize(); # 查询集合的大小
db.collectionname.find({key:value}) # 查询集合的数据包含 key 和 value。
db.collectionname.find() # 查询整个集合,每次只会显示部分数据,经过输入 it 来查看其它数据。
db.collectionname.renameCollection("newname")# 集合重命名
db.collectionname.stats()# 查询集合的状态

文档级别经常使用命令

db.collectionname.insert({key:value})#  添加数据,collectionname指的是集合名称。
db.collectionname.count() #查询集合有多少文档数量
db.collectionname.remove({'key':value}) # 删除集合collectionname 中 key='key',value=value 的 文档。

用户经常使用命令

show users #  当前数据库的用户列表
show roles #  当前数据库的全部角色列表,包括用户定义和内置角色。
db.auth(username,pwd) # 登陆验证
db.changeUserPassword(username, password) # 更改用户密码
db.createUser() # 建立用户
db.dropUser(username) # 删除用户
db.dropAllUsers() # 删除全部的用户
db.getUser(username)  # 查询用户
db.getUsers() # 返回当前数据库全部的用户
db.removeUser(username) # 删除用户
db.grantRolesToUser(username, roles, writeConcern) # 给用户受权新的权限
db.revokeRolesFromUser() # 删除用户受权的权限
db.updateUser() # 更新用户信息,该方法会替代用户原有的全部值。

7、MongoDB 认证

MongoDB 默认的认证是 SCRAM

MongoDB 建立用户命令详解:

#  建立用户 
db.createUser(
{
user: "用户名",
pwd: "密码",
customData: {  < any  information >  },
roles: [
    { role: "<role>", db: "<database>" } | "<role>",
    ...
  ],
authenticationRestrictions: [
     {
       clientSource: ["<IP>" | "<CIDR range>", ...]
       serverAddress: ["<IP>" | "<CIDR range>", ...]
     },
     ...
  ],
  mechanisms: [ "<SCRAM-SHA-1|SCRAM-SHA-256>", ... ],
  passwordDigestor: "<server|client>"
}
)
字段 数据类型 描述
user string 用户名
pwd string 密码
customData document 可选的,任意信息,能够是用户的id
roles array 受权用户的角色。能够指定一个空数组[]来建立没有角色的用户。
authenticationRestrictions array 可选,3.6版本中的新功能,容许服务器能够接受用户的IP地址和服务器地址,和CIDR 范围
mechanisms array 可选的,4.0版本的功能,指定用于建立SCRAM用户凭据的特定SCRAM机制,可选值为 SCRAM-SHA-1 、SCRAM-SHA-256
passwordDigestor string 可选的,服务端和客户端是否记录密码,默认为 server ,可选 server 、client。

示例:

建立管理员用户

use admin
db.createUser(
  {
    user: "myUserAdmin",
    pwd: "abc123",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
  }
)

建立普通用户 myTester ,密码为 xyz123 ,对库 test 有可读可写的权限 和 对库 reporting 有可读的权限。

use test
db.createUser(
  {
    user: "myTester",
    pwd: "xyz123",
    roles: [ { role: "readWrite", db: "test" },
             { role: "read", db: "reporting" } ]
  }
)

8、MongoDB 用户角色

官网连接

MongoDB 包含如下客户端的角色 :

基本权限: read(可读)、readWrite(可读可写)。

管理员权限:dbAdmin(管理员)、userAdmin(当前数据库上建立和修改角色和用户的功能)、dbOwner (数据库全部者,包含readWritedbAdminuserAdmin角色)

备份和还原权限:backup(提供备份数据所须要的最小权限)、restore(提供从不包含system.profile 集合数据的备份还原数据所需的权限)

针对全部数据库的权限:readAnyDatabasereadWriteAnyDatabase、`userAdminAnyDatabaseuserAdminAnyDatabasedbAdminAnyDatabase

超级管理员: root (包含readWriteAnyDatabase, dbAdminAnyDatabase,userAdminAnyDatabase, clusterAdmin,restore,和 backup)

咱们也能够定义本身须要的角色,来实现咱们特定的权限规则。咱们能够建立角色,并赋予其权限,详细设置见官网。

9、MongoDB 备份与恢复

因为文章篇幅太长,因此单独放到一个文章里了。

MongoDB 备份与还原 mongodump、mongorestore

10、生产环境注意事项

因为文章篇幅太长,因此单独放到一个文章里了。

MongoDB 生产环境笔记

11、MongoDB 调优

MongoDB 日志切割

MongoDB 日志切割三种方式

CPU 占用较高

MongoDBCPU占用较高(阿里云)

MongoDB 开启慢查询

MongoDB调优-查询优化-MongoDB Profiler

MongoDB Oplog详解

MongoDB-Oplog详解

MongoDB 日志清理

  • 用户禁止使用 db.repairDatabase命令。
  • 日志占用空间过大时,会触发自动清理策略。

注:紧急状况下请使用 db.runCommand({compact: 'oplog.rs'})命令清理日志。

12、MongoDB 经常使用的几大GUI工具

MongoDB 经常使用的几大GUI工具

十3、MongoDB-副本集搭建与管理

MongoDB-副本集搭建与管理

相关文章
相关标签/搜索