文章目录

  • 一、MongoDB 索引
    • 1、索引操作
    • 2、索引结构
    • 3、索引特性
    • 4、索引语句优化
  • 二、MongoDB 存储引擎
    • 1、默认WiredTiger
    • 2、Why WiredTiger
    • 3、checkpoint
    • 4、Disk空间回收
    • 5、db.serverStatus()和db.stats()
  • 三、MongoDB 数据安全
    • 1、为什么需要安全
    • 2、基本概念
    • 3、实操——单节点
    • 3、实操——副本集
    • 3、实操——分片集群
  • 四、MongoDB 性能优化
    • 1、操作系统优化
    • 2、监控工具优化
    • 3、数据库优化
  • 五、MongoDB 备份与恢复
    • 1、MongoDB冗余和备份
    • 2、分片集备份
    • 3、MongoDB的恢复
  • 六、MongoDB 运维工具——Ops Manager
    • 1、Ops Manager用途
    • 2、Ops Manager工作原理
    • 3、Ops Manager使用

一、MongoDB 索引

1、索引操作

索引就是将文档按照某个(或某些)字段顺序组织起来,以便能根据该字段高效的查询。

索引的基本作用:搜索+排序。

# 创建索引
db.collection.createIndex(keys, options)
db.comment.createIndex({userid:1})
db.comment.createIndex({userid:1,nickname:-1})
# 获取索引
db.collection.getIndexes()
db.collection.totalIndexSize()
db.collection.getIndexSpecs()
# 修改索引
db.collection.reIndex({userid:-1})
# 删除索引
db.collection.dropIndex(index)
db.comment.dropIndex({userid:1})
db.collection.dropIndexes()
  • 索引分类

单字段索引、复合索引、多键索引、Hash索引、地理位图索引、TTL索引、全文索引等

db.person.createIndex( {age: 1} )
db.person.createIndex( {age: 1, name: 1} )
#多键索引是建立在数组(array)上的索引。多key索引是自动创建的。
db.person.createIndex( {habbit: 1} )
#哈希索引(Hashed Index)是指按照某个字段的hash值来建立索引,目前主要用于MongoDB Sharded Cluster的Hash分片,hash索引只能满足字段完全匹配的查询,不能满足范围查询等。
db.person.createIndex( {a: "hashed"} )
db.places.createIndex( { loc : "2dsphere" } )
#TTL索引,在集合中的文档超过expireAfterSeconds关键字定义的时间后,会被自动删除。【删除过期文档的后台任务每60秒运行一次】
db.events.createIndex({"createdAt":1},{expireAfterSeconds: 3600})
#text索引可以包括任何值为字符串或者字符串元素数组的字段。为了执行文本检索查询,必须在集合上有一个text索引。
db.stores.createIndex( { name: "text", description: "text" } )

2、索引结构

MongoDB索引使用B树数据结构(确切的说是B-Tree,MySQL是B+Tree)。

当往某各个集合插入多个文档后,每个文档在经过底层的存储引擎持久化后,会有一个位置信息,通过这个位置信息,就能从存储引擎里读出该文档。

WiredTiger: WiredTiger在存储文档时生成的一个key【即位置信息:pos】,通过这个key能访问到对应的文档。

假设现在有个查询db.person.find( {age: 18} ),查询所有年龄为18岁的人,这时需要遍历所有的文档(全表扫描),根据位置信息读出文档,对比age字段是否为18。当然如果只有4个文档,全表扫描的开销并不大,但如果集合文档数量到百万、甚至千万上亿的时候,对集合进行全表扫描开销是非常大的,一个查询耗费数十秒甚至几分钟都有可能。

建立索引后,MongoDB会额外存储一份按age字段升序排序的索引数据,引结构类似如下:索引通常采用类似b- tree的结构持久化存储,以保证从索引里快速(O(logN)的时间复杂度)找出某个age值对应的位置信息,然后根据位置信息就能读取出对应的文档。


B-Tree != Binary Tree && B-Tree == Self-Balancing Tree

MongoDB默认会为插入的文档生成_id字段(如果应用本身没有指定该字段),_id是文档唯一的标识,为了保证能根据文档id快递查询文档,MongoDB默认会为集合创建_id字段的索引。

3、索引特性

  • 索引存储在内存(RAM)中,应该确保该索引的大小不超过内存的限制。
  • 如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。
  • 每个collection限制64个索引。
  • 索引名的长度不能超过125个字符。
  • 一个复合索引最多可以有31个字段。
  • 所有索引字段是一个数组,不能使用索引覆盖查询。
  • 正则表达式及非操作符,如in,not等;算术运算符,如mod,等;where子句。
  • 索引越多写性能越差,例如:一张频繁修改的collection ,其索引达到20-30索引性能严重瓶颈。
  • 建立索引是一个IO密集型操作,特别是当你的集合很大的时候。包括MySQL在内的所有支持辅助索引的数据库系统都有这种情况。如果你需要在一个大集合上建立索引,可以考虑在后台建立它。
  • 索引是有代价的,如果很少对集合进行读取,可以不使用索引。

4、索引语句优化

  • Profiling分析器

使用Profiling 查看慢查询。

db.setProfilingLevel(n,slowms=1000ms)#n=0 关闭Profiling。
#n=1 记录执行时间大于slowms的操作
#n=2 记录所有操作
#分析结果记录在system.profile集合。
  • 查询优化器

分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等。

MongoDB查询优化器:当有多个索引可用时,MongoDB会同时尝试每一个索引,最先拿到100条(或者所有)结果者为胜者。短暂的cache 上次的优化结果直到:– 1000 个更新以后,– reIndex或restart。

#告诉数据库使用什么索引
db.recipes.find( {calories: { $lt : 1000 } }).hint ( { _id : 1 } )
#告诉数据库不要使用什么索引
db.recipes.find({ calories: { $lt : 1000 } }).hint( { $natural : 1 } )db.collection.find(query,options).explain(options)
# eg:未对userid创建索引的情况
db.comment.find({userid:"1003"}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "articledb.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1003"}},"winningPlan" : {"stage" : "COLLSCAN",   ## 基于集合扫描"filter" : {"userid" : {"$eq" : "1003"}},"direction" : "forward"},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "9ef3740277ad","port" : 27017,"version" : "4.0.10","gitVersion" : "c389e7f69f637f7a1ac3cc9fae843b635f20b766"},"ok" : 1
}
# eg:对userid创建索引的情况
db.comment.find({userid:"1013"}).explain()
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "articledb.comment","indexFilterSet" : false,"parsedQuery" : {"userid" : {"$eq" : "1013"}},"winningPlan" : {"stage" : "FETCH","inputStage" : {"stage" : "IXSCAN",    ## 索引扫描"keyPattern" : {"userid" : 1},"indexName" : "userid_1","isMultiKey" : false,"multiKeyPaths" : {"userid" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"userid" : ["[\"1013\", \"1013\"]"]}}},"rejectedPlans" : [ ]},"serverInfo" : {"host" : "9ef3740277ad","port" : 27017,"version" : "4.0.10","gitVersion" : "c389e7f69f637f7a1ac3cc9fae843b635f20b766"},"ok" : 1
}

二、MongoDB 存储引擎

1、默认WiredTiger

存储引擎是MongoDB的核心组件,负责管理数据如何存储在硬盘和内存上。从MongoDB 3.2 版本开始,MongoDB 支持多数据存储引擎,MongoDB支持的存储引擎有:WiredTiger,MMAPv1和In-Memory。

从mongodb3.2开始默认的存储引擎是WiredTiger,3.3版本之前的默认存储引擎是MMAPv1,mongodb4.x版本不再支持MMAPv1存储引擎。WiredTiger是各种操作应用的理想选择,因此是MongoDB的默认存储引擎

MongoDB不仅能将数据持久化存储到硬盘文件中,而且还能将数据只保存到内存中;In-Memory存储引擎用于将数据只存储在内存中,只将少量的元数据和诊断日志(Diagnostic)存储到硬盘文件中,由于不需要Disk的IO操作,就能获取索取的数据,In-Memory存储引擎大幅度降低了数据查询的延迟(Latency)。

查看存储引擎【搜索engine】:
db.serverStatus()
db.serverStatus().connections

查看WiredTiger内部缓存到底占用了多少内存:
db.runCommand({serverStatus:1}).wiredTiger.cache[“bytes currently in the cache”]

2、Why WiredTiger

WiredTiger存储引擎的主要优势:

  • 最大化可用缓存: WiredTiger最大限度地利用可用内存作为缓存来减少I / O瓶颈。使用了两个缓存:WiredTiger缓存文件系统缓存。WiredTiger缓存存储未压缩的数据并提供类似内存的性能。操作系统的文件系统缓存存储压缩数据。当在WiredTiger缓存中找不到数据时,WiredTiger将在文件系统缓存中查找数据。

    mongodb从3.4版本开始默认使用内存为下面两个中的最大一个:

    • 50% of (RAM - 1 GB)
    • 256MB
  • 高吞吐量: WiredTiger使用“写入时复制” - 当文档更新时,WiredTiger将制作文档的新副本并确定最新版本以返回给读者。此方法允许多个客户端同时修改集合中的不同文档,从而实现更高的并发性和吞吐量。当应用程序使用具有多个内核的主机(越多越好)并且多个线程正在写入不同的文档时,实现最佳写入性能。

  • 减少存储空间并改善磁盘IOP: WiredTiger使用压缩算法来减少磁盘上存储的数据量。不仅存储减少了,而且随着从磁盘读取或写入更少的位,IOP性能也会提高。某些类型的文件比其他文件压缩得更好。文本文件是高度可压缩的,而二进制数据可能不是可压缩的,因为它可能已经被编码和压缩。使用压缩时,WiredTiger会产生额外的CPU周期,但用户可以配置压缩方案以优化CPU开销与压缩比。Snappy是默认的压缩引擎,在高压缩率和低CPU开销之间提供了良好的平衡。Zlib将实现更高的压缩比,但会产生额外的CPU周期。

  • 压缩(索引和journals日志):索引可以在内存和磁盘上压缩。WiredTiger利用前缀压缩来压缩索引,节省RAM使用以及释放存储IOP。默认情况下,使用Snappy压缩压缩journals日志。

  • 多核可扩展性:随着CPU制造商缩小到更小的平版印刷,功耗变得越来越成问题,处理器趋势已转向多核架构,以维持摩尔定律的节奏。WiredTiger在设计时考虑了现代的多核架构,并提供跨多核系统的可扩展性。危险指针,无锁算法和快速锁存等编程技术可最大限度地减少线程之间的争用。线程可以执行操作而不会相互阻塞 - 从而减少线程争用,更好的并发性和更高的吞吐量。

  • 文档级并发:WiredTiger使用文档级并发控制进行写操作。因此,多个客户端可以同时修改集合的不同文档。对于大多数读写操作,WiredTiger使用乐观并发控制[乐观锁]。WiredTiger仅在全局,数据库和集合级别使用意向锁。当存储引擎检测到两个操作之间的冲突时,会发生写入冲突,导致MongoDB透明地重试该操作。

在移动到WiredTiger缓存之前,在文件系统缓存中找到的数据首先经过解压缩过程。

WiredTiger缓存在保存尽可能多的工作集时表现最佳。但是,为需要它的其他进程(如操作系统,包括文件系统缓存)保留内存也很重要。这也包括MongoDB本身,因此整体上消耗的内存比WiredTiger主动使用的内存要多。

WiredTiger允许用户为其读取指定隔离级别。读取操作可以返回大部分副本集已接受或提交到磁盘的数据视图。这样可以保证应用程序只读取在发生故障时仍然存在的数据,并且在将新的副本集成员提升为主要成员时不会回滚。

3、checkpoint

在Checkpoint操作开始时,WiredTiger提供指定时间点(point-in-time)的数据库快照(Snapshot),该Snapshot呈现的是内存中数据的一致性视图。当向Disk写入数据时,WiredTiger将Snapshot中的所有数据以一致性方式写入到数据文件(Disk Files)中。一旦Checkpoint创建成功,WiredTiger保证数据文件和内存数据是一致性的,因此,Checkpoint担当的是还原点(Recovery Point),Checkpoint操作能够缩短MongoDB从Journal日志文件还原数据的时间。

当WiredTiger创建Checkpoint时,MongoDB将数据刷新到数据文件(Disk Files)中,在默认情况下,WiredTiger创建Checkpoint的时间间隔是60s,或产生2GB的Journal文件。在WiredTiger创建新的Checkpoint期间,上一个Checkpoint仍然是有效的,这意味着,即使MongoDB在创建新的Checkpoint期间遭遇到错误而异常终止运行,只要重启,MongoDB就能从上一个有效的Checkpoint开始还原数据。

当MongoDB以原子方式更新WiredTiger的元数据表,使其引用新的Checkpoint时,表明新的Checkpoint创建成功,MongoDB将老的Checkpoint占用的Disk空间释放。使用WiredTiger 存储引擎,如果没有记录数据更新的日志,MongoDB只能还原到上一个Checkpoint;如果要还原在上一个Checkpoint之后执行的修改操作,必须使用Jounal日志文件。

  • journal日志[预写日志]

WiredTiger使用预写日志的机制,在数据更新时,先将数据更新写入到日志文件,然后在创建Checkpoint操作开始时,将日志文件中记录的操作,刷新到数据文件,就是说:**通过预写日志和Checkpoint,将数据更新持久化到数据文件中,实现数据的一致性。**WiredTiger 日志文件会持久化记录从上一次Checkpoint操作之后发生的所有数据更新,在MongoDB系统崩溃时,通过日志文件能够还原从上次Checkpoint操作之后发生的数据更新。

  • 压缩

WiredTiger支持对所有集合和索引进行压缩。压缩可以以额外的CPU为代价最大限度地减少磁盘的使用。

默认情况下WiredTiger存储引擎使用snappy方式压缩所有集合,前缀压缩方式压缩索引。

对于集合的压缩还可以使用zlib方式压缩。

storage:joural:enabled: true    #启用journal日志,false为关闭engine:  wiredTiger  #指定存储引擎 wiredTiger:cacheSizeGB: 8    #来指定mongodb使用内存的多少-8GengineConfig:     #存储引擎的配置journalCompressor:  snappy        #指定journal日志的压缩方式indexConfig:                         #索引配置 prefixCompression:  true          #前缀压缩开启    collectionConfig:blockCompressor: snappy           #指定集合的压缩方式

4、Disk空间回收

当从MongoDB中删除文档(Documents)或集合(Collections)后,MongoDB不会将Disk空间释放给OS,MongoDB在数据文件(Data Files)中维护Empty Records的列表。当重新插入数据后,MongoDB从Empty Records列表中分配存储空间给新的Document,因此,不需要重新开辟空间。为了更新有效的重用Disk空间,必须重新整理数据碎片。

WiredTiger使用compact 命令,移除集合(Collection)中数据和索引的碎片,并将unused的空间释放,调用语法:

db.runCommand ( { compact: '<collection>' } )
eg:
db.runCommand({compact:'comment',force:true})
#在执行compact命令时,MongoDB会对当前的database加锁,阻塞其他操作。在compact命令执行完成之后,mongod会重建集合的所有索引

5、db.serverStatus()和db.stats()

监控实例的运行状态(内存使用、锁、用户连接等信息)。

# 一些重要信息
db.serverStatus().connections
db.serverStatus().locks
db.serverStatus().activeClients
db.serverStatus().opcounters
db.serverStatus().opcountersRepl
db.serverStatus().storageEngine
db.serverStatus().memdb.serverStatus()
{"host" : "mdb-6229df1e0f921362cbb1b28f-0","version" : "4.0.21","process" : "mongod","pid" : NumberLong(394490),"uptime" : 96,"uptimeMillis" : NumberLong(95864),"uptimeEstimate" : NumberLong(95),"localTime" : ISODate("2022-03-14T08:09:44.443Z"),"asserts" : {"regular" : 0,"warning" : 0,"msg" : 0,"user" : 65,"rollovers" : 0},"connections" : {"current" : 21,"available" : 979,"totalCreated" : 299,"active" : 3},
...db.stats()
{"db" : "test","collections" : 1,"views" : 0,"objects" : 100,"avgObjSize" : 33.22,"dataSize" : 3322,"storageSize" : 32768,"numExtents" : 0,"indexes" : 1,"indexSize" : 32768,"fsUsedSize" : 643317760,"fsTotalSize" : 32196526080,"ok" : 1,"operationTime" : Timestamp(1647246974, 1),"$clusterTime" : {"clusterTime" : Timestamp(1647246974, 1),"signature" : {"hash" : BinData(0,"pqfevp7IwKB0jYF1a8R3cPNQwJg="),"keyId" : NumberLong("7073430430610882562")}}
}

三、MongoDB 数据安全

1、为什么需要安全

默认情况下,MongoDB实例启动运行时是没有启用用户访问权限控制的,也就是说,在实例本机服务器上都可以随意连接到实例进行各种操作,MongoDB不会对连接客户端进行用户验证,这是非常危险的。

因此官网建议:

  • 使用新的端口,默认的27017端口如果一旦知道了ip就能连接上,不安全。
  • 置mongodb的网络环境,最好将mongodb部署到公司服务器内网,这样外网是访问不到的。公司内部访问使用vpn等。
  • 开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。

为了强制开启用户访问控制(用户验证),则需要在MongoDB实例启动时使用选项 --auth 或在指定启动配置文件中添加选项 auth=true。

2、基本概念

认证(Authentication):确认这个人是谁——认证管理:通过访问控制和授权管理,防止非授权访问。

授权(Authorization):确认这个该干什么——安全加固:通过操作系统和网络加固,保护数据库安全。

审计(Authentication):记录系统发生了什么——操作审计:通过操作记录,提供完整操作审计与分析。

加密(Authorization):只有授权用户才能理解——数据加密:通过数据存储和传输加密,保证数据安全。

RBAC:MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。

  • 传输加密——启用TLS/SSL加密传输保证网络传输安全。
# 前提:mongodb.pem文件和客户端文件client.pem文件通过openssl工具生成;mongodb需要开启ssl模式
mongo --ssl --sslCAFile ./mongodb.pem --sslPEMKeyFile ./client.pem --sslPEMKeyPassword yourpassword
  • 存储加密
mongod --enableEncryption --encryptionKeyFile mongodb-keyfile
  • 操作审计
# 操作审计支持CRUD、数据schema (DDL)、部署架构、用户认证与授权等
mongod --dbpath data/db --auditDestination file --auditFormat JSON --auditPath data/db/auditLog.json
  • 安全加固
# 关闭http接口
net.http.enabled=False
# 关闭运行json访问http端口
net.http.JSONenabled=False
# 管理Rest API接口
net.http.RESTInterfaceEnabled=False
# 监听的IP地址
net.bindIp=127.0.0.1,192.168.1.21
# 使用普通用户,而非root运行MongoDB
# 修改默认监听端口:27017

3、实操——单节点

# 用户权限的CRUD
use admin
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
db.createUser({user:"myadmin",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
db.system.users.find()
db.changeUserPassword("myroot", "12345678")
db.dropUser("myadmin")## 服务端
#有两种方式开启权限认证启动服务:一种是参数方式,一种是配置文件方式。
#方式一、在启动时指定参数 -- auth
mongod -f /etc/mongod.conf --auth#方式一二、配置文件方式
vim /etc/mongod.conf
security:#开启授权认证authorization: enabled## 客户端
#开启了认证的情况下的客户端登录
#有两种认证方式,一种是先登录,在mongo shell中认证;一种是登录时直接认证
#方式一、先登录,在mongo shell中认证
mongo --host 192.168.168.101 --port 27017
use admin
db.auth("myroot","123456")#方式二、登录时直接认证
mongo --host 192.168.168.101 --port 27017 --authenticationDatabase admin -umyroot -p123456
mongo --host 192.168.168.101 --port 27017 --authenticationDatabase articledb -u bobo -p 123456

3、实操——副本集

注意两点:

(1)副本集和共享集群的各个节点成员之间使用内部身份验证,可以使用密钥文件或x.509证书。密钥文件比较简单,本文使用密钥文件,官方推荐如果是测试环境可以使用密钥文件,但是正式环境,官方推荐x.509证书。原理就是,集群中每一个实例彼此连接的时候都检验彼此使用的证书的内容是否相同。只有证书相同的实例彼此才可以访问。

(2)使用客户端连接到mongodb集群时,开启访问授权。对于集群外部的访问。如通过可视化客户端,或者通过代码连接的时候,需要开启授权。

#第一步:添加安全认证用户
#只需要在主节点上添加用户,副本集会自动同步。
use admin
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})#第二步:创建副本集认证的key文件
#生成一个key文件到当前文件夹中。
openssl rand -base64 90 -out ./mongo.keyfile
chmod 400 ./mongo.keyfile
ll mongo.keyfile
#所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错: permissions on /mongodb/replica_sets/myrs_27017/mongo.keyfile are too open
cp mongo.keyfile /mongodb/replica_sets/myrs_27017
cp mongo.keyfile /mongodb/replica_sets/myrs_27018
cp mongo.keyfile /mongodb/replica_sets/myrs_27019#第三步:分别编辑几个服务的mongod.conf文件,添加相关内容
vim /mongodb/replica_sets/myrs_2701x/mongod.conf
security:#KeyFile鉴权文件keyFile: /mongodb/replica_sets/myrs_2701X/mongo.keyfile#开启认证方式运行authorization: enabled#第四步: 重新启动副本集群【先通过kill -2关闭服务】
mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf
mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf
mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf#第五步:在主节点上添加普通账号
#先用管理员账号登录
#切换到admin库
use admin
#管理员账号认证
db.auth("myroot","123456")
#切换到要认证的库
use articledb
#添加普通用户
db.createUser({user: "bobo", pwd: "123456", roles: ["readWrite"]})#重新连接,使用普通用户 bobo重新登录,查看数据。也要使用rs.status()命令查看副本集是否健康。

3、实操——分片集群

分片集群环境下的安全认证和副本集环境下基本上一样。
但分片集群的服务器环境和架构较为复杂,建议在搭建分片集群的时候,直接加入安全认证和服务器间的鉴权,如果之前有数据,可先将之前的数据备份出来,再还原回去。

#第一步:关闭分片服务器副本集中的服务,建议依次关闭仲裁节点、副本节点、主节点。#第二步:创建副本集认证的key文件
#生成一个key文件到当前文件夹中。
openssl rand -base64 90 -out ./mongo.keyfile
chmod 400 ./mongo.keyfile
ll mongo.keyfile
#将该文件分别拷贝到多个目录
echo '/mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile /mongodb/sharded_cluster/myshardrs01_27118/mongo.keyfile /mongodb/sharded_cluster/myshardrs01_27218/mongo.keyfile /mongodb/sharded_cluster/myshardrs02_27318/mongo.keyfile /mongodb/sharded_cluster/myshardrs02_27418/mongo.keyfile /mongodb/sharded_cluster/myshardrs02_27518/mongo.keyfile /mongodb/sharded_cluster/myconfigrs_27019/mongo.keyfile /mongodb/sharded_cluster/myconfigrs_27119/mongo.keyfile /mongodb/sharded_cluster/myconfigrs_27219/mongo.keyfile /mongodb/sharded_cluster/mymongos_27017/mongo.keyfile /mongodb/sharded_cluster/mymongos_27117/mongo.keyfile' | xargs -n 1 cp /root/mongo.keyfile#第三步:分别编辑几个服务【共十一个】的mongod.conf文件,添加相关内容
vim /mongodb/sharded_cluster/myshardrs01_2721X/mongod.conf
security:#KeyFile鉴权文件keyFile: /mongodb/sharded_cluster/myshardrs01_2721X/mongod.conf#开启认证方式运行#authorization: enabled
#mongos 比mongod少了authorization:enabled的配置。原因是,副本集加分片的安全认证需要配置两方面的,副本集各个节点之间使用内部身份验证,用于内部各个mongo实例的通信,只有相同keyfile才能相互访问。所以都要开启 keyFile:/mongodb/sharded_cluster/mymongos_27117/mongo.keyfile 。然而对于所有的mongod,才是真正的保存数据的分片。mongos只做路由,不保存数据。所以所有的mongod开启访问数据的授权authorization:enabled。这样用户只有账号密码正确才能访问到数据。#第四步: 重新启动分片集群
#这里有个非常特别的情况,就是启动顺序。先启动配置节点,再启动分片节点,最后启动路由节点。如果先启动分片节点,会卡住,提示:about to fork child process, waiting until server is ready for connections。这也许是个 bug,原因未知。
mongos -f /mongodb/sharded_cluster/myconfigrs_27019/mongod.conf
mongos -f /mongodb/sharded_cluster/myconfigrs_27119/mongod.conf
mongos -f /mongodb/sharded_cluster/myconfigrs_27219/mongod.confmongos -f /mongodb/sharded_cluster/myshardrs01_27018/mongod.conf
mongos -f /mongodb/sharded_cluster/myshardrs01_27118/mongod.conf
mongos -f /mongodb/sharded_cluster/myshardrs01_27218/mongod.confmongos -f /mongodb/sharded_cluster/myshardrs02_27318/mongod.conf
mongos -f /mongodb/sharded_cluster/myshardrs02_27418/mongod.conf
mongos -f /mongodb/sharded_cluster/myshardrs02_27518/mongod.confmongos -f /mongodb/sharded_cluster/mymongos_27017/mongos.conf
mongos -f /mongodb/sharded_cluster/mymongos_27117/mongos.conf#第五步:在分片路由节点上创建帐号和认证
#创建一个管理员账号
mongo --port 27017
use admin
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
#创建一个普通账号
use admin
db.auth("myroot","123456")
use articledb
db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite",db: "articledb" }]})
db.auth("bobo","123456")
#通过mongos添加的账号信息,只会保存到配置节点的服务中,具体的数据节点不保存账号信息,因此,分片中的账号信息不涉及到同步问题。#分别使用管理员账号和普通账号登录测试:退出连接,重新连接服务,使用普通权限帐号访问数据

四、MongoDB 性能优化

1、操作系统优化

内核和文件系统
关闭数据库文件的access-time
内核网络参数调整
IO调度策略
提高默认文件描述符和进程/线程数限制
Dirty Ratio
Swappiness
HugePages
NUMA
readahead设置
NTP时间服务器

2、监控工具优化

  • db.serverStatus()

监控实例的运行状态(内存使用、锁、用户连接等信息)。

通过持续观察这个状态,可以看到系统运行的趋势。

# 一些重要信息
db.serverStatus()
db.serverStatus().connections
db.serverStatus().locks
db.serverStatus().activeClients
db.serverStatus().opcounters
db.serverStatus().opcountersRepl
db.serverStatus().storageEngine
db.serverStatus().mem
  • db.stats()

查看当前数据库的统计信息。

db.stats()
{"db" : "test","collections" : 1,"views" : 0,"objects" : 100,"avgObjSize" : 33.22,"dataSize" : 3322,"storageSize" : 32768,"numExtents" : 0,"indexes" : 1,"indexSize" : 32768,"fsUsedSize" : 643317760,"fsTotalSize" : 32196526080,"ok" : 1,"operationTime" : Timestamp(1647246974, 1),"$clusterTime" : {"clusterTime" : Timestamp(1647246974, 1),"signature" : {"hash" : BinData(0,"pqfevp7IwKB0jYF1a8R3cPNQwJg="),"keyId" : NumberLong("7073430430610882562")}}
}
  • db.collection.status()

查看集合的当前状态。所有参考均以字节为单位。

  • db.currentOp()

查看数据库当前执行什么操作。用于查看长时间运行进程。通过(执行时长、操作、锁、等待锁时长)等条件过滤。
如果发现一个操作太长,把数据库卡死的话,可以用这个命令杀死他 :

db.killOp(608605)
  • mongostat

实时数据库状态,读写、加锁、索引命中、缺页中断、读写等待队列等情况。
每秒刷新一次状态值,并能提供良好的可读性,通过这些参数可以观察到MongoDB系统整体性能情况。

mongostat --host 10.214.11.59:32409,10.214.11.59:31822,10.214.11.59:31245  -u6229df1e0f921362cbb1b28f -pGotapdatad8! --authenticationDatabase admin

mongostat重要指标
command:语句操作,在压力测试过程需要注意是否均匀执行。
used% :内存使用比例,设置CacheSizeGB 只是大概进行限制 。一般占用到80%使用,超过之后有一个进程使用最近最少使用算法进行内存刷新。达到95%的时候,所有的进程会进行驱逐内存的操作。
dirty%:数据进入内存,但是还没有进入磁盘的比例 。特别是重写的系统需要注意,如果特别高的时候可能是磁盘IO不足。
res:实际占用内存。
conn:当前连接数。
qr|qw:客户端查询排队长度(读|写)。最好为0,如果有堆积,数据库处理慢。

qr|qw:客户端查询排队长度(读|写)。最好为0,如果有堆积,数据库处理慢。

  • mongotop

mongotop用来跟踪MongoDB的实例, 提供每个集合的统计数据。
默认情况下,mongotop每一秒刷新一次。

mongotop --host 10.214.11.59:32409,10.214.11.59:31822,10.214.11.59:31245  -u6229df1e0f921362cbb1b28f -pGotapdatad8! --authenticationDatabase admin

mongotop重要指标:
ns:数据库命名空间,后者结合了数据库名称和集合。
total:mongod在这个命令空间上花费的总时间。
read:在这个命令空间上mongod执行读操作花费的时间。
write:在这个命名空间上mongod进行写操作花费的时间。

3、数据库优化

  • 参数调整

1、连接数

MongoDB实例接受的默认最大并发连接数:1000000

net:maxIncomingConnections:1000

注:并发连接数不能大于操作系统最大文件句柄数。如果大于操作系统最大文件句柄数,则设置无效。

2、缓存大小的设置

默认情况下,将使用较大的以下两者之一:50% of (RAM - 1 GB)、256MB

  • 语句优化

优化查询语句(慢查询日志–分析执行计划)

详见 二、MongoDB索引

  • 索引优化

详见 二、MongoDB索引

1、Selectivity——过滤性

2、复合索引——索引顺序,由过滤性决定优先级

3、使用索引排序查询结果
在MongoDB中,排序操作可以通过根据索引中的排序检索文档来获取排序顺序。如果查询计划器无法从索引获取排序顺序,则会将结果排序到内存中。使用索引的排序操作通常比不使用索引的操作具有更好的性能。另外,不使用索引的排序操作会在使用32MB内存时中止。

五、MongoDB 备份与恢复

1、MongoDB冗余和备份

冗余≠备份。

冗余的目的:7*24h可用。故障发生无需干预。系统升级维护对用户透明。

备份的目的:灾难恢复。人工误操作。程序Bug损坏数据。

MongoDB的备份方式有三种:

  • mongodump/mongorestore

    逻辑备份。将集合导出成BSON文件,同时生成一份JSON格式的索引元数据信息。可指定导出的数据库(database)和集合(collection)。不包含索引(恢复时重建)。

    参数选择:
    –oplog 记录开始进行dump到dump结束之间所有的oplog
    –query 选择性导出。

  • 文件备份或磁盘快照

    物理备份。前提是必须开启journal日志。 为保证数据一致性,要求日志和数据文件在一个物理盘上。如果journal日志和数据文件在一个物理磁盘上,可以不加Lock。

    步骤:

    1. db.fsyncLock()
    2. 复制/快照
    3. db.fsyncUnlock()
  • Ops Manager自动备份

    通过数据同步重建一个镜像数据库。每6小时形成一次快照。oplog被保存48小时。

备份方法 适合场景 使用限制
mongodump 适合少量数据3.0之前单进程 不备份索引数据,恢复时重建;不适合大数据量,不支持增量;不适合分片环境
文件系统备份 使用LVM;备份和恢复速度快;适用复制集环境 需要确保数据无写入;不适合分片环境;不支持恢复到特定时间点
Ops Manager (企业版) 适用于大数量 适用于复制集环境和分片环境 支持自动增量备份 对少量数据的简单环境而言,部署复 杂

以上三种备份方式都适用于MongoDB副本集备份。

2、分片集备份

MongoDB分片集群备份实质是对分片集群中副本集的备份。

在分片集群下,不可能在一个时间点上得到一个完整集群状态的快照。当集群越来越大时,从备份恢复整个架构的几率越来越小的。 因此,对于分片集群的备份,只需独自备份config server和复制集。

在对分片集群进行备份与恢复操作前,要关闭balancer。备份时,直接连接分片集群的mongod而不是通过mongos。

对于比较小型的分片集群,可以直接通过mongodump连接到mongos进行备份,备份的文件将包含config服务器的元数据信息和实际数据。

  • 备份分片流程:
1)关闭balancer。
注意:连接到mongos而不是config server实例
sh.setBalancerState(false) 或
sh.stopBalancer() 或
use config
db.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );
2)备份集群元数据。使用mongodump备份任意一台config server。可以直接连接任意一台的config mongod实例,也可以通过mongos连接。
# mongodump --db config
3)备份shard集群内各个replica set。可并行执行。
4)启用balancer。注意:连接到mongos而不是config server实例。
sh.setBalancerState(true) 或
sh.startBalancer() 或
use config
db.settings.update( { _id: "balancer" }, { $set : { stopped: false } } , true );

3、MongoDB的恢复

MongoDB的恢复方式也有三种:

  • 文档级恢复:mongorestore
    –oplogReplay 基于时间点备份的恢复
    –oplogLimit 恢复到任意状态
  • 文件系统恢复
    所有数据库文件
    选择特定的数据库和集合恢复
    Replay Oplog
  • Ops Manager自动恢复
    副本集可以恢复到任意状态。
    分片集群可以恢复到15min之前的状态。

六、MongoDB 运维工具——Ops Manager

前面的章节中,多次提到了Ops Manager。

官网:https://www.mongodb.com/products/ops-manager

1、Ops Manager用途

  • Ops Manager自动化

  • Ops Manager监控与备份

  • Ops Manager日常管理

2、Ops Manager工作原理

Agents承担了大部分工作:自动化、监控、备份。
OPS Manager负责小部分但最重要的工作:人机交互、信息的收集和分发。

3、Ops Manager使用

作为独立后台使用——中小企业
集成到企业现有系统——大企业

https://docs.opsmanager.mongodb.com/current/api/

https://github.com/zhangyaoxing/ops-api-demo

OPS Manager集成到LDAP
MongoDB集成到LDAP

MongoDB 文档数据库【进阶】相关推荐

  1. MongoDB文档数据库

    一,引言 MongoDB 是一个开源的文档数据库,并是领先的NoSQL数据库. MongoDB 是由C++语言编写. 通过本系列教程的讲解,使得学习者可以了解并掌握创建和部署高度可扩展和高性能的面向对 ...

  2. python mongodb_Python操作MongoDB文档数据库

    1.Pymongo 安装 安装pymongo: pip install pymongo PyMongo是驱动程序,使python程序能够使用Mongodb数据库,使用python编写而成: 2.Pym ...

  3. MongoDB 文档数据库

    文章目录 一.MongoDB 基本介绍 1.简介 2.应用场景 3.MongoDB的特点 4.MongoDB的优势 5.体系架构 二.MongoDB 索引 1.索引操作 2.索引结构 3.索引特性 4 ...

  4. 速递!MongoDB最新书籍出版啦:MongoDB进阶与实战-微服务整合、性能优化、架构管理

    新书速递 近期,MongoDB中文社区核心成员之一唐卓章老师出了一本MongoDB最新书籍--<MongoDB进阶与实战:微服务整合.性能优化.架构管理>,全面涵盖了MongoDB的基本原 ...

  5. 使用Spring Boot和MongoDB创建REST API

    Spring Boot是一个自以为是的框架,可简化Spring应用程序的开发. 它使我们摆脱了复杂配置文件的束缚,并帮助我们创建了不需要外部servlet容器的独立Spring应用程序. 这听起来实在 ...

  6. MongoDB与Spring Data项目

    如今,我们所有人都在观察NoSql解决方案的爆炸式增长. 我已经习惯了RDBMS,但这些并不是您可能遇到的所有挑战的解决方案. 根据最近的经验,我有机会使用MongoDB –文档数据库. 在本文中,我 ...

  7. 第五十四期:MongoDB与MySQL:如何选择

    MongoDB和MySQL分别是领先的开源NoSQL和关系数据库.哪个最适合您的应用程序? 作者:XEyes行走的CODE来源 MongoDB和MySQL分别是领先的开源NoSQL和关系数据库.哪个最 ...

  8. mongodb不等于某个值_MongoDB的安装以及基本增删改查命令

    MongoDB 介绍 mongodb 和大多数NoSQL 数据库(redis,memcached 等)一样,都是以 kv数据库(key/value) 存储数据 不同的是mongodb 文档数据库,存储 ...

  9. mongodb索引生成HTML页面,mongodb高阶:索引创建、聚合查询、复制集、分片、创建备份和部署...

    先前我们讨论了mongodb的进阶查询:投影查询.分页查询以及对查询结果进行排序,从本节起我们开始学习mongodb相关的高级技术,首先我们会讨论mongodb如何创建索引,索引是数据库中最重要的东西 ...

最新文章

  1. libevent和libev的区别对比(二)
  2. SAP Cloud Application Programming CatalogService 默认的路径
  3. mysql不能存字母,使用不常見的字母/符號時,MySql數據庫不能正確存儲數據
  4. Flink 1.11 SQL 十余项革新大揭秘,哪些演变在便捷你的使用体验?
  5. linux高级命令组合
  6. 让AI打工!搜狗全体员工于3月12日狗胜节放假一天
  7. 用c语言输出魔方阵答案,如何用C语言输出一个1—16 组成的4*4的魔方阵
  8. android获取上下文对象,如何在Android服务类中获取上下文
  9. deepfacelive实时AI换脸直播使用教程
  10. android m是什么单位,M代表什么单位?
  11. 超详细的微信公众号创建与管理教程
  12. 计算机量子化学计算焓,本科毕业论文--量子化学计算的基本原理及应用.doc
  13. poi-3.17版本 和若依框架结合--excel导出,excel图片导出
  14. java迁移框架_Java敏捷数据库迁移框架——Flyway
  15. Win7蓝牙耳机怎么连接电脑
  16. Batch Normalization介绍
  17. RDBMS(关系型数据库)与HBase的对比
  18. High-speed Charting Control(MFC绘图控件)--MFC绘图Demo(包含鼠标响应)
  19. 每周新品|鉴黄API上线 云市场2017最值得期待的产品盘点
  20. AE 枪口火焰的五毛特效

热门文章

  1. 阿里云 Redis 报出You can't read against a non-read redis.解决方案
  2. Python近期练习小案例
  3. Omni扫块,和非原生归集
  4. 新浪微博视频批量上传社区投稿工具教程
  5. 第一章 计算机网络和因特网
  6. 网站自动链接SEO优化技巧
  7. 奋发图强半年多,终于四面阿里如愿拿到心仪offer定级P7
  8. IT定律之计算机行业发展规律——三大定律
  9. WPF窗体自适应电脑分辨率的问题
  10. 2012IT公司校园招聘笔试面试题