抄摘:我为什么选择MongoDB(用于备忘)
mongodb是从09年开始关注,从最初的一些文档可以看出这家伙是来解决实际问题的,mongodb的作者们对mysql+memcached这套东西的优势和弊端看的非常清楚,项目的设计对我们这些lamp程序员来说,也有天然的亲和力,你可以很容易把mysql的那套东西照搬到mongodb,比如collection对于mysql里面的table,没有言必谈分布式,可以很容易在单机上开发测试,可以相信在mongodb早期的auto-sharding只是个噱头,事实上在早期的很多版本官方也不太推荐大家用。
我在选用一些技术的时候大多考虑这些方面:
1. 新的方案能不能解决目前项目中难以忍受的问题?
2. 新的方案是不是足够简单?见过很多的项目为了解决一个稍显复杂的问题引入一个更加复杂的方案,着实累人
3. 新的方案能不能很平滑的应用到项目中去?
4. 新的方案能不能被替换?不能被替换的方案都是烂方案
在mongodb之前,我碰到的问题是:
1. 项目的需求不断变化,数据库表结构需要不断调整来满足新的需求,FriendFeed用的是schema-less方法来解决这种问题,但是schema-less也有一些问题,在设计时候需要考虑动静分离,要不然为了更新某个小数据需要频繁的更新整个大数据块会比较烦躁,数据的一致性和有效性需要在代码中特别注意。
2. 多对多关系的处理,典型的例子是文章tag,一篇文章有多个tag,每个tag对应多篇文章,传统的做法是维护2张表,一张是tag表,里面是tag_id对应的tag_name,另外一张是文章对应tag表,里面维护3个字段,tag_id、文章id、tag被打的次数,然后当有用户新打tag的时候,你需要把新的tag和已有的tag比较,相同的+1,不存在的需要新建,然后置为1,删除什么的也是各种烦躁
mongodb文档型数据库设计可以很好的解决这些问题,schema less的设计可以把整片数据塞进去,可以很方便的对数据key建立索引,提高访问速度,tag处理也非常方便,直接把{tag_name:tag_times}数据丢进去就可以,非常方便。
mongodb支持大多数的mysql操作,原有代码稍作修改即可,可以很平滑的应用,对于一个MVC的应用来说,基本上小修改model层就可以,非常轻松,当然,如果一天mongodb不行了,再切换回去也不是什么困难的事情。
作为一个前中期的开源项目,mongodb也有一些问题需要注意:
1. 运维和监控工具不如mysql那么丰富
2. mongodb采用的mmap机制,在断电和某些异常情况下有可能丢失数据或者crash,好消息是1.8以后可以打开journal日志来避免此类问题
3. schema less是一把双刃剑,因为什么数据都可以往里面存,不像mysql那样会有字段的概念可以对数据有效性把最后一道关,需要在编写程序的时候特别注意一下数据有效性,当然用mysql也要注意
4. 没有auto increment id,这个很不爽,不过可以通过findandmodify来模拟出来
function autoIncrementId( $domain , $collection = 'autoIncrementIds' , $db = null ) { $result = $mongo -> command ( array ( 'findAndModify' => $collection , 'query' => array ( '_id' => $domain ) , 'update' => array ( '$inc' => array ( 'val' => 1 ) ) , 'new' => true , 'upsert' => true ) ) ; if ( $result [ 'ok' ] ) { return $result [ 'value' ] [ 'val' ] ; } throw new Exception( 'Mongo: gen auto increment id failed' ) ; }
如果你采用ColaPHP框架开发的话,这部分代码已经包含在里面了。
一个建议是如非必要,不要用mongodb里面独有的特性,用的越多,绑的越紧,这些特性包括auto-sharding之类。