为什么MongoDB可以替代MySQL?
MongoDB是⼀个⾯向⽂档的数据库,⽬前由10gen开发并维护,它的功能丰富,齐全,完全可以替代MySQL。在使⽤MongoDB做产品原型的过程中,我们总结了MonogDB的⼀些亮点:
使⽤JSON风格语法,易于掌握和理解:MongoDB使⽤JSON的变种BSON作为内部存储的格式和语法。针对MongoDB的操作都使⽤JSON风格语法,客户端提交或接收的数据都使⽤JSON形式来展现。相对于SQL来说,更加直观,容易理解和掌握。
Schema-less,⽀持嵌⼊⼦⽂档:MongoDB是⼀个Schema-free的⽂档数据库。⼀个数据库可以有多个Collection,每个Collection是Documents的集合。Collection和Document和传统数据库的Table和Row并不对等。⽆需事先定义Collection,随时可以创建。
Collection中可以包含具有不同schema的⽂档记录。这意味着,你上⼀条记录中的⽂档有3个属性,⽽下⼀条记录的⽂档可以有10个属性,属性的类型既可以是基本的数据类型(如数字、字符串、⽇期等),也可以是数组或者散列,甚⾄还可以是⼀个⼦⽂档(embed document)。这样,可以实现逆规范化(denormalizing)的数据模型,提⾼查询的速度。
图1 MongoDB是⼀个Schema-free的⽂档数据库
mysql帮助文档
图2是⼀个例⼦,作品和评论可以设计为⼀个collection,评论作为⼦⽂档内嵌在art的comments属性中,评论的回复则作为comment⼦⽂档的⼦⽂档内嵌于replies属性。按照这种设计模式,只需要按照作品id检索⼀次,即可获得所有相关的信息了。在MongoDB中,不强调⼀定对数据进⾏Normalize ,很多场合都建议De-normalize,开发⼈员可以扔掉传统关系数据库各种范式的限制,不需要把所有的实体都映射为⼀个Collection,只需定义最顶级的class。MongoDB的⽂档模型可以让我们很轻松就能将⾃⼰的Object映射到collection中实现存储。
图2 MongoDB⽀持嵌⼊⼦⽂档
简单易⽤的查询⽅式:MongoDB中的查询让⼈很舒适,没有SQL难记的语法,直接使⽤JSON,相当的直观。对不同的开发语⾔,你可以使⽤它最基本的数组或散列格式进⾏查询。配合附加的operator,MongoDB⽀持范围查询,正则表达式查询,对⼦⽂档内属性的查询,可以取代原来⼤多数任务的SQL查询。
CRUD更加简单,⽀持in-place update:只要定义⼀个数组,然后传递给MongoDB的insert/update⽅法就可⾃动插⼊或更新;对于更新模式,MongoDB⽀持⼀个upsert选项,即:“如果记录存在那么更新,否则插⼊”。MongoDB的update⽅法还⽀持Modifier,通过Modifier可实现在服务端即时更新,省去客户端和服务端的通讯。这些modifer可以让MongoDB具有和Redis、Memcached等KV类似的功能:
较之MySQL,MonoDB更加简单快速。Modifier也是MongoDB可以作为对⽤户⾏为跟踪的容器。在实际中使⽤Modifier来将⽤户的交互⾏为快速保存到MongoDB中以便后期进⾏统计分析和个性化定制。
所有的属性类型都⽀持索引,甚⾄数组:这可以让某些任务实现起来⾮常的轻松。在MongoDB中,“_id”属性是主键,默认MongoDB会对_id创建⼀个唯⼀索引。
服务端脚本和Map/Reduce:MongoDB允许在服务端执⾏脚本,可以⽤Javascript编写某个函数,直接在服务端执⾏,也可以把函数的定义存储在服务端,下次直接调⽤即可。MongoDB不⽀持事务级别的锁定,对于某些需要⾃定义的“原⼦性”操作,可以使⽤Server side脚本来实现,此时整个MongoDB处于锁定状态。Map/Reduce也是MongoDB中⽐较吸引⼈的特性。Map/Reduce可以对⼤数据量的表进⾏统计、分类、合并的⼯作,完成原先SQL的GroupBy等聚合函数的功能。并且Mapper和Reducer的定义都是⽤Javascript来定义服务端脚本。
性能⾼效,速度快: MongoDB使⽤c++/boost编写,在多数场合,其查询速度对⽐MySQL要快的多,对于CPU占⽤⾮常⼩。部署也很简单,对⼤多数系统,只需下载后⼆进制包解压就可以直接运⾏,⼏乎是零配置。
⽀持多种复制模式: MongoDB⽀持不同的服务器间进⾏复制,包括双机互备的容错⽅案。
Master-Slave是最常见的。通过Master-Slave可以实现数据的备份。在我们的实践中,我们使⽤的是Master-Slave模式,Slave只⽤于后备,实际的读写都是从Master节点执⾏。
Replica Pairs/Replica Sets允许2个MongoDB相互监听,实现双机互备的容错。
MongoDB只能⽀持有限的双主模式(Master-Master),实际可⽤性不强,可忽略。
内置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;当前版本(<v1.6)删除数据的空间不能被回收,如果你频繁删除数据,那么需要定期执⾏repairDatabase,释放这些空间。
结束语
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⼀样,历史总是惊⼈的相似,让我们拭⽬以待吧!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。