【mongDB】MongoDB高手课答疑

WiredTiger 是一个开源的、高性能、可伸缩的 MongoDB 数据存储引擎。

SSPL协议是只对使用云厂商提供的MongoDB存储服务有要求,但是对于我们自己在云厂商主机上部署自己的MongoDB数据库是没有任何限制的,是吧?

按SSPL协议,最多也只能到MongoDB4.0版本。

这可能也是阿里云、百度云等云厂商上提供的MongoDB数据库版本最多也是到MongoDB4.0的原因?


正解。这个只影响云厂商的MongoDB托管服务的部门。你自己在云上部署是不受SSPL限制的。

mongDB社区版使用的是 SSPL 协议, 和标准开源AGPL协议最大的差别就是 Mongo的不允许公有云厂商在云上卖MongoDB云服务。

阿里云已经获得商业授权所以他们接下来可以继续提供更新版本。其他云暂时就只能到4.0,正如你已经观察到的。


 mongodb适合做数据仓库吗?

如果是传统用来做星形schema或者雪花schema,不是太合适。

如果是用来做现代数仓,类似于大数据那样做大宽表,mongodb可以作为一个选择。

我在我自己的类似数仓的平台产品里就用了mongodb。 

有一些比较不错的亮点是:横向扩展能力,多结构化数据支持,检索能力,元数据管理等



最近在java项目中尝试将日志输出到mongodb,发现效果挺不错,解决了日志集中存储,分析排查问题方便了很多。

我想问的是 为什么现在微服务架构中流行用elk方案处理日志,mongodb不是更方便 更简单吗? 由于我没做过对比测试 不知mongodb存日志会不会有什么不足之处?

ELK 除了存储日志之外,有一些另外的插件比如说Logstash 可以用来用工具方式收集一些日志文件,比如说Kibana可以用来做一些日志分析和可视化的工作。另外ELK在日志全文搜索方面也略胜一筹。

你的场景是从Java 里写日志就没有太大区别了,mongo 和ES都可以很好的解决。当然,像我们公司一样因为已经用MongoDB 作为数据库,那我们就不需要额外再去用另一个分布式系统了。架构可以简单很多,这个可能是mongo能够作为一个通用数据库而不只是某些日志或搜索功能的优势了。



关于mongodb在loT领域的应用,比如怎样实现时序数据库的功能?

MongoDB不是一个专门的IoT,但是可能在70%-80%的IoT场景下它可以是个不错的选择。只有你在考虑有几十亿几百亿的量级,并且要做海量数据分析的时候,Mongo的行级存储特性会使得它不是最优的选择。这个时候要考虑专门的IoT数据库了。

Mongo的优势:

1)足够好的扩展能力来支撑大部分的IoT时序数据的存储,特别是使用了分桶设计以后(第2章我会讲) 

2)灵活的JSON模型,特别适合各种传感器的不规则数据结构。

国内的某一大厂物联网方案就是基于mongo的。西门子的工业物联网Mindsphere也是用mongo。非常多的使用者。


http://mongoing.com上的MongoDB中文文档是3.4的,现在MongoDB的版本已经到4.2了,3.4的文档跟4.2文档的差别大吗?mongoing.com后面会翻译4.0版本的文档吗?现在看3.4的文档翻译是 2017年的了。

mongodb的官方文档工具升级后就不支持非英语语言的合并,造成翻译的文档难以更新。

这个问题我们已经反应给官方,我们还在看有无机会等他们更新工具后重新启动新版翻译。



看到很多书或者其他资料中说MongoDB是BSON数据模型,能解释一下BSON吗?

BSON 是MongoDB用来在落盘存储时候或者网络传输时候的底层物理数据模型。

如果你是存储引擎开发者或者mongodb驱动程序开发者,你需要从这个层面去了解。如果你是绝大部分的应用开发者或者数据库使用者,你只需要关心JSON。

BSON = Binary JSON, 是基于JSON基础上加了一些类型及元数据描述的格式。


MongoDB 的特性是无Schema 设计,但在使用过程中通过 Java (Spring Boot)操作时需要先定义对象结构,加上相应的注解,与 MongoDB 的 Feild 对应,这样其实 没有办法利用 MongoDB 的这一特性了,有什么办法吗?

MongoDB是动态Schema,不是无schema。

你定了一个schema以后,以后新增字段(在springboot)的时候,直接改就可以了,不需要去数据库调整。这就是它的优越性。


mongoDB这门课需要什么样的基础?需要懂开发语言么?

懂一些Javascript的话会比较有帮助一些。如果是只做管理的DBA,你可能也需要一些Javascript来维护下数据。

当然,我不觉得用JS来做些脚本就一定要是像开发者那样熟练,所以说不是100%需要懂开发语言。


您在课程中提到“介绍 MongoDB 的基本操作”这个任务,是留给“参考书”去做的。那么您能否推荐一些,这种用来给初学者入门的“参考书”,或者是网络上的学习资源呢?

MongoDB: The Definitive Guide

有中文译本:MongoDB权威指南



Mongodb 操作系统优化这块推荐的参数?

可以参考一下这里:

https://docs.mongodb.com/manual/administration/production-notes



MongoDB是一个基于json的数据库,文档模型灵活,很好横向扩展能力

2.x版本加入聚合的操作

3.x版本引入wiredtiger引擎

4.x版本引入事务acid的支持


为什么副本集说是5个9(99.999%)的高可用?

MongoDB复制集在从节点故障时候是不会影响到可用性。

在主节点故障,进行选举的时候需要数秒到十几秒,这期间会影响写入。

一年有365天x86640秒 ~= 3000多万秒。假设你每个月发生一次主节点故障或者其他问题导致选举,每次影响15秒,那么可用率就是:就是(3000w-12x15) / 3000w ~= 99.9994%


MongoDB这种复制集模式,在不同的数据中心,这中间的网络延迟比较严重吧,不会影响做复制集的效果吗?

数据规模达到多大级别需要使用分片机制?,我们现在数据有200多G,是不是复制集已经足以应对了?

在多中心部署的时候要考虑网络延迟,所以一般多活中心只是建议能够接受一定数据延迟的情况下才建议。

分片有3个触发条件:数据量,并发量,以及热数据大小(内存需求)。理论上,任意一个都会触发分片需求。如果只看数据量,单分片一般可以到1-2TB。



mongoDB和MySQL比写入性能方面优势大吗?

按照我个人经验是有明显的优势的。有好几家大厂的兄弟,包括百度,网易,字节都有分享类似的经验。 

稍微网络搜一下,都有十倍或者更多的数字。原因:

1)MongoDB默认的事务级别比MySQL低

2)MongoDB支持的batch 写入模式可以大幅度提升写入速度

3)MongoDB默认写到内存就返回,不等落盘


mongoDB是不是完爆MySQL呢?什么情况下该选用mysql而不是MongoDB呢?

实际情况是,很多同学在学校里学习的只是SQL。

很多开发团队,特别是有项目压力的,没有时间让团队来学习,就会选择大家比较熟悉的方式。

如果有额外的时间的话,我的几个创业公司的朋友都说,想从MySQL 切换到MongoDB。


为什么MySQL不用一张表多个字段呢,而是拆分成几个表?

MySQL一张表没法做到一对多的关系,只能拆分表来做。

当然,MySQL现在也支持json了,但是那个是非主流用法。对JSON的支持也是相对较弱,所以使用人并不多。


MongoDB 支持multi-master,所有节点可以同时读写数据库吗?

 在一个复制集群里没有multi-master,但是一个分片集群可以有多个master (primary), 每个分片一个primary这种方式。


mongoDB性能优势大不大呢?

如果不说单节点性能比较,MongoDB最少是分布式架构,可以通过横向扩容来克服性能瓶颈。

这个和同样是用来作为应用程序数据库的RDBMS来比还是有很明显的优势的。



Grafana不支持mongodb作为数据源,也没有相关插件,有什么方案,使用grafana显示mongodb的一些数据吗?

https://grafana.com/grafana/dashboards/8339


mongoDB有什么推荐的客户端软件吗?

MongoDB Compass(官方)

Studio3T

NoSQL Booster

navicat


mogodb安装在linuc或windows上,运行差别很大吗?官方推荐是部署在什么系统上(难道大部分生产环境是部署在centos上)?


MongoDB生产环境绝大部分是Linux 系统。RedHat, CentOS, Ubuntu 等都有。

Windows 开发环境多一点,也有少数线上使用。但是确实不是主流。

差别:Linux版本上面用的最多,踩得坑也最多,相对更加稳定。


mongodb在生产环境建议使用docker部署吗?用docker部署副本集如何处理?

docker 在生产环境中不建议。

在开发测试环境中okay,需要注意的一点是要用服务名或者配置的域名进行复制集的配置,否则可能会因为docker 内部ip无法互相通信而启动不了集群。


如果在docker容器中布署mongodb,一般容器内存与heap内存的比例大概是个什么比例?

 MongoDB 默认会使用60%的系统内存,一般至少也要用到1GB缓存,所以容器至少要给个2GB。


如果想对mongodb脱敏,非结构型的数据结构有什么好的解决方案推荐吗?

可以采用一些ETL工具,如Kettle, Talend, Tapdata等。这些工具都对mongodb有一定程度的支持。


numa架构下现在安装mongodb还需要配置interleave=all,进行交叉内存分配么?

这个还是建议的。


看3.6的官方文档,删除是用deleteOne, deleteMany,这跟remove有什么区分吗?

remove是mongo shell下的命令。deleteOne deleteMany是程序语言下的API。做的是类似的事情。


文件分布式的文件存储也会选用MongoDB么?除了MongoDB还有其他的解决方案吗?

可以尝试 minio


请问分片集群的chunk分裂阈值有哪些?

shard key与chunk的分裂阈值是什么关系?

如何避免按shard key做chunk分裂时出现超出chunkSize的chunk块?

这个阈值应该是在80%(64MB * 80%)的时候,就会把块一分为二。


mongodb删除了数据、表、数据库是没法恢复的么,有没有类似mysql有个日志记录的机制去回滚的?

 mongodb有类似的oplog。但是那个要求你对全量的oplog都要保存,才能够从oplog里完全恢复被误删的表。




在外分布式环境中,mongo如何做开机自启?

将服务注册成系统服务:

CentOS6.x  写启动脚本

CentOS7.x  写service文件

如果你是说希望有那种中央化的管控,那你可以使用OpsManager,可以通过GUI对全部节点进行起停控制,并且是会在服务器宕机时候自动重启服务。


使用mongodump的时候会给collection加lock吗?

不会加lock。所以mongodump出来的不是一个一致的backup。通常可以加上 --oplog参数来获取一个某个时间点的快照类的备份。


对于mongo副本集,如果有多个库,由于单集群达到瓶颈了,我想把一个库迁移出去,有什么方法吗,能达到像mysql主从实现吗?并且切换到新集群控制在切换ip的时间吗?

如果可以停服务,可以用 mongodump -d xxx 方式如果不能停服,需要用一些工具:如果在阿里云,可以考虑mongoshake 工具MongoDB官方有mongomirror工具,我们Tapdata也有一个工具,有免费3个月的使用期,如果只是一次性迁移够用了。


我们系统一开始使用es, 但是我们的一个index包含2000多个field,经常会出现写性能问题,请问mongoDB对于写入的文档的字段,以及字段嵌套的深度由限制吗?

那个没有限制。限制就是最大不能超过16MB。ES的长处是查询/搜索,写入从来不是它优势。

MongoDB比较平衡点,增删改查都还不错。


使用mongodump去备份db,备份过程中会阻塞insert写入吗?

是不是如果不想要一致性备份集,就不上锁,如果想要一致性的备份集,加--oplog参数,也不阻塞insert写入?

备份不阻塞,除非你用fsyncLock()。

不上锁的话,就用 --oplog


mongodb的动态特性有缺点嘛?


有一些值得注意的地方。

schema 管理会复杂, 你不能一下确定这个集合到底是什么结构。

解决方案是使用Schema Validation 或者 JSON Schema来定义这个集合的严格结构。 

JSON Schema类似于关系数据库的schema,但是不同的是如果你需要修改这个schema的话可以随时更改,理论上也不需要对已有数据做更新或者迁移。



我以前用的MySQL,如果一个服务器上有多个数据库,想迁移数据库的时候直接考走对应的数据库文件就好。如果是mongodb,发现没有对应的文件,请问除了把数据导出还有别的办法吗?

 mongodb 不能这么玩,只能用mongodump 或者 mongoexport,或者用迁移工具。



比如在MySQL批量插入,一次3000条左右比较合适,性能也不错,如果是mongodb,一次插多少条比较高效?

这个没有绝对值,通常和文档大小有关。如果在1KB以内的话,我会推荐用1000左右的batch size


想删除多行数据,得对多行数据进行备份,有什么工具可以生成反向语句insert进行备份吗?

换一个思路。

使用MongoDB Ops Manager可以实现任意时间点恢复 - 比如你3:00执行删除动作,4:00发现有问题想回滚,那么可以使用ops manager 把数据库回到3:00的时候。

类似的事情可以用命令行方式做,但是就不是小项目了。反向生成insert的没有见过,但是自己实现应该很简单。


mongodb $in子句有长度限制吗?另外mongodb的 findMany返回的游标,会不会有内存溢出的问题呢?

理论上没有,只有bson 大小限制(16MB)。但实际上我用到1000的时候查询就很慢了。


MongoDB官方好像是建议1主1从1arbiter。如果是1主2从,主节点挂掉后,两个从节点都投票给自己,这样僵持,不是会没法产生新的master吗?


“MongoDB官方好像是建议1主1从1arbiter” 请提供相应的文章。

主节点挂了以后,两个从节点的投票算法会防止你说的现象发生。

具体来说,如果两个从节点条件完全一样,那么第一个主张的节点就获胜。如果两个从节点同时主张自己,那么两个人同时放弃,并用一个随机值等待一小段时间(数秒),然后重试。所以总有一个节点会在另一个之前选为主节点。



通常怎样提高写性能?

 升级存储是最直接的方案,如PCIE + SSD

- 注意索引的数量:索引越多写入越慢

- 分片: 增加写的节点来提供并发


如果是奇数节点,那么主节点挂掉,不就变成偶数节点了?

总数是看最初的配置,如你部署并配置了3个,虽然坏了一个,但是你的拓扑还是3节点, 按3节点的规则,剩下2个存活就可以正常工作。



1.建立3个独立的单机库,然后导入同一份数据,然后将3个节点设置为复制集模式,那么被设置为从节点的数据库里面的数据会被清空,然后再从主节点再同步回来吗?

2.如果3个节点通过公网ip地址互连,那么这中间的数据通信需要做安全防护吗?也就是这个时候节点间的通信数据被窃取,是否有泄露数据的风险?


1)是的会重新同步。节点之间判断是否需要同步是根据local库里的元数据决定的。里面记录了节点同步的状态信息,并不是看你实际存储的数据。

2)建议用SSL/TLS 加密链路就可以有效防止数据被窃取。

https://docs.mongodb.com/manual/tutorial/configure-ssl/index.html



太多的slave 数据节点,都从主节点拉oplog 是否反而增加了主节点的压力?反而让主节点性能变差了?

写主 读取从的这种配置是否还被推荐?什么场景适合这种?

太多从节点会增加主节点的压力,大概是每增加一个节点会有10%左右的性能影响。

主从读写分离还是比较常见的。所有读操作对数据时效(如报表型,或者历史数据)不高的都可以用从节点。



增加副本集节点,只能提高并发访问能力,单个查询并不会变快。

那么有办法通过水平扩展的方式提高单个查询的性能吗?

 通过水平扩展可以提高整体的吞吐量,但是单个(比如说,查询 id=1234 这条记录)查询是不会得到改善的。因为这个查询就是会在一个节点上发生。

提高单个查询性能就是把数据放在内存里,加上合适的索引可以来提升性能(降低读取延迟)


选举是发生在主节点故障时,那么它也会参与投票么?

主节点故障如果是进程crash或者server crash,那么它当然无法进行选举。

如果故障是因为节点之间网络不通,那失联的主节点会自动降级为从节点。

如果是短暂故障马上回复后,主节点(这个时候已经是从节点了)会重新加入选举,但是有个30秒的等待期。



复制集主从读写分离看起来很美好,但是如果对主从同步延时要求高,使用就很受限。

比如某些业务会写操作多,实时要求高的读场景多,这样主节点压力就很大,而从节点可以分担的业务场景非常有限。

老师如何看待复制集架构在这种业务场景中的应用和优化呢?

对。

读写分离的读一般指的是对时效性要求不高的读场景。

如果要求高一般都建议读主节点。如果主节点性能扛不住,这个时候就要采用分片集群来分担压力(读和写)。



我们想使用此方式来提高mongodb的查询性能, 复制集采用一主两从,主节点使用memeory,从节点wiredtiger。 这样是否能够提供查询效率?

这样做是OKAY的,当然要注意InMemory Engine是商业版产品需要付费。

之前有人用RAMDISK方式来模拟InMemory,但是由于代码还是WT,所以和真正的InMemory Engine还是有些差别。


复制集,有没有集群,就是分布式存储?

 复制集也是集群,3个节点以上的高可用集群。

数据不做分布式存储,只是主从热备。


复制集能基于数据库粒度吗? 

复制集只能同步所有数据库吗,能只同步选择的数据库吗?

公司项目数据库服务实例有多个数据库,但是只想迁移部分数据库. dump oplog选项也不支持数据库粒度, 但是阿里云DTS和tapData又能基于oplog做数据库粒度的毫秒级同步增量迁移,怎么做到的呢?


这个功能提了几年了,但是还没支持。

复制集的设计原理是基于3个节点是完全等同的基础上(因为会主从切换)。

当然,对于某些指定的非主节点(第4个以上,priority为0), 技术上实现库级/选择性同步是可以的的,只不过这个优先级不高,没有在mongo产品路线图里实现而已。



1主2从的复制集节点,当主挂掉了,怎么从2个从节点中选择新的主节点呢?

主挂掉了,但是节点的架构没有变,还是3个节点(2个好的,1个坏的)。符合大多数原则,可以选举主节点。


1.主从这种配置实现了高可用和高并发,一主二从的配置其实就是一份数据最终落到了三台机器,如果数据太多,导致磁盘不够用,增加从节点是没有用的对吧?是不是只能增加磁盘容量才可以?

2.对于mongo,究竟多大的数据量和并发量适合使用mongo,这个有什么评估标准吗?

1. 你的理解是正确的。需要分片或者增加容量。

2. 如果不是为别的考量,只是数据量,通常我见的比较多的是亿级以上的数据量,可以考虑mongodb。


主从复制是否会产生延迟,如果有延迟,那么常见有哪些因素会导致延迟,该如何避免或者降低延迟?

主从复制会有延迟。常见因素:

1) 网络抖动 (没办法)

2)网络拥挤 (评估数据增量需求,给予足够的带宽)

3)节点之间延迟太长

4)主节点压力过大 (注意监控,压力过大要扩容)

5)从节点配置不均衡,低于主节点配置(尽量均衡)


副本集提高读性能,是指提高并发访问的性能,还是指单个查询会变快?或者二者兼有之?

通过增加节点,并且每个节点同时提供服务来提高并发访问能力。

单个查询的性能不受影响(不会变快)。


mongodb 的复制线程是主节点上的线程还是从节点上的线程?

复制是主节点通知从节点还是从节点定时拉取呢?

主从复制是由从节点的线程发起的。通过监听主节点的oplog表的变化,并把oplog的entries pull到从节点进行回放。

oplog变化通知的方式类似于你在linux 下执行一个tail -f 命令,一旦你tail的文件(oplog)有变化,马上就会打印出来。或者在java里是类似于observable pattern。


1 投票节点疑问:

投票节点为什么不建议用?我看有的书上,如果是偶数的时候,又增加一个投票节点,这样就变成奇数了,比如3个数据节点,2个投票节点。mongo为什么要设计投票节点?

2 集群部署问题:

1 从节点之间出现心跳不通,但是都和主节点是通的,这个会出现问题么?是不是网络结构部署有问题?

1)投票节点的最早设计初衷:需要奇数节点满足一致性协议,但同时又想节省资源。为何不建议用?降低的可用性(丢一个数据节点后风险很高),无法使用更高的writeConcern(后续章节会讲)来保证在主从切换的时候保证不丢失数据

2) 这种现象出现的可能性不大,你可以尝试下画下网络拓扑,具体到物理层链路。如果真的出现了,应该是可以继续工作的。



选举这块,如果有三个节点,leader节点挂了,剩余的两个节点能对外提供服务吗?能完成选举不?

可以 - 剩下两个满足大多数(2)就可以正常完成选举并工作。



Mongodb2.4主从架构,从库复制从主库复制数据时会清空本地所有数据,然后再同步?

如果是因为同步滞后,超过oplog window大小,或者是数据库损坏,或者是刚加入主库,都需要执行initial syn的操作,这个就会清空本地库再同步。


请问下有关选举过程:对于保证大多数选举节点存活这一个条件。

举例有7个选举节点,是不是意味着必须有4个节点以上存活才可以进行选举?如果有4个节点存活,但是存活节点是偶数个,是否可以完成RAFT算法完成选举。还是说选举节点必须是奇数个?

选举节点必须是奇数,过半数(4)才可以工作和选举



第一个问题:关于复制集这块的secondary是怎么从主库来来取oplog的,实现的细节是什么?想了解这块的出发点就是作为dba的话,会经常遇到一些生产问题,需要从原理上解决问题?

第二个问题:在local下,有几个关于副本集的集合,这几个集合是干什么用的,排查问题的时候,这几个表有什么作用?

第三个问题: 我有一个副本集,现在对一个secondary进行了物理的热备,之后,想把这个节点加入现有集群,是只需要配置参数文件,add加入副本集就可以吗?如果可以加入副本集的话,他是通过哪个集合来判断从哪个时间点开始来取oplog的?

第一个问题你可以先看下这篇博客:

https://www.cnblogs.com/Joans/p/7723554.html

如果进一步了解的话,源码也可以尝试阅读下

第二个问题也在上面的文章里有提及

第三个问题:可以的,但是要通过对local库下面的一些表做个手脚。如果你用MongoDB的Ops Manager的话,它就提供这种方法来快速恢复一个从节点。

https://docs.opsmanager.mongodb.com/v1.4/tutorial/use-restore-to-seed-secondary/

其中关键的集合是system.replset 以及oplog.rs。 system.replset必须包含对应的配置(和其他节点一致)和时间戳。oplog.rs必须包含至少一条和主节点oplog一样的记录用来匹配同步点。


请问下配置复制集的时候用IP+端口的方式可以吗?

可以的 - 如果能用hostname最好


我们的生产环境只有一台服务器,但有2个硬盘。做一主一从副本集,有意义吗?

意义不是很大,你crash了一个进程,另一个进程也是没法正常服务(需要3个节点才可以有HA)。硬盘的容错直接用RAID就可以。


请教一下采用多副本集后,主节点写,其他复制集读,但有时候主会切换成其他副节点,导致访问mongodb的端口变化,调用程序无法连接上之前主节点进行写入操作,前端调用程序该如何处理?

“但有时候主会切换成其他副节点” 你是在同一台服务器上起了几个不同端口的实例?这样的复制集/副本集是没有意义的。

这种场景是常见的,在mongo世界里。你的连接串要同时包含3个节点的IP:PORT,这样在切主的时候mongo的驱动会自动连到下一个主节点,你的应用程序无需处理。


我有两个问题:

1从节点是主动监听主节点的op log并拉取吗? 

mongo 选举的时候,怎么知道集群中一共有多少节点?还有就是自己是和大多数节点互通的?

1: 是的。

2: 配置。开始搭建集群时候就要配置一下(或者通过add方法增加节点)


在做复制架构是在现有的环境做,这样是会自动将现有的节点设置为主吗?

还是要将现有节点数据同步到新节点上。还是要在初始化的时候指定优先级?

顺序是:

1) 关掉mongo 服务

2)以复制集模式重新启动mongo(加replSet 参数)

3) 初始化复制集

4)增加第二(三)个节点(新的节点)

5) 等待initialSync 完成

这个时候你的原来的节点会是主节点。


我有多个复制集,当我想提升读能力的时候。

是不是在读的时候,要动态切换这些复制集的地址?

如果可以接受从节点读,那么可以使用 readPreference: secondary/nearest (后续有讲如何使用)。这种方式可以使用更多的节点来支持读操作。


复制集和分片机制有什么区别?

我们可以对数据分片到不同机器上的同时保留复制集吗?部署配置方式有区别吗?

复制集提供高可用,分片集在此基础上横向扩充,增加系统对数据量/并发量的支持。分片集由2个或多个复制集组成。



我在搭建集群的过程中遇到一个问题。 

如果我集群中的所有节点都设置了密码,在使用rs.add("host:port")时会报没有权限。此时我该如何解决呢?

可能的问题:

1. 没有为各个节点配置KeyFile,或者

2. 启用认证之后没有创建管理员账户。rs.add()需要权限才能执行。

3.不能用local 库。那个是系统保留的。用任意其他库都可以。如 use test


试过用mysql 做读写分离,开了binlog做主从同步。遇到一种情况,主库写太频繁(load file操作,没有事务),从库同步延迟越来越大。

oplog的原理是否也是记录成文件之后传输到从节点,由专门线程回放,mongodb是否也会出现这种问题?

oplog 和 binlog类似。并且在压力超大的时候,也有可能在从节点造成一些延迟。当然mongodb可以用多线程同时来回放。


讲到MongoDB Ops Manager 集群管理平台时,说到该软件支持 分片集群的备份。

请问分片集群的备份是什么意思?mongodump 做不了吗?

mongodump 能做全量备份,但是做不到一致性备份。比如说,你想要一个半夜12点的备份,希望这个备份能够还原那个时间点的分片数据库的准确状态。事实上,当你12点开始跑的时候,可能要跑几十分钟到数小时才能备份完。这个时候又有持续的写入(可能会在备份里,可能不会在,取决于mongodump的读取顺序),所以你这个备份是属于不一致状态。

Ops Manager有自己独特的机制来保证一个备份的多个分片之间数据是在一个时间点上一致的。


1 MongoDB锁能否支持行级锁?

2. 64G内存的虚拟机 能否设置大于50%的wiredTiger cacheSizeGB?

 1)MongoDB采用的是MVCC机制,实际效果和行级锁类似。

2)可以的,但是要考虑到mongodb除了缓存以外自身还需要额外内存,所以要适当给操作系统和mongo本身留一些。



从课程目录里没有看到有介绍MongoDB的数据库引擎的内容。在这个课程里是不会涉及这部分内容吗?

因为目前我们公司使用的单节点MongoDB数据库,每隔一段时间就会被服务器的OOM杀掉,在网上搜索了下相关资料,设置了WiredTiger引擎可用的缓存大小,但并没有起作用,从系统日志里还是能看到MongoDB在占用了5G左右的内存后被OOM杀掉。

MongoDB不仅仅是WiredTiger 缓存占据内存,除了缓存外,还有连接管理,聚合计算,排序等都会用到。

另外你可以注意下swap有无配置。配置swap可能可以缓解OOM的问题。



第三范式的理由是什么呢?是因为节省数据库空间吗?

因为我感觉只有一个group的表然后有name, description和一组contact_id的数组也可以把?中间抽离一个contactGroup的意义何在呢?

第三范式是关系设计的实践。

节省空间是一个很大的驱动 - 关系型理论出来的时候,1GB硬盘需要10万美元的价格。

数据一致性也是第三范式的一个目标。

你说的那种方式就是MongoDB的设计模式了。内嵌数组。



mongodb除了collection之外还有一个功能可以存附件,比如文件,视频,音频等。这个是和普通关系型数据库有区别的地方吧,还有就是以前面试的时候,面试官也拿mongodb和fastdfs提问,两者有什么区别,老师你可以用之前的项目经验解答下么?

MongoDB的GridFS 不是一个真正的filesystem。

它其实是一个api sugarcoating。实现是在驱动端(不是mongodb服务器),提供一个字节流的API, 允许你把二进制文件通过这个接口提交给MongoDB 驱动,或者从这个接口读取二进制文件流。然后驱动会把这个文件分块,每一块作为一个mongodb的文档插入到集合里。 当你需要的时候,mongodb驱动会把所有相关的切块读出来,拼成一整个文件,返回给应用程序。

所以这个不是真的文件系统,只是提供了一个虚拟的文件接口供应用进行文件存储和读取。优点是可以用到mongo的分布式能力,做海量的二进制文件管理和高可用等。


在学习过程中遇到一个概念Tailable Cursor,这个应该怎么理解呢?

Linux 有个命令叫tail,如果你理解那个的用法,就知道这个名词的由来了。

tail -f debug.log

这个命令会打印debug.log 的内容,然后不会退出,会在那里监听debug.log文件是否有新的日志写入,一旦有新的,就会马上在控制台打印出来。

使用tailable cursor, 你的程序不会退出,读完cursor最后一条以后会block,等待下一条数据过来后继续。很多时候可以用来做一些类似Java里面 observer pattern的事情或者传统数据库里触发器的事情。


使用的mongo是4.0.11版本的,架构是分片集群,现在问题是,默认的最大连接数不够用的,819,怎么调优最大连接数?

有可能是和ulimits相关。你看下这个

https://docs.mongodb.com/manual/reference/ulimit/


日志、journal、oplog 这三个有什么联系与区别呢?

日志: 这个是一个比较通用的概念,可以包括你说的所有(journal,oplog,以及server日志)。

具体一点来说, journal日志是数据库的crash recovery手段。通常的做法是把数据库内的数据块修改,提前用文件顺序写方式刷到盘上,然后再去真正的提交数据的修改。这样的目的是在服务器宕机的时候,内存中被丢失的数据可以在恢复过程中从journal 日志文件中读回来。

Oplog也是记录的数据库的操作日志,但是记的是逻辑操作命令。主要的目的是用于节点之间复制数据,而不是上面journal主要是用来recover crash。

还有一种就是mongod.log,这个就是一个文本文件,记录数据库系统的正常运行和错误信息等等。



Mongo 落盘的时候,有用到文件系统的 Page Cache 机制吗?

当有一条数据更新的时候是先写到内存,然后是Page Cache 最后是 硬盘吗?

j 这个参数是代表写到 Page Cache 还是硬盘呢?

j:1 表示Journal 日志刷盘,所以就是要写文件到硬盘。

正常数据只是写到内存的Cache(不是操作系统的cache,而是WiredTiger自己管理的Cache),然后异步刷盘。



mongodb事务的默认隔离级别是什么?

默认是read uncommitted。

正常情况都不会有问题,除了发生宕机的时候,这个可能会有问题 - 你读到的一条数据可能会在宕机的时候被回滚掉。这种事情概率很小,发生了可能问题也不算特别严重,很多场景可以接受。如果要求比较高,那么需要用 readConcern: majority 来提高隔离级别。

按照mongodb复制集选举规则,有最新数据的会第一优先被选为主节点


mongo是否可以在服务器端配置 majority write concern ,跟 j : true ?

服务器端无法配置。

你可以在Connection String上设置,这个一般是全局统一的设置。

例子:mongodb://db0.example.com,db1.example.com,db2.example.com/?replicaSet=myRepl&w=majority&wtimeoutMS=5000

详细文档:

https://docs.mongodb.com/manual/reference/connection-string/


oplog是在内存中还是在磁盘上呢? 

每一次写操作都会事务的记录oplog?

oplog和就是一个MongoDB的collection ,都是存储在磁盘上的。 对oplog的操作只是顺序追加写入,所以效率相对来说会高不少,相比于普通collection 的随机读写。

每一次增删改都会记录相应的oplog,并且对oplog的操作和数据表的写入是同一个原子事务的。


为什么说写入多数集群才算安全呢?

写入多数节点后,即时一个节点数据失效/不可用,你的数据还在另外一个节点上。是从这个角度。


请问怎样限制 MongoDB 使用的总内存大小?

32GB只是控制数据的缓存空间大小。MongoDB服务器本身还需要内存来进行工作,如管理TCP连接,聚合、排序运算等。


chunk过程中各个分片上的oplog是会变化的吗?这时候oplog跟分片上的数据能对应起来吗?

会产生日志。日志里有个特殊字段会标记出来是来自于chunk migration



change stream是如何触发微服务的?比如库存低于一定阈值后,触发Java服务发送邮件

可以看这个例子:

https://github.com/spring-projects/spring-data-examples/tree/master/mongodb/change-streams


MongoDB适合存储车辆GPS信息吗?比如十万辆车,每辆车每十秒上传一次GPS信息(时间,坐标,方向,位置,速度等),MongoDB可以支持这种量级的数据吗?还要考虑车辆位置实时监控,历史时间段轨迹查询等应用。

这个有非常多的案例。比较著名的是有最大的一个共享单车,国内最大的汽车制造厂之一,以及最著名的电动车厂都是用mongo来记录车辆GPS位置。放心去用吧。



请问MongoDB复制集的连接数 和机器的配置应该怎么换算?怎么样达到合理的连接数?

可以参考下这个文档:

https://docs.atlas.mongodb.com/connection-limits/index.html

mongodb atlas云服务里面的规格和AWS机器规格对应:

M30 m4.large

M40 m4.xlarge

M50 m4.2xlarge

M60 m4.4xlarge


请问MongoDB的用户是在库上来配置的吗,还是只是在admin库里配置的?

 理论上都可以 - 用户可以在admin库里,也可以在用户库里。我们一般建议建在admin库里方便统一管理



在MongoDB中怎么设置本地时间,在查询时间,显示的时间比本地时间慢8个小时?

 目前只支持格林威治时间。。。没法设置。


MongoDB集群分片数据分配不均衡,怎么办 ?

少数不均衡不是问题(比如说5-10% 的差别)。多了不均衡,要看看是不是有下面问题?

1) Jumbo chunk

2) balancer 是不是停了? sh.getBalancerState()

3) 写入太频繁,超过IO能力


数据量不是很大,如果要支撑百万并发,一般要如何设计,大概要多少个节点,用复制集还是分片集?

官方的建议不管读还是写,都用分片来解决。百万级的并发算是很大了,如果是以查为主的读操作占绝大多数,那么一个节点理论上支撑10万以上并发是可以的,当然必须是那种32/64 核高CPU的物理服务器。 Oppo的同学分享过单集群支撑100万+并发,该集群由14个分片组成,14x3共42台机器



看视频得知configsrv节点很重要,它保存了分片集群的元数据。

如果这个节点的数据因为一些原因损坏、丢失了,那集群里的各个分片还能重新组成一个新的分片集群吗?

各个分片的数据理论上是互不重叠的,所以如果配置服务器坏的话,你将无法组成一个新的分片集群,但是你的数据可以合并起来组成非分片的集群。

当然,考虑到分片集群某一时间点会有正在分片之间迁移的数据,这个数据合并还是有点风险。

所以你的配置服务器,也是需要3个节点来保证数据的可靠性。


mongodb还需要考虑分库分表吗,如果要考虑一般是在什么数量级别才分呢?

一般原则是不需要。

如果你的应用场景用不到数据合并(连统一报表都不需要),并且数据量级在10亿级以上,可以考虑作为一个特殊优化手段做分表。



数据大小与机器配置有没有经验换算方式,比如1TB数据,1主2从复制集,单台服务器需要多大的配置,CPU、内存,还是需要模拟压测?


官方没有标准算法 - 根据workload的不同,硬件配置可以差别很大。

你可以参考MongoDB Atlas上面有个机器大小可以支持的Connections,所以从应用要支持的连接数,可以做一个反推。但是并不考虑你的数据量,所以只是个概括估计。

https://docs.atlas.mongodb.com/connection-limits/index.html



mongo分片集群如何实现读写分离?需要配置哪些?可以提供一些资料查看吗?

分片的读写分离和复制集的是一样机制。可以查阅一下MongoDB read preference。参数可以直接给到mongos连接串。

视频课程相关内容在这里

https://time.geekbang.org/course/detail/100040001-176897


我们生产使用的是分片模式,但是有一个集合没有建片键,这个集合现在太大了占了7.4TB

1:现在怎么建片键,可以建吗?

2:建了片键之后会不会影响之前的数据查询

1)可以,直接用shardCollection就可以

2)不会。

数据均衡可能会花很长时间(数天),这是正常的。


没有分片的集合是会随机找个shard 复制集存吗?

mongos在你新建库的时候会为你的库挑一个“primary shard”,所有未分片的集合都会在这个shard里面。挑选的规则就是看哪个分片相对数据量小一点。



mongos configsvr 是否需要高内存 多核心的服务器,这2个服务能部署在同一个服务器上面么?

config server通常有1~2c就可以,内存也不用大,通常4G就可以。

mongos 因为要承接很多连接处理,一般建议CPU还是有给够,可以和mongod参考。因为它不缓存数据,所以内存也可以不用太大。可以参考mongod的一半。



有一套环境config改完端口shard不能启动了,还去连修改之前的端口。

为什么shard启动的时候会去连config?shard从哪里读取config的信息?如何修改?

config上面存着分片的重要元数据(如chunk分布),没有config server 分片集群无法工作的。shard server会建立到configserver的连接(正常端口)来获取并缓存配置数据。

改完端口以后,config 复制集是否正常?你有重新启动mongos 和 shard mongod 实例吗?

所有操作必须要使用mongos。不能直接使用分片主节点。直接操作主节点仅仅限于数据库故障恢复


有的库我不分片,目前我有2个分片集(A和B),然后我创建一个新数据库,怎么指定其在分片集B上面?

db.adminCommand( { movePrimary : "your_dbname", to : "shard0001" } )

https://docs.mongodb.com/manual/reference/command/movePrimary/



 集群如何启用验证?

:集群如果启用验证的话,需要用一个shared key文件,或者使用 X509 公钥机制来进行集群间的互相认证。

可以先看下这个英文文档,有问题再提。

https://docs.mongodb.com/manual/core/security-internal-authentication


1、如果两个分片服务器性能不一样,访问和存储可以权重类的设置吗?

2、加入新的分片后,集群里的分片数据会自动均衡到各分片吗?比如首先只有第一个分片有30G数据,后面新增两个分片,各分片会迁移10G数据吗?

1)可以使用zone sharding方式来自己控制数据的分布。比如说分片1是16Core SSD,那你可以给它更多的数据。

2)是的,最后3个分片会各有10G左右



MongoDB备份只备份某一时刻的数据。

如果发生宕机时用备份进行数据恢复也只能回复到备份的那一时刻。那岂不是备完成到宕机这段时间的数据不就丢失了吗?

这个就是RPO指标决定的。Recovery Point Objective. 如果是定期备份,你的RPO就是你的备份间隔时间,比如说24小时。这样的话你由可能丢失24小时的数据。

如果你希望RPO最小化,就要启用实时备份oplog的方式。MongoDB官方提供OpsManager可以实现,数据可以恢复到故障之前一分钟。

然后,一般需要恢复的场景不是宕机。宕机这种比较常见的场景在MongoDB里面是通过复制集来解决的。一个节点宕机不影响业务,重启就好了。

备份恢复通常是出现一些数据问题,比如说,有人删库跑路。


mongo的全量备份的时候,如果有插入或删除数据呢,比如我在t0开始全量备份,t1时插入了一条数据,t2时备份到刚插入的数据,t3时完成备份,事后我用全量的备份数据加上期间的oplog的话,不就多插入一条数据了吗?

oplog是有幂等性的。回放的时候,t1 的数据+oplog的一条,合在一起,还是一条。


请问mysql中的数据怎么迁移到mongodb呢?

对于少量数据(100M内) 和 大量数据(几个T) 的处理方式分别是什么呢?

如果是一次性迁移,直接导出到CSV文件然后使用mongoimport命令。100MB或者几个T都是这样。

如果是持续迁移,那需要一些专门的工具,比如说我们公司的tapdata产品。


为什么需要分片集备份?

不是可以用mongodump进行全量备份嘛?

这个方法可以做备份,但是不是最严格的。

严格的备份能够提供指定时间点的恢复。比如说,如果你发现13:01分的时候有个误删操作,使用好的分片备份机制,可以恢复到13:00的准确状态。而通过mongodump是没有这种保障机制的。


我们的生产环境近几日有些数据删掉了,看还在oplog的覆盖范围内,但是我们之前没做过全量备份,这个有什么办法可以恢复吗?

可以通过历史数据备份+oplog 重放来恢复,抱歉恢复不了。



副本集集群有通过物理备份+oplog实现任意点的恢复吗,就是类似mysql的innobackupex+binlog的方式,有可参照的案例吗?


可以的,大致步骤是:

1)用snapshot或者关机复制文件方式进行全量备份

2)使用mongodump 备份 oplog 库

3)恢复全量备份

4) 使用 mongorestore 的 --oplogFile --oplogLimit 参数来恢复指定的oplog 时间点

可以参考下面这个英文博客

https://alexmarquardt.com/2017/01/25/mongodb-point-in-time-restore


分片集群具体如何实施备份?

 停掉均衡器之后,各个节点通过定时任务备份(各个机器启动备份时间点是否能够绝对一致,如果备份时间点存在几秒的差别,是否有致命风险?)

停掉均衡以后,备份可以保证每个节点各自是准确的。但是各个节点之间时间点很难保证在同一点上,所以每个节点恢复以后那个状态不是完全同步的。这个没有致命风险,但是确实有数据不一致的可能性。如果要做到完全一致,需要使用MongoDB 企业版 Ops Manager的分片备份功能。



mongodb启动参数中的logpath指的是mongo系统日志文件路径, 相当于mongodb配置文件中的systemLog.path

你可以配置MongoDB写日志到以下目的地:

1) 本地文件 (命令行参数--logpath,或者配置文件 systemLog.path)

2) syslog (命令行参数 --syslog,或者配置文件内的systemLog.syslog)

3) 标准输出(不用任何参数,默认)

参见: https://docs.mongodb.com/manual/reference/configuration-options/#systemLog.path


分片的集群通过mongos连接建立的用户是保存在哪里,config集群上面还是每个shard里面也保存?

config 集群


$  mongo -u reader -p "Reader@123"  --authenticationDatabase  admin 

上面的命令中, 一定要加上 --authenticationDatabase admin 否则会导致 Authentication failed。


如果黑客mongo连接进去然后创建个超级用户再登录这种情况怎么办?

启动鉴权后,你可以无密码登录进去,但是只能做一件事:创建超级用户。

这个事情也只能做一次(无密码创建超级用户),以后“黑客”再来,他就必须要登录才能做创建用户的事情。

所以你要做的事情,就是尽快创建那个超级用户。



mongoDB 可以定义类似 MySQL 的 create_time 和 update_time 字段吗?

可以参考 $currentDate

https://docs.mongodb.com/manual/reference/operator/update/currentDate



这个ticket默认是128,一般调高这个值的时候需要参考哪些指标?比如物理机内存?cpu核数?节点数?有没有相关经验的最佳实践分享下?

ticket一般只是个标志,如果发现用光,是因为你的物理资源不够,主要是IOPS,少数时候CPU。这个时候不是调高tickt,而是优化硬件资源。


最近做了个前端监控分析的系统,使用了MongoDB作为数据库,现在每天的存储记录达到300W+条,查询返回百万级数据这块不知道怎么优化,老师有什么建议吗?

你需要对这些数据做pre-aggregation,按照时间颗粒度,获得分钟级平均数,小时级平均数,把他们事先存到库里,给前段展现用。这样的话你就不需要返回大量的原始数据再在应用里做计算了。


听完写入操作的过程,有点好奇,oplog和journal日志能不能合并呢,我的理解的话就是oplog是个定容的集合,存放的记录都是幂等操作,用于mongodb的复制集模式,从主节点复制到其他slave节点保证数据的一致,journal日志是用于mongodb crash之后恢复的一个日志。那crash恢复能不能也用oplog呢?

oplog记录的是对数据库的逻辑操作, 在MongoDB里面用一个固定大小的普通集合来记录,和其他的数据一样,默认增删都是在内存里发生。

journal 和其他数据库类似,采用WriteAheadLog机制,用来提供对数据库写入操作的一致性和持久性保证。它记录的是要对数据物理区块修改的一些动作。

Journal 日志和Oplog理论上都可以用来恢复,但是journal比较底层,直接操作存储区,写入和恢复效率要比oplog 日志高,所以通常数据库都会采用专门的journal来做crash recovery.



如果刚开始只有一台单体,后面想扩容,做分片,搭复制集,但是这台单体上已经有相当的数据,那搭建复制集的时候是不是要先用dump等工具备份恢复一下数据?

对。使用dump/restore 可以加速这个过程。如果不用dump也是可以,时间需要更多点,但是也是可以完成的。


对于分片集群来说,应用端怎样去配置连接串呢?

只需要指定对应的几个分片路由节点连接信息就可以了么,后面的副本集发生切换对路由节点或应用有没有感知或者影响呢?

默认只需要配路由节点就可以。副本集切换是透明的。


Retrywrite 只会重试一次吗?如果重试第二次时新的primary还没被选举出来,是不是会写失败?

只会重试一次, 会一直等到primary选举成功才会试。如果30秒还没选出来,这个写操作就失败了。

30秒选不出来,这个大概率集群出故障了。


请问这一系列的课程,其中有一个课程(04 | MongoDB特色及优势),有描述到有一个企业从1.x升级到4.X,影片时间落在9:48的位置,透过滚动服务升级,透过replica set升级的升级。未来是否有课程会讨论到这一块,我想尝试不下线的方式,从4.2升级到4.22,不知道是否有该实作的教学?

其实比较简单的,假设ABC三个节点,A是当前主节点,大致可以按照以下步骤:

- 停止C的mongo服务,升级C的mongodb binary文件

- 重启C服务,等待集群稳定

- 停止B的mongo服务,升级B的mongodb binary文件

- 重启B服务,等待集群稳定

- 停止A,升级A的mongodb binary文件

- 重启A,等待集群稳定

这里有个中文翻译

http://www.mongoing.com/docs/release-notes/3.0-upgrade.html



切换FCV是在所有节点上都切换还是只在主节点上切换?

主节点上操作,会被复制到从节点。


MongoDB 压测有什么好的工具和方法实践吗?

我们一般用 POCDriver / YCSB来做压测。监控的话用Ops Manager,可以整体看压测过程中系统性能表现。


mongo是内存数据库吗? 它的数据应该在保存到硬盘吧?

MongoDB 会在内存里操作数据,用异步刷盘方式。所以你内存足够大的话,可以近似的认为它有内存数据库的性能。

 事实上它有一种存储引擎InMemory就是完全的内存数据库了。


电商网站的oracle部分不能用mongo替代吗?

 完全可以。 你可以搜一下 MongoDB Cisco关键词。 几百亿的订单都在MongoDB上处理,特别是4.0以后mongo支持了多文档事务以后。


mongodb为什么这么快,适用于秒级别的数据库访问(物联网场景等)?

比如说redis虽然是单线程,但是它基于了I/O多路复用的机制。

那mongodb呢?因为它天然的支持了分布式么?


它的数据默认只是写到内存就返回。数据的安全性通过同步到其他节点上和journal日志来保证。

没有IO在里面,响应时间自然就快。


怎么在mongo shell中修改MongoDB的配置参数?

db.adminCommand( { setParameter: 1, : } )

https://docs.mongodb.com/manual/reference/command/setParameter



mongoDB 数据库存储的时间相差八小时,有什么设置可以调整吗?还是必须要代码转一下?

 by design,没法调整。这样其实减少很多有bug的机会,就是要麻烦一点点转一下



mongodb存储文件,比如图片和视频,有什么方案吗?

大视频不太适合放mongodb。图片可以考虑。

如果真的存,直接用GridFS API就可以。还是挺方便的。


MongoDB 专家之路的 3 个建议:

1、去 MongoDB 网络大学注册学习,并通过认证考试。(https://university.mongodb.com)

2、通过官方文档学习。(https://docs.mongodb.com)

3、MongoDB 中文社区收集了很多 MongoDB 专家的精华文章和案例分享。(http://www.mongoing.com)

你可能感兴趣的:(【mongDB】MongoDB高手课答疑)