MongoDB从入门到优化

目录

  • 一、MongoDB 简介
  • 二、MongoDB 的储存引擎
  • 三、mongodb 配置参数
  • 四、MongoDB 单节点搭建
  • 五、MongoDB 连接
  • 六、MongoDB 常用命令
  • 七、MongoDB 认证
  • 八、MongoDB 用户角色
  • 九、MongoDB 备份与恢复
  • 十、生产环境注意事项
  • 十一、MongoDB 调优
  • 十二、MongoDB 常用的几大GUI工具
  • 十三、MongoDB-副本集搭建与管理

一、MongoDB 简介

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

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

主要优点

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

4.0版本的优势:

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

MongoDB 与 mysql 对比

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 的储存引擎

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。 两个参数。

三、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:   # 是否绑定本地所有ip,与bindIp 参数是互斥的
   port: 27017  # 绑定的端口,默认值27017
   maxIncomingConnections: 500 # 最大同时连接数,默认值为65536
   wireObjectCheck:   # 对客户端的写入进行验证,会有较小的性能影响,默认为 True.
   ssl:  # ssl 的详细配置
      sslOnNormalPorts:   # deprecated since 2.6
      certificateSelector: 
      clusterCertificateSelector: 
      mode: 
      PEMKeyFile: 
      PEMKeyPassword: 
      clusterFile: 
      clusterPassword: 
      CAFile: 
      clusterCAFile: 
      CRLFile: 
      allowConnectionsWithoutCertificates: 
      allowInvalidCertificates: 
      allowInvalidHostnames: 
      disabledProtocols: 
      FIPSMode: 
   compression:
      compressors:  # 通信压缩器,可取值 snappy、zlib(版本3.6+可用)、disabled,默认值snappy,
   serviceExecutor:  #线程执行模型 3.6+版本使用,默认值: synchronous,可取值 adaptive、synchronous
storage: # 数据储存配置
   dbPath: "/opt/mongodb/data/"   #  mongod 数据储存的位置
   indexBuildRetry:  # mongod 在下次启动重新构建不完整索引,默认为True,不能与replication.replSetName 一起使用
   repairPath:    
   journal: 
      enabled:  # 是否开启journal日志在64位系统默认为 true,在32位系统为false,建议启用
      commitIntervalMs:  # 设置日志储存到磁盘的间隔时间,默认为100毫秒,可以设置为1-500.
   directoryPerDB:   # 是否开启分目录储存数据,默认值为 False,
   syncPeriodSecs:   # MongoDB通过fsync操作将数据储存到磁盘的时间,默认值 60,单位秒,不建议更改此值
   engine:  # 储存引擎,默认值wiredTiger,MongoDB不推荐使用MMAPv1存储引擎
   wiredTiger:    # wiredTiger 储存引擎配置
      engineConfig:
         cacheSizeGB:   # 内部缓存内存大小,默认是取50% of (RAM - 1 GB)和256 MB的最大者,可设置值为 0.25G-10000G,如果一台服务器有多个MongoDB实例或者运行在docker中,需要设置该值,避免多台实例占用完系统的所有内存,和mongodb在容器中获取不到实际内存大小。
         journalCompressor:  # WiredTiger日志数据的压缩类型 默认值 snappy,可选值 none、snappy、zlib.
         directoryForIndexes:  # 将index储存到一个目录,并软连接到数据目录,默认值为False,
      collectionConfig: 
         blockCompressor:   # 集合数据的压缩类型,默认值 snappy,可选值 none、snappy、zlib.
      indexConfig:
         prefixCompression:  # 启用的索引的前缀压缩 默认值为 true
   inMemory:  # inmemory 引擎配置
      engineConfig:
         inMemorySizeGB:   # 设置 inmemory 引擎分配的最大内存默认为50%(RAM - 1 GB)
security:
   keyFile:  #储存密钥文件的路径,用于存储MongoDB实例用于在分片集群或副本集中相互进行身份验证的共享密钥 
   clusterAuthMode:  #集群验证模式
   authorization:  #启用基于角色的访问控制,可选值enabled、disabled默认值为禁用,建议开启

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

四、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 <> /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 <>/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 生产环境笔记 。

五、MongoDB 连接

MongoDB 默认连接端口 27017 。

MongoDB shell 连接

指定端口:

mongo --port 27037

指定端口和主机

mongo --host mongodb0.example.com:28015

具有认证的 MongoDB 实例

mongo --host mongodb://[email protected]:28015/?authSource=admin
或者使用
 --username   --password, --authenticationDatabase 

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=

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

最小连接数 &minPoolSize=

六、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() # 更新用户信息,该方法会替代用户原有的所有值。

七、MongoDB 认证

MongoDB 默认的认证是 SCRAM

MongoDB 创建用户命令详解:

#  创建用户 
db.createUser(
{
user: "用户名",
pwd: "密码",
customData: {  < any  information >  },
roles: [
    { role: "", db: "" } | "",
    ...
  ],
authenticationRestrictions: [
     {
       clientSource: ["" | "", ...]
       serverAddress: ["" | "", ...]
     },
     ...
  ],
  mechanisms: [ "", ... ],
  passwordDigestor: ""
}
)
字段 数据类型 描述
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" } ]
  }
)

八、MongoDB 用户角色

官网链接

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

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

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

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

针对所有数据库的权限:readAnyDatabase、readWriteAnyDatabase、`userAdminAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase,

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

我们也可以定义自己需要的角色,来实现我们特定的权限规则。我们可以创建角色,并赋予其权限,详细设置见官网。

九、MongoDB 备份与恢复

由于文章篇幅太长,所以单独放到一个文章里了。

MongoDB 备份与还原 mongodump、mongorestore

十、生产环境注意事项

由于文章篇幅太长,所以单独放到一个文章里了。

MongoDB 生产环境笔记

十一、MongoDB 调优

MongoDB 日志切割

MongoDB 日志切割三种方式

CPU 占用较高

MongoDBCPU占用较高(阿里云)

MongoDB 开启慢查询

MongoDB调优-查询优化-MongoDB Profiler

MongoDB Oplog详解

MongoDB-Oplog详解

MongoDB 日志清理

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

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

十二、MongoDB 常用的几大GUI工具

MongoDB 常用的几大GUI工具

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

MongoDB-副本集搭建与管理

你可能感兴趣的:(MongoDB从入门到优化)