57

MongoDB是什么?看完你就知道了!

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzIxNzU1Nzk3OQ%3D%3D&%3Bmid=2247489605&%3Bidx=2&%3Bsn=59e92c5a4b1de59582eaee78eaf3a8dd
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

code小生  一个专注大前端领域的技术平台 公众号回复 Android 加入安卓技术群

☞ 程序员进阶必备资源免费送「多种技术」 ☜

来源: http://suo.im/5e8a94

一、概述

1.MongoDB是什么?用一句话总结

MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统。没错MongoDB就是数据库,是NoSQL类型的数据库。

2.为什么要使用MongoDB?

(1)MongoDB提出的是文档、集合的概念,使用BSON(类JSON)作为其数据模型结构,其结构是面向对象的而不是二维表,存储一个用户在MongoDB中是这样子的。


username:'123',
password:'123'

使用这样的数据模型,使得MongoDB能在生产环境中提供高读写的能力,吞吐量较于mysql等SQL数据库大大增强。

(2)易伸缩,自动故障转移。易伸缩指的是提供了分片能力,能对数据集进行分片,数据的存储压力分摊给多台服务器。自动故障转移是副本集的概念,MongoDB能检测主节点是否存活,当失活时能自动提升从节点为主节点,达到故障转移。

(3)数据模型因为是面向对象的,所以可以表示丰富的、有层级的数据结构,比如博客系统中能把“评论”直接怼到“文章“的文档中,而不必像myqsl一样创建三张表来描述这样的关系。

3.主要特性

(1)文档数据类型

SQL类型的数据库是正规化的,可以通过主键或者外键的约束保证数据的完整性与唯一性,所以SQL类型的数据库常用于对数据完整性较高的系统。MongoDB在这一方面是不如SQL类型的数据库,且MongoDB没有固定的Schema,正因为MongoDB少了一些这样的约束条件,可以让数据的存储数据结构更灵活,存储速度更加快。

(2)即时查询能力

MongoDB保留了关系型数据库即时查询的能力,保留了索引(底层是基于B tree)的能力。这一点汲取了关系型数据库的优点,相比于同类型的NoSQL redis 并没有上述的能力。

(3)复制能力

MongoDB自身提供了副本集能将数据分布在多台机器上实现冗余,目的是可以提供自动故障转移、扩展读能力。

(4)速度与持久性

MongoDB的驱动实现一个写入语义 fire and forget ,即通过驱动调用写入时,可以立即得到返回得到成功的结果(即使是报错),这样让写入的速度更加快,当然会有一定的不安全性,完全依赖网络。

MongoDB提供了Journaling日志的概念,实际上像mysql的bin-log日志,当需要插入的时候会先往日志里面写入记录,再完成实际的数据操作,这样如果出现停电,进程突然中断的情况,可以保障数据不会错误,可以通过修复功能读取Journaling日志进行修复。

(5)数据扩展

MongoDB使用分片技术对数据进行扩展,MongoDB能自动分片、自动转移分片里面的数据块,让每一个服务器里面存储的数据都是一样大小。

4.C/S服务模型

MongoDB核心服务器主要是通过mongod程序启动的,而且在启动时不需对MongoDB使用的内存进行配置,因为其设计哲学是内存管理最好是交给操作系统,缺少内存配置是MongoDB的设计亮点,另外,还可通过mongos路由服务器使用分片功能。

MongoDB的主要客户端是可以交互的js shell 通过mongo启动,使用js shell能使用js直接与MongoDB进行交流,像使用sql语句查询mysql数据一样使用js语法查询MongoDB的数据,另外还提供了各种语言的驱动包,方便各种语言的接入。

5.完善的命令行工具

mongodump和mongorestore,备份和恢复数据库的标准工具。输出BSON格式,迁移数据库。

mongoexport和mongoimport,用来导入导出JSON、CSV和TSV数据,数据需要支持多格式时有用。mongoimport还能用与大数据集的初始导入,但是在导入前顺便还要注意一下,为了能充分利用好mongoDB通常需要对数据模型做一些调整。

mongosniff,网络嗅探工具,用来观察发送到数据库的操作。基本就是把网络上传输的BSON转换为易于人们阅读的shell语句。

因此,可以总结得到,MongoDB结合键值存储和关系数据库的最好特性。因为简单,所以数据极快,而且相对容易伸缩还提供复杂查询机制的数据库。MongoDB需要跑在64位的服务器上面,且最好单独部署,因为是数据库,所以也需要对其进行热备、冷备处理。

二、进入MongoDB shell

因为本篇文章不是API手册,所有这里对shell的使用也是基础的介绍什么功能可以用什么语句,主要是为了展示使用MongoDB shell的方便性,如果需要知道具体的MongoDB shell语法可以查阅官方文档。

1.切换数据库

use dba

创建数据库并不是必须的操作,数据库与集合只有在第一次插入文档时才会被创建,与对数据的动态处理方式是一致的。简化并加速开发过程,而且有利于动态分配命名空间。如果担心数据库或集合被意外创建,可以开启严格模式。

2.插入语法

db.users.insert({username:"smith"})
db.users.save({username:"smith"})
  • 区别: 若新增的数据中存在主键 ,insert() 会提示错误,而save() 则更改原来的内容为新内容。如:

    已存在数据:{_id : 1, " name " : " n1 " },再次进行插入操作时,insert({_id : 1, " name " : " n2 " }) 会报主键重复的错误提示,save({ _id : 1, " name " : " n2 " }) 会把 n1 修改为 n2 。

  • 相同点: 若新增的数据中没有主键时,会增加一条记录。已存在数据:{ _id : 1, " name " : " n1 " },再次进行插入操作时,insert({ " name " : " n2 " }) 插入的数据因为没有主键,所以会增加一条数据,save({ " name " : " n2 " }) 增加一条数据。

3.查找语法

db.users.find()
db.users.count()

4.更新语法

db.users.update({username:"smith"},{$set:{country:"Canada"}})
//把用户名为smith的用户的国家改成Canada

db.users.update({username:"smith"},{$unset:{country:1}})
//把用户名为smith的用户的国家字段给移除

db.users.update({username:"jones"},{$set:{favorites:{movies:["casablance","rocky"]}}})
//这里主要体现多值修改,在favorties字段中添加多个值

db.users.update({"favorites.movies":"casablance"},{$addToSet:{favorites.movies:"the maltese"}},false,true)
//多项更新

5.删除语法

db.foo.remove() //删除所有数据
db.foo.remove({favorties.cities:"cheyene"}) //根据条件进行删除
db.drop() //删除整个集合

6.索引相关语法

db.numbers.ensureIndex({num:1})
//创建一个升序索引
db.numbers.getIndexes()
//获取全部索引

7.基本管理语法

show dbs
//查询所有数据库
show collections
//显示所有表
db.stats()
//显示数据库状态信息
db.numbers.stats()
//显示集合表状态信息
db,shutdownServer()
//停止数据库
db.help()
//获取数据库操作命令
db.foo.help()
//获取表操作命令
tab 键 //能自动帮我们补全命令

以上的命令只是简单实例,假设如果你之前没有学习过任何数据库语法,同时开始学sql查询语法和MongoDB 查询语法,你会发现哪一个更简单呢?如果你使用的是java驱动去操作MongoDB,你会发现任何的查询都像Hibernate提供出来的查询方式一样,只要构建好一个查询条件对象,便能轻松查询(接下来会给出示例),博主之前熟悉ES6,所以入手MongoDB js shell完成没问题,也正因为这样简洁,完善的查询机制,深深的爱上了MongoDB。

三、使用java驱动

使用java驱动链接MongoDB是一件非常简单的事情,简单的引用,简单的做增删改查。在使用完java驱动后我才发现spring 对MongoDB 的封装还不如官方自身提供出来的东西好用,下面简单的展示一下使用。

1.使用maven引入jar包

    <dependency>
<groupId>org.mongodbgroupId>
<artifactId>mongodb-driver-syncartifactId>
<version>3.8.0-beta3version>
dependency>

2.创建一个访问客户端

MongoClient client = MongoClients.create(“mongodb://10.201.76.94:27017”);

3.获取集合数量

public long count() {
MongoClient client = this.getClient();
MongoCollection collections= client.getDatabase( "mongodb_db_name").getCollection( "mongodb_collection_name");
return collections.count();
}

4.查询集合

public List
 find
  (Document params,Bson sort,int skip,int limit) 
 {
MongoClient client = this.getClient();
MongoCollection collections= client.getDatabase( "mongodb_db_name").getCollection( "mongodb_collection_name");
List list = new ArrayList (Integer.valueOf(config.getPro( "sync_limit")));
collections.find(params).sort(sort).skip(skip).limit(limit).forEach( new Block () {
@Override
public void apply(Document document) {
list.add(document);
}
});
return list;
}

这里只举例了简单的链接与简单的MongoDB操作,可见其操作的容易性。使用驱动时是基于TCP套接字与MongoDB进行通信的,如果查询结果较多,恰好无法全部放进第一服务器中,将会向服务器发送一个getmore指令获取下一批查询结果。

插入数据到服务器时间,不会等待服务器的响应,驱动会假设写入是成功的,实际是使用客户端生成对象id,但是该行为可以通过配置配置,可以通过安全模式开启,安全模式可以校验服务器端插入的错误。

四、schema 设计原则

1.需要关注MongoDB的自身的特性

要清楚了解MongoDB的基本数据单元。在关系型数据库中有带列和行的数据表。而MongoDB数据的基本单元是BSON文档,在键值中有指向不定类型值的键,MongoDB拥有即时查询,但不支持联结操作,简单的键值存储只能根据单个键来获取值,不支持事务,但支持多种原子更新操作。

2.需要关注系统本身的读写特性

如读写比是怎样的,需要何种查询,数据是如何更新的,会不会存在什么并发问题,数据结构化的程度是要求高还是低。系统本身的需求决定mysql还是MongoDB。

3.关注MongoDB schema 的设计模式

  • 内嵌与引用:当子对象总是出现在父对象的上下文中时,使用内嵌文档;否则将子对象单独存一个集合。

  • 一对多的关系:在“多”的集合关系中添加id指向依赖的id。

  • 多对多:在其中一种对应关系中使用对象数组指向另外一个对象。

  • 树:具化路径,在树中的每个节点都包含一个path字段,该字段具体保存了每个节点祖先的id。

  • 动态属性:可以为不同的动态属性添加索引,如果需要将属性圈在一个范围,那么可以通过key-value的方式,然后在统一的key上面加索引。

  • 关于事务:如果需要事务支持,那么只能选择另一种数据库,或者提供补偿性事务来解决事务的问题。

在关于schema 的设计中要注意一些原则,比如:

  • 不能创建没用的索引

  • 不能在同一个字段中存不同的类型

  • 不能把多类实体都放在一个集合里 不能创建体积大、嵌套深的文档

  • 不能过多的创建集合,集合、索引、数据库的命名空间都是有限的

  • 不能创建无法分片的集合

4.关注MongoDB里面一些具体细节

(1)关注数据库的概念

数据库是集合的逻辑与物理分组,MongoDB没有提供创建数据库的语法,只有在插入集合时,数据库才开始建立。创建数据库后会在磁盘分配一组数据文件,所有集合、索引和数据库的其他元数据都保存在这些文件中,查阅数据库使用磁盘状态可通过。

db.stats()

(2)关注集合概念

集合是结构上或概念上相似得文档的容器,集合的名称可以包含数字、字母或 . 符号,但必须以字母或数字开头,完全。

限定集合名不能超过128个字符,实际上 . 符号在集合中很有用,能提供某种虚拟命名空间,这是一种组织上的原则,和其他集合是一视同仁的。 在集合中可以使用。

system.namespaces //查询当前数据库中定义的所有命名空间
system.indexes //存储当前数据库的所有索引定义

(3)关注文档

其次是键值,在MongoDB里面所有的字符串都是UTF-8类型。 数字类型包括double、int、long。 日期类型都是UTC格式,所以在MongoDB里面看到的时间会比北京时间慢8小时。 整个文档大小会限制在16m以内,因为这样可以防止创建难看的数据类型,且小文档可以提升性能,批量插入文档理想数字范围是10~200,大小不能超过16MB。

五、索引与查询优化

1.索引的经验法则

(1)索引能显著减少获取文档的所需工作量,具体的对比可以通过  .explain() 方法进行对比

(2)解析查询时MongoDB通过最优计划选择一个索引进行查询,当没有最适合索引时,会先不同的使用各个索引进行查询,最终选出一个最优索引做查询

(3)如果有一个a-b的复合索引,那么仅针对a的索引是冗余的

(4)复合索引里的键的顺序是很重要的

2.索引类型

(1)单键索引

(2)复合索引

(3)唯一性索引

(4)稀疏索引

如索引的字段会出现null的值,或是大量文档都不包含被索引的键。

3.索引的构建问题

如果数据集很大时,构建索引将会花费很长的时间,且会影响程序性能,可通过

db.currentOp() //查看索引的构建时间

当使用 mongorestore 时会重新构建索引。 当曾经执行过大规模的删除时,可使用

db.values.reIndex() 

对索引进行压缩,重建。

4.识别慢查询

(1)查阅慢查询日志

grep -E '([0-9])+ms' mongod.log //使用grep 命令 识别命令信息

db.setProfillingLevel(2) //使用解刨器,将记录每次的读写到日志

db.setProfillingLevel(1) //只记录慢(100ms)操作

(2)分析慢查询

db.values.find({}).sort({close:-1}).limit(1).explain()
  • scanOrder 字段表明没有使用索引

  • cursor当没有索引时,用的是BasicCursor,当使用索引时使用的是BtreeCursor

  • n 表示需要返回的结果集

  • nscanned表示需要遍历的文档数 indexBounds 表示索引边界

注意新版本的MongoDB 的explain方法是需要参数的,不然只显示普通的信息。

六、MongoDB副本集

本节同样主要简单呈现MongoDB副本集搭建的简易性,与副本集的强壮性,监控容易性

1.为什么要使用副本集

提供主从复制能力,热备能力,故障转移能力

2.构建方式

rs.initiate()
rs.add("localhost:40001")
rs.add("localhost:40002",{arbiterOnly:true})

3.监控

db.isMasrter()
rs.status()

4.副本集的工作原理

实际上MongoDB对副本集的操作跟mysql主从操作是差不多的,先看一下mysql的主从数据流动过程

主binlog -> 从relay.log -> 从bin.log -> 从数据库

而MongoDB主要依赖的日志文件是oplog

主oplog -> 从oplog

写操作先被记录下来,添加到主节点的oplog里。 与此同时,所有从结点复制oplog。 首先,查看自己oplog里最后一条的时间戳; 其次,查询主节点oplog里所有大于此时间戳的条目;最后,把那些条目添加到自己的oplog里并应用到自己的库里。 从节点使用长轮询立即应用来自主结点oplog的新条目。

当遇到以下情况,从节点会停止复制

  • 如果从节点在主节点的oplog里找不到它所同步的点,那么会永久停止复制

  • 一旦某个从节点没能 在主节点的oplog里找到它已经同步的点,就无法再保证这个从结点的完美副本

local数据库保存了所有副本集元素据和oplog日志

  • replset.minvalid 包含指定副本集成员的初始化同步信息

  • system.replset 保存在副本集配置文档

  • system.indexes 标准索引说明容器

  • me slaves 主要用于写关注

可以使用以下命令查看复制情况

db.oplog.rs.findOne()
  • ts 保存了该条目的BSON时间戳

  • t 是从纪元开始的描述

  • i是计数器

  • op 表示操作码

  • ns 标明了有关的命名空间

5.心跳检测

每个副本集成员每秒钟ping一次其他所有成员,可以通过rs.status()看到节点上次的心跳检测时间戳和健康状况。

6.故障转移

这个点没必要过多描述,但是有一个特殊场景,如果从节点和仲裁节点都被杀了,只剩下主节点,他会把自己降级成为从节点。

7.提交与回滚

如果主节点的数据还没有写到从库,那么数据不能算提交,当该主节点变成从节点时,便会触发回滚,那些没写到从库的数据将会被删除,可以通过rollback子目录中的BSON文件恢复回滚的内容。

8.驱动与复制

(1)使用单节点链接

只能链接到主节点,如果链接到从节点的话,会被拒绝写入操作,但是如果没有使用安全模式,因为mongo的fire and forget 特性,会把拒绝写入的异常给吃掉。

(2)使用副本集方式链接

能根据写入的情况自动进行故障转移,但是当副本集进行新的选举时,还是会出现故障,如果不使用安全模式,依旧会出现写不进去,但现实成功的情况。

(3)写关注

可以使用写关注来关注数据是否已经被写入MongoDB的库中,使用写关注会消耗性能,需要在速度和持久性之间做出权衡。

七、分片

分片是数据库切分的一个概念实现,这里也是简单总结为什么要使用分片以及分片的原理,操作。

1.为什么需要分片

当数据量过大,索引和工作数据集占用的内存就会越来越多,所以需要通过分片负载来解决这个问题

2.分片的工作原理

(1)分片组件

  • 分片:每个分片都是一个副本集

  • mongos路由器:是一个路由器,将读写请求指引到合适的分片上

  • 配置服务器config:持久化分片集群的元数据,包括:全局集群配置;每个数据库、集合和特定范围数据位置;一份变更记录,保存了数据在分片之间进行迁移的历史信息。配置服务器之间不是副本集形式存在,mongos向配置服务器提交信息时是两阶段提交,保证配置服务器之间的一致性。

(2)分片的核心操作

分片一个集合: 分片是根据一个属性的范围进行划分的,MongoDB使用所谓的分片键让每个文档在这些范围里找到自己的位置

块: 是位于一个分片中的一段连续的分片键范围,可以理解为若干个块组成分片,分片组成MongoDB的全部数据

(3)拆分与迁移

块的拆分: 初始化时只有一个块,达到最大块尺寸64MB或100000个文档就会触发块的拆分。 把原来的范围一分为二,这样就有了两个块,每个块都有相同数量的文档。

迁移: 当分片中的数据大小不一时会产生迁移的动作,比如分片A的数据比较多,会将分片A里面的一些块转移到分片B里面去。 分片集群通过在分片中移动块来实现均衡,是由名为均衡器的软件进程管理的,任务是确保数据在各个分片中保持均匀分布,当集群中拥有块最多的分片与拥有块最少分片的块差大于8时,均衡器就会发起一次均衡处理。

3.分片实战

启动两个副本集、三个配置服务器、一个mongos进程

配置分片

sh.help() //查看分片相关帮助
sh.addShard() //添加分片
db,getSiblingDB("config").shards.find() //查看分片列表
sh.status() //分片详情
sh.enableSharding("cloud-docs") //开启一个数据库上的分片
db.getSiblingDB("config").databases,find() //查看数据库列表
sh.shardCollection("cloud-docs.spreadsheets",{username:1,_id:1}) //使用一个分片键定义一个分片集合spreadsheets,根据用户名进行切分
sh.getSiiblingDB("config").collections.findOne() //查看集合列表
db.chunks.count() //查看块的个数
db.chunks.findOne() //查看块的信息
db.changelog.count(}what:"split"|) //查看块切分日志
db.changelog.find({what:"moveChunk.commit"}).count() //查看日志迁移记录

4.分片的查询与索引

(1)分片查询类型

  • 针对性查询:查询包含分片键

  • 全局查询或分散/聚集查:查询不包含分片键

  • 查询过程:通过分片键将查询路由给指定分片,一旦到了某个分片上,由分片自行决定使用哪个索引来执行该查询

(2)索引

每个分片都维护了自己的索引,当在分片集合上声明索引时,每个分片都会为它那部分集合构建独立的索引,每个分片上的分片集合都应该拥有相同的索引。

分片集合只允许在_id字段和分片键上添加唯一性索引,其他地方不行,因为这需要在分片间进行通信,实施起来很复杂。

当创建分片时,会根据分片键创建一个索引。

5.选择分片键

(1)分片键是不可修改的、分片键的选择非常重要

(2)低效的分片键

  • 分布性差:如使用BSON对象ID,那么会导致所有最新插入的文档都会落到某个很小的连续范围,无法分散插入

  • 缺乏局部性:升序分片键有明确的方向,完全随机的分片键则根本没有方向。前者无法分散插入,后者插入分散,如使用MD5作为分片键

(3)理想的分片键

  • 将插入数据均匀分布到各个分片上

  • 保证CRUD操作能够利用局部性 有足够的粒度进行块拆分

  • 满足这些要求的分片键通常由两个字段组成,第一个是粗粒度的,第二个粒度较细

6.生产环境中的分片

(1)部署拓扑

  • 复制mongod:需要独立的部署服务器

  • 配置服务器:配置服务器不需要有自己的机器

根据不同的数据中心划分

ZBzuIjN.jpg!web

(2)最低要求

  • 副本集每个成员,无论是完整的副本集节点还是仲裁节点,都需要放在不同的机器上 每个用于复制的副本集成员都需要有自己的机器

  • 副本集仲裁节点很轻量级,和其他进程共用一台机器即可

  • 配置服务器也可以选择与其他进程共用一台机器

Ib2QFnF.jpg!web

(3)配置的注意事项

需要估计集群大小,可使用以下命令对现有集合进行分片处理

sh.splitAt("cloud-docs.spreadsheets",{"username":"chen","_id":ObjectId("")})
//手动拆分块
sh.moveChunk("cloud-docs.spreadsheets",{username:"chen"},"shardB")
//手动将某分块移至分片B
db.runCommand({removeshard:"shard-1/arete:30100,arete:30101"})
//删除分片
db.runCommand({moveprimary:"test",to:"shard-0-test-rs"});
//移动主分片

(4)备份分片集群

备份分片时需要停止均衡器

db.settings.update({_id:"ba;ancer"},{$set:{stopped:true},true});
sh.setBalancerState(false);
//停止均衡器,此时均衡器将进行最后一轮均衡

db.locks.find({_id:"balancer"});
sh.isBalancerRunning();
//查看均衡器状态,任何状态大于0 的状态值都说明均衡器仍在进行中

八、部署与管理

1.部署

(1)部署架构

使用64位机器、32位机器会制约mongodb的内存,使其最大值为1.5GB

(2)cpu

mongodb 只有当索引和工作集都可放入内存时,才会遇到CPU瓶颈,CPU在mongodb使用中的作用是用来检索数据,如果看到CPU使用饱和的情况,可以通过查询慢查询日志,排查是不是查询的问题导致的,如果是可以通过添加索引来解决问题

mongodb写入数据时会使用到CPU,但是mongodb写入时间一次只用到一个核,如果有频繁的写入行为,可以通过分片来解决这个问题

(3)内存

大内存是mongodb的保障,如果工作集大小超过内存,将会导致性能下降,因为这将会增加数据加载入内存的动作

(4)硬盘

mongodb默认每60s会与磁盘强制同步一次,称为后台刷新,会产生I/O操作。 在重启时mongodb会将磁盘里面的数据加载至内存,高速磁盘将会减少同步的时间

(5)文件系统

使用ext4 和 xfs 文件系统

禁用最后访问时间

vim /etc/fstab

(6)文件描述符

linux 默认文件描述符是1024,需要大额度的提升这个额度

(7)时钟

mongodb各个节点服务器之间使用ntp服务器

2.安全

(1)绑定IP

启动时使用 - -bind_ip 命令

(2)身份验证

启动时使用 - -auth 命令

db.addUser("","",true)
//创建用户,最后一个参数指定是否只读

(3)副本集身份认证

使用keyFile,注意keyFile文件的权限必须是600,不然会启动不起来

3.数据的导入与导出

mongoimport
mongoexport

4.服务器配置

(1)拓扑结构

搭建副本集至少需要两个节点,其中仲裁结点不需要有自己的服务器

(2)Journaling日志

写数据时会先写入日志,而此时的数据也不是直接写入硬盘,而是写入内存

但是Journaling日志会消耗内存,所以可以在主库上面关闭,在从库上面启动

可以单独为Journaling日志使用一块固态硬盘

在插入时,可以通过驱动确保Journaling插入后再反馈,但是会非常影响性能。

5.日志

logpath 选项指定日志存储地址

-vvvvv 选项(v越多,输出越详细)

db.runCommand({logrotare:1}) 开启滚动日志

6.数据库监控命令

(1)serverStatus

UnMzqqV.jpg!web这里写图片描述
  • globalLock 表示服务器花在写锁上面的总时间

  • mem显示了如何使用内存

  • bits 表明这台机器的位长

  • resident 表示占用物理内存数量

  • virtual 表示使用的虚拟内存

(2)top

raYNnq7.jpg!web

(3)db.currentOp()

Qb2AVjM.jpg!web

7.mongostat

动态展示mongodb活动数据

8.web控制台

占用当前mongodb监听端口往上1000号的端口

9.备份与恢复

(1)mongodump

把数据库内容导出成BSON文件,而mongorestore能读取并还原这些文件

(2)mongorestore

把导出的BSON文件还原到数据库

(3)备份原始数据文件

可以这么做,但是,操作之前需要进行锁库处理  db.runCommand({fsync:1,lock:true})

db.$cmd.sys.unlock.findOne()  请求解锁操作,但是数据库不会立刻解锁,需要使用 db.currentOp() 验证。

10.压紧与修复

(1)修复

mongd --repair  修复所有数据库

db.runCommand({repairDatabase:1})  修复单个数据库

修复就是根据Jourling文件读取和重写所有数据文件并重建各个索引

(2)压紧

db.spreadsheets.reIndex() //重建索引
db.runCommand({compact:"spreadsheets"})

压紧,会重写数据文件,并重建集合的全部索引,需要停机或者在从库上面运行,如果需要在主库上面运行,需要添加force参数 保证加写锁。

11.性能调优

(1)监控磁盘状态

iostat

(2)为提升性能检查索引和查询

总的来说,扫描尽可能少的文档。

保证没有冗余的索引,冗余的索引会占用磁盘空间、消耗更多的内存,在每次写入时还需做更多工作

(3)添加内存

db.stats() //查看数据库数据占用大小状态

dataSize 数据大小 和 indexSize 索引大小,如果两者的和大于内存,那么将会影响性能。

storageSize超过dataSize 数据大小 两倍以上,就会因磁盘碎片而影响性能,需要压缩。

以上,便是今天的分享,大家觉得内容不错的,欢迎点击 在看 支持,谢谢

B3Q7faa.jpg!web

如果你想要跟大家分享你的文章

欢迎投稿

喜欢文章,点个 在看   ArIZ7na.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK