初探MongoDB:暴力美学

Tags mongodab


2015-02-09 11:57:20


AUTH:PHILO version:2.0

##Abstract 为了在项目中更好的使用MongoDB来完成我们的业务,我们探究了MongoDB性能暴力的成因以及如何更加合理的使用MongoDB。 并且简单的描述普通业务数据库设计的简单分析方法。以及避免盲目崇拜对整体数据存储与处理的分析。 同时也为了大家初探本数据库提供了可靠的研究学习路线让学习曲线不会那么陡峭。 当然我们也总结了关于以golang为例的驱动解决方案,以及复杂存储业务的解决方案。 在整个研究过程中我们发现MongoDB的存储因为更加符合现代业务既关系复杂涉及到的实体比较多的特征。提升了整个存储系统的IO能力。 另外BSON数据操作让业务处理如虎添翼。更是提升了开发速度。

Introduction

随着互联网业务爆炸式的增长,云计算的兴起,业务的拓展与实现面临着又一次新的挑战。 MongoDB的出现能够快速的完成系统的开发于拓展需求。提升持久化系统的吞吐量。 MongoDB相较于普通的关系型数据库(SQL)具有简洁的数据库设计同时设计也是非常容易的。更加契合业务数据特征的存储方式。 降低了很多业务存储上的代价。在工程中应该从严谨的角度来给MongoDB选择合适的业务来存储。

关于性能

性能方面没有必要列举过多的数据来说明具体的情况。一方面这些都是官方应该干的事。另外一方面每次项目每个公司的硬件环境都有很大的不同,这些硬件上的不同会导致测试数据的结果有着天差地别的结果。 最为重要的一点是应用场景的不同。不同的业务会导致不同的数据库使用情况。所以真正想要得到具体的项目解决方案,一方面要靠个人对项目的准确判断,另一方面具体的方案确定需要根据情况做出具体的测试。

说到性能肯定是要从搜索Page Rank最高的结果说起 来自博主疯狂光纤的博文 http://www.cnblogs.com/crazylights/archive/2013/05/08/3066056.html 以及相关的实战相关博文 http://www.cnblogs.com/crazylights/archive/2013/05/08/3068098.html 客观来讲,第一篇文的内容语言的确是比较激进的。缺少可观的分析。但是第二篇文章直接上了实战来直接说明到底MongoDB性能有多暴力。但是有一点不可取的点就是第一篇说的忘记。这个观点与我的想法有点背道而驰,我们更应该扬长避短结合SQL于NoSQL的优势来快速完成我们的需求。正片开始。

简单的存储特征分析

  1. 使用KV数据存储(BSON)
    1. 使用方便。类似JSON操作,当然很多语言可以映射到内存里面。
    2. 查询修改也使用BSON,操作更加清晰。
  2. 文件存储
    1. 每一条数据都是一个文件,文件有大小限制,如果想使用更大的文件系统请使用GridFS
    2. 提升数据存储于业务的契合度,比如说一个帖子的文件中直接存储回复。一次取出整个文件减少了再次查询回复内容的时间。
  3. 查询功能强大
    1. 使用BSON查询的功能非常强大清晰。
    2. 由于使用文件的对象存储方式,因此在索引上相对于普通的 SQL92 标准的数据库会有一定的性能代价。推荐使用有意义的键值来尽量避免业务的查询。

因为MongoDB有如上的特征。因此: 1. MongoDB更适合存储关系型数据 2. 普通的关系型数据库更适合大量对象的数据检索

理由在于二者索引的区别,前者不适合有大量数据扫描的查询,后者更加擅长大量数据扫描的业务。 在很多文章中MongoDB不适合有太多的skip操作(甚至还提出避免skip的方案)

适应情况的例子

业务描述粒度:具体到CURD应该在什么数据库中存储,
描述方法: 业务类型,使用数据库,场景举例。 这里只是大概描述一下数据库选择的轮廓有一个选择的概念。也只是说了很小一部分的片面的参考

  1. 偏向增加的业务
    1. 用户数据版本管理(文章,记事本等)
  2. 偏向于复杂关系数据的查询
    1. 帖子的回复(帖子的范围: 可以评论的对象)
    2. 对象状态改变的记录图 (比如说订单状态改变,记录具体时间,事件,发起者,以及其他内容。)
  3. 偏向于修改的业务
    1. 用户个人信息的修改(密码,NickName等)
    2. 复杂对象的属性修改(店铺信息等)
    3. 对象复杂但是存储数据内容简短的内容且update比较频繁的情况。
  4. 不推荐删除系统数据这部分会在后面给出解释
    1. 数据永远都不要删除,数据就是财富。在凌晨的时候或者负载非得低的时候停机一个小时来维护数据还是非常值得的。

学习方法路线以及其他应该注意的地方

之前确实参考了很多其他人写的书,但是最后发现。一定还是Manual写的是最好的。 由浅入深,讲明白了基础知识之后从CURD开始一步一步的讲述MongoDB是如何存储数据的。 因此在这里也是强烈推荐大家从MongoDB的manual开始学习。

驱动

因为语言不同驱动也有不同,但是对于MongoDB来说都是对应几个接口的Bson操作。因此接口比较好脑补。如果遇到难点可以直接绕过去,我在2014年年末的时候就研究出来一套复杂查询的方案。 > 只在极端情况下使用,如果你的查询过于复杂也许你就犯了Skip过多数据的错误。 http://www.philo.top/1899/11/30/788MongoDB%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98/

删除数据

请不要在数据库中删除数据。因为remove()函数不会删除集合本身,同时,原有的索引也同样不会被删除。因此在查询的时候就会留下一个黑洞。对于生产环境会有很大的问题。

关于Don’t use MongoDB

原文链接 http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/ 我不做评论,只是几点需要注意 1. 吐槽者所解决的问题已经是非常复杂的了。就类似于12306已经达到了计算机集群的性能极限。因此只说MongoDB的问题是片面的。 2. 这只是高手级别(CTO级别)的吐槽。解决问题的办法总是有的。可能他们需要更加复杂的方案 3. 注意吐槽者说的项目时间是在2010年吐槽时间实际在2013年。 4. 他们通篇并没有提及MongoDB使用的版本但是我相信他们用是MongoDB的官方版本,如果他们的产品是千万用户量级的话,也许就会类似淘宝&&FaceBook一样针对社区产品Fork自己应用场景的Branch

So , do not panic.

Cache必不可少

  1. 比如说用户表的缓存。 > 新浪微博对用户分类的方法: 1. 当天登陆过的用户 2. 活跃用户 3. 不活跃的用户 我们可以对第一种跟第二种的情况进行缓存,因为很多用户数据的查询都关系到了User表的查询。在高负载情况请建立用户缓存。 但是请注意优化不要过早。缓存类型根据情况选择Memcache或Redis

  2. 高速度也是有代价的。因此要针对业务热点做一个权衡,是否应该浪费性能在磁盘IO上。

盲目崇拜

早在2010年的时候我在学校的图书馆里面为数不多的订阅杂志里面发现了NoSQL方面的论文,那时候MongoDB也只是距离First Release刚刚一年而已,而我也只是饶有兴趣的在读里面的CAP理论,清楚的记得,数据库也只能三选二。

再后来2011年的时候Mysql Release 5.5的版。我在寝室里面奔走相告。告诉大家性能提升了百分之55。

而当我毕业的时候正好有一个百万用户量级的需求押在了MySql+MongoDB+Golang的头上。

话不多说,我只看见了很多口炮一方面又开始说XX数据库很垃圾。另一方面说。你只是不会用而已。但是个人推崇一种更加中立的观点: 工程是一种妥协的艺术。所以方案的选择没有好坏只有根据具体情况的不同有着不同的选择。

而经过几个月的研究学习,虽然我非常肤浅的研究了一下MongoDB但是还是总结出来了一套关于MongoDB性能的掌握,我个人认为适用的应用场景以及最低学习代价的学习方法。

最关键的是,我们所使用的大部分服务器都是基于冯诺依曼体系的,他规定了计算机核心组件就那么几样,特征也都是固定的,所以只要是一样的机器。 执行指令集的性能应该是一样的。既然大家的大环境都是一样的,只是存储跟查询的方式不一样,如果深入了解之后会发现,两种数据库存储数据的方式上的差异造成了各种业务存储选择的多样化。因此只有深入学习深入了解这两种数据库具体的核心内容才能判定到底哪个更适合你的业务。

总结

归于实用主义,还是就说到这里吧。没有太多的图表内容,实在是无意写一些口水文。 最后非常感谢能看完我啰嗦这么半天。 于2-9-2015公司上班最后一天。


本人博客文章采用CC Attribution-NonCommercial协议: CC Attribution-NonCommercial 必须保留原作者署名,并且不允许用于商业用途,其他行为都是允许的。