内置GridFS,支持大容量的存储:这个特点是最吸引我眼球的,也是让我放弃其他NoSQL的一个原因。GridFS具体实现其实很简单,本质仍然是将文件分块后存储到files.file和files.chunk 2个collection中,在各个主流的driver实现中,都封装了对于GridFS的操作。由于GridFS自身也是一个Collection,你可以直接对文件的属性进行定义和管理,通过这些属性就可以快速找到所需要的文件,轻松管理海量的文件,无需费神如何hash才能避免文件系统检索性能问题, 结合下面的Auto-sharding,GridFS的扩展能力是足够我们使用了。在实践中,我们用MongoDB的GridFs存储图片和各种尺寸的缩略图。
图3 MongoDB的Auto-sharding结构
内置Sharding,提供基于Range的Auto Sharding机制:一个collection可按照记录的范围,分成若干个段,切分到不同的Shard上。Shards可以和复制结合,配合Replica sets能够实现Sharding+fail-over,不同的Shard之间可以负载均衡。查询是对客户端是透明的。客户端执行查询,统计,MapReduce等操作,这些会被MongoDB自动路由到后端的数据节点。这让我们关注于自己的业务,适当的时候可以无痛的升级。MongoDB的Sharding设计能力最大可支持约20 petabytes,足以支撑一般应用。
第三方支持丰富: MongoDB社区非常活跃,很多开发框架都迅速提供了对MongDB的支持。不少知名大公司和网站也在生产环境中使用MongoDB,越来越多的创新型企业转而使用MongoDB作为和Django,RoR来搭配的技术方案。
实施结果
实施MonoDB的过程是令人愉快的。我们对自己的PHP开发框架进行了修改以适应MongoDB。在PHP中,对MongoDB的查询、更新都是围绕Array进行的,实现代码变得很简洁。由于无需建表,MonoDB运行测试单元所需要的时间大大缩短,对于TDD敏捷开发的效率也提高了。当然,由于MongoDB的文档模型和关系数据库有很大不同,在实践中也有很多的困惑,幸运的是,MongoDB开源社区给了我们很大帮助。最终,我们使用了2周就完成了从MySQL到MongoDB的代码移植比预期的开发时间大大缩短。从我们的测试结果看也是非常惊人,数据量约2千万,数据库300G的情况下,读写2000rps,CPU等系统消耗是相当的低(我们的数据量还偏小,目前陆续有些公司也展示了他们的经典案例:MongoDB存储的数据量已超过 50亿,>1.5TB)。目前,我们将MongoDB和其他服务共同部署在一起,大大节约了资源。
一些小提示
切实领会MongoDB的Document模型,从实际出发,扔掉关系数据库的范式思维定义,重新设计类;在服务端运行的JavaScript代码避免使用遍历记录这种耗时的操作,相反要用Map/Reduce来完成这种表数据的处理;属性的类型插入和查询时应该保持一致。若插入时是字符串“1”,则查询时用数字1是不匹配的;优化MongoDB的性能可以从磁盘速度和内存着手;MongoDB对每个Document的限制是最大不超过4MB;在符合上述条件下多启用Embed Document, 避免使用DatabaseReference;内部缓存可以避免N+1次查询问题(MongoDB不支持joins)。
用Capped Collection解决需要高速写入的场合,如实时日志;大数据量情况下,新建同步时要调高oplogSize的大小,并且自己预先生成数据文件,避免出现客户端超时;Collection+Index合计数量默认不能超过24000;当前版本(
结束语
MongoDB的里程碑是1.6版本,预计今年7月份发布,届时,MongoDB的Sharding将首次具备在生产环境中使用的条件。作为MongoDB的受益者,我们目前也在积极参与MongoDB社区活动,改进Perl/PHP对于MongoDB的技术方案。在1.6版本后也将年内推出基于MongoDB的一些开源项目。
对于那些刚刚起步,或者正在开发创新型互联网应用的公司来说,MongoDB的快速、灵活、轻量和强大扩展性,正适合我们快速开发产品,快速迭代,适应用户迅速变化和更新的种种需求。
总而言之,MongoDB是一个最适合替代MySQL的全功能的NoSQL产品,使用MongoDB+Perl/PHP/Django/RoR的组合将很快成为开发Web2.0、3.0的产品的非常好的组合,就像当年MySQL替代Oracle/DB2/Informix一样,历史总是惊人的相似,让我们拭目以待吧!