大数据存储:MongoDB实战指南——常见问题解答

 

锁粒度与并发性能怎么样?

数据库的读写并发性能与锁的粒度息息相关,不论是读操做仍是写操做开始运行时,都会请求相应的锁资源,若是请求不到,操做就会被阻塞。读操做请求的是读锁,可以与其它读操做共享,可是当写操做请求数据库时,它所申请的是写锁,具备排它性。算法

MongoDB在2.2以前的版本,锁的粒度是很是粗的,它会锁住整个mongod实例。这意味着当一个数据库上的写锁被请求后,对mongod实例上管理的其它数据库的操做都会被阻塞。2.2版本下降了锁的粒度,引入了单个数据库范围的锁,也就是说读写操做的锁被限定在单个数据库上,当一个数据库被锁住后,其它数据库上的操做能够继续被执行。尽管相对于全局实例范围锁,数据库范围锁性能有所提升,可是对于同一个数据库大量的并发读写仍是会有性能瓶颈出现,本书介绍的2.6版本仍然是数据库范围锁,因此并发性能问题仍然存在。数据库

在即将发布的2.8版本中将会引入基于文档级别的锁,至关于关系数据库中的行级锁,锁的粒度更进一步变细。所以当一个写操做发生时,只有涉及到的文档会被锁住,若是写操做涉及到整个集合,那么将会产生一个集合锁来锁住整个集合,同理,若是写操做涉及多个数据库,仍然会有一个全局实例锁产生。数组

是否支持ACID事务?

经典ACID事务有四种特性即Atomicity,Consistency,Isolation和Durability。其中原子性保证了事务的操做要么所有成功,要么失败后进行回滚,使数据库回到原来的状态;一致性保证了事务在开始以前和结束之后,数据库中的数据彻底符合所设置的各类约束和规则;隔离性保证了多个事务操做同一数据时,相互之间按照约定的隔离级别访问和修改相同的数据,不一样的关系数据库会有不一样的默认隔离级别;持久性保证了事务结束后,事务所涉及到的数据变化被持久的保存在数据库中,即便断电重启数据也会存在,而且是完整的。服务器

MongoDB并不支持ACID事务特性,可是MongoDB支持在单个文档(记录)上的原子操做,设计数据模型时,经过文档嵌套的方式也能解决关系数据库中ACID事务特性所要求的大多数问题。例如,在关系数据库中多条相关联的记录存储,能够经过嵌套数组或文档的形式做为一条记录保存在MongoDB中,这样至关于实现了原子性。数据结构

 

 

内存映射文件如何工做?

内存映射文件是指调用操做系统的底层函数mmap( )将磁盘上的文件映射到一个操做系统虚拟地址空间中,只是地址与地址之间创建一个映射关系,实际数据还在物理磁盘上,不在内存中。内存映射文件是MongoDB存储引擎管理数据的核心方法,一旦完成映射,MongoDB对这部分文件数据的访问,就好像在内存中访问同样,经过一个地址就能直接访问了。并发

MongoDB利用内存映射文件的方式管理和操做全部的数据,若是数据没有被映射到内存中,则不能被访问。对已经完成内存映射的文件进行访问时,若是发现数据不在内存中,则会发生缺页错误,操做系统将经过映射好的地址关系找到在磁盘上的数据文件并将它加载到内存中。分布式

服务器的内存多大合适?

MongoDB采用内存映射文件的机制来加快数据的读写速度,使用操做系统自带的虚拟内存管理器来管理内存,理论上MongoDB会占用服务器上全部的空闲内存,但实状况下的数据文件老是远大于物理内存的大小,何况可能会有新的进程运行在服务器上,这也须要占用内存,所以所有将数据文件映射到虚拟地址空间是不可能的。函数

MongoDB在实际运行过程当中,会有一部分常常被客户端访问的数据和索引,称之为活跃“工做集”,若是能保证这部分“工做集”的数据常驻内存,系统性能将比较高效,不然,大量的磁盘I/O操做将会发生,下降系统性能。所以,服务器的内存大小最少大于“工做集”数据的大小比较合适。当服务器的空闲内存不足时,操做系统会根据内存管理算法将最近最少使用的数据从内存中移除,腾出空间给有须要的数据。 性能

不支持join查询怎么办?

Join查询是关系数据库中一种经典的多表联合查询的方式,但MongoDB并不支持这种操做。若是你想在多个Collection中检索数据,那么你必须作屡次的查询,若是以为手动作的查询太多了,你能够重设计你的数据模型来减小总体查询的数量。大数据

MongoDB中的文档能够是任何类型,咱们能够轻易的对数据结构进行重构,这样就可让它始终和应用程序保持一致,用一次查询就能知足需求。切记,避免用关系数据库的思惟来设计MongoDB的表结构。

复制集提供了数据冗余功能为何还要用Journaling?

Journaling是特别有用的当数据库遇到忽然断电等异常状况时,尤为是对只有单个节点的数据中心,它能使数据库快速的恢复起来。Journaling相似关系数据库MySql中的事务日志功能,它与复制集的冗余功能不同,后者更强调的是一种数据备份,而journaling偏向与数据库灾难恢复。关于Journaling的工做机制,请参考本书第5章。

何时该用GridFS?

GridFS本质上仍是基于MongoDB的collection和document等核心技术的,只是它会将大于16MB的文件分割成许多小文件,而后将这些小文件存储在相应的collection中。若是须要存储的单个文件的大小超过16MB,就应该用MongoDB自带的GridFS系统,有的时候将大文件存储在MongoDB的GridFS中比直接存在操做系统的文件系统中要更加高效;若是须要存储的文件数超过了操做系统中一个目录下容许包含的文件总数,则能够用GridFS系统;当你想要将你的文件分布式部署在各个数据中心并提供冗余保护时,能够用GridFS系统。

此外,当你的全部文件大小都小于16MB时,不要用GridFS系统,由于将每一个文件保存在一个document中每每会更高效。

分片集群如何分发查询请求的?

如何分发查询请求在一个分片集群上取决于集群的配置和查询语句自己。例如一个被分片的集合,有两个字段:user_id和user_name,其中user_id为分片的片键,当一个查询语句利用user_id做为过滤条件返回结果时,mongos路由进程将先利用配置服务器上的元信息解析出须要从哪一个或哪几个片上获取数据,而后直接将查询请求定向到具体的片上,最后返回结果给客户端;当一个查询利用user_id做为过滤条件同时要求对查询结果进行排序时,mongos先将查询请求路由到具体的片上,并在各个片上完成排序,最后mongos将合并排序结果返回给客户端;当一个查询利用user_name做为过滤条件时,则查询请求将被定向到全部的片上,mongos合并各片上查询结果返回给客户端。

复制集从故障中自动恢复要多久?

复制集从故障中恢复并选择一个新的primary节点大约需1分钟的时间。一般其它成员节点将会花大约10到30秒的时间发送心跳包到发生故障的primary节点,判断primary节点发生了故障;接着触发一个选举,大约再花10到30秒的时间选举出新的primary节点,在选举的过程当中,复制集不能响应写操做请求。若是配置了容许客户端从其它secondary节点读取,则在选举的过程当中复制集可以响应客户端的读请求。

为何磁盘分配的空间大于数据库中数据大小?

这主要有如下几方面的缘由:

(1)MongoDB存储引擎采起预分配数据文件机制,这样可以减小文件系统的碎片。MongoDB将第一个数据文件命名为<数据库名>.0,第二个命名为<数据库名>.1,依次类推下去。第一个文件的大小为64MB,第二个为128MB,后面分配的文件大小都是前面一个的两倍,这样会致使最后分配的数据文件可能会有部分空间是没有保存数据库数据的,所以会浪费一点磁盘空间。

(2)若是mongod实例是复制集的成员,则会在数据目录下产生一个oplog.rs文件,文件中包含用来同步数据的操做日志,相似于MySql中的二进制日志,这个文件的大小约占5%的磁盘空间,它是能够被重复使用的。

(3)数据目录中还会包含journal文件,在写做的更改刷新到数据文件以前,用来保存写操做日志,实现数据库的恢复功能,相似于MySql中的redo日志。

(4)当删除一些集合或文档时,MongoDB存储引擎会重用这部分数据空间,可是不会把这部分空间返还给操做系统,除非执行repairDatabase命令。

因此mongod实例占用的磁盘空间大小老是大于数据库中数据文件的大小。

大数据存储:MongoDB实战指南

相关文章
相关标签/搜索