大概在08年,那時(shí)候nosql的概念特別熱,最早的那批開源項(xiàng)目好多參考google bigtable來設(shè)計(jì),我也關(guān)注過其中的幾個(gè),比如hypertable,couchdb之類,閱讀了一些相關(guān)的文檔和博文,沒有太跟進(jìn),那些開源項(xiàng)目的設(shè)計(jì)scope太大,想解決google都不一定很好解決的問題,事實(shí)上國內(nèi)能真正碰到那種數(shù)據(jù)規(guī)模的人少,很少,極少;遷移的成本也很高,我們的項(xiàng)目大多構(gòu)建在mysql+memcached上,關(guān)系型的操作很多,這種key-value或者類key-value的數(shù)據(jù)庫不是特別合用;也覺得很難從那些產(chǎn)品中獲得什么可預(yù)知的好處,不管是性能上的還是開發(fā)上的,所以也在那些項(xiàng)目上淺嘗輒止。
mongodb是從09年開始關(guān)注,從最初的一些文檔可以看出這家伙是來解決實(shí)際問題的,mongodb的作者們對(duì)mysql+memcached這套東西的優(yōu)勢(shì)和弊端看的非常清楚,項(xiàng)目的設(shè)計(jì)對(duì)我們這些lamp程序員來說,也有天然的親和力,你可以很容易把mysql的那套東西照搬到mongodb,比如collection對(duì)于mysql里面的table,沒有言必談分布式,可以很容易在單機(jī)上開發(fā)測(cè)試,可以相信在mongodb早期的auto-sharding只是個(gè)噱頭,事實(shí)上在早期的很多版本官方也不太推薦大家用。
我在選用一些技術(shù)的時(shí)候大多考慮這些方面:
1. 新的方案能不能解決目前項(xiàng)目中難以忍受的問題?
2. 新的方案是不是足夠簡(jiǎn)單?見過很多的項(xiàng)目為了解決一個(gè)稍顯復(fù)雜的問題引入一個(gè)更加復(fù)雜的方案,著實(shí)累人
3. 新的方案能不能很平滑的應(yīng)用到項(xiàng)目中去?
4. 新的方案能不能被替換?不能被替換的方案都是爛方案
在mongodb之前,我碰到的問題是:
1. 項(xiàng)目的需求不斷變化,數(shù)據(jù)庫表結(jié)構(gòu)需要不斷調(diào)整來滿足新的需求,F(xiàn)riendFeed用的是schema-less方法來解決這種問題,但是schema-less也有一些問題,在設(shè)計(jì)時(shí)候需要考慮動(dòng)靜分離,要不然為了更新某個(gè)小數(shù)據(jù)需要頻繁的更新整個(gè)大數(shù)據(jù)塊會(huì)比較煩躁,數(shù)據(jù)的一致性和有效性需要在代碼中特別注意。
2. 多對(duì)多關(guān)系的處理,典型的例子是文章tag,一篇文章有多個(gè)tag,每個(gè)tag對(duì)應(yīng)多篇文章,傳統(tǒng)的做法是維護(hù)2張表,一張是tag表,里面是tag_id對(duì)應(yīng)的tag_name,另外一張是文章對(duì)應(yīng)tag表,里面維護(hù)3個(gè)字段,tag_id、文章id、tag被打的次數(shù),然后當(dāng)有用戶新打tag的時(shí)候,你需要把新的tag和已有的tag比較,相同的+1,不存在的需要新建,然后置為1,刪除什么的也是各種煩躁
mongodb文檔型數(shù)據(jù)庫設(shè)計(jì)可以很好的解決這些問題,schema less的設(shè)計(jì)可以把整片數(shù)據(jù)塞進(jìn)去,可以很方便的對(duì)數(shù)據(jù)key建立索引,提高訪問速度,tag處理也非常方便,直接把{tag_name:tag_times}數(shù)據(jù)丟進(jìn)去就可以,非常方便。
mongodb支持大多數(shù)的mysql操作,原有代碼稍作修改即可,可以很平滑的應(yīng)用,對(duì)于一個(gè)MVC的應(yīng)用來說,基本上小修改model層就可以,非常輕松,當(dāng)然,如果一天mongodb不行了,再切換回去也不是什么困難的事情。
作為一個(gè)前中期的開源項(xiàng)目,mongodb也有一些問題需要注意:
1. 運(yùn)維和監(jiān)控工具不如mysql那么豐富
2. mongodb采用的mmap機(jī)制,在斷電和某些異常情況下有可能丟失數(shù)據(jù)或者crash,好消息是1.8以后可以打開journal日志來避免此類問題
3. schema less是一把雙刃劍,因?yàn)槭裁磾?shù)據(jù)都可以往里面存,不像mysql那樣會(huì)有字段的概念可以對(duì)數(shù)據(jù)有效性把最后一道關(guān),需要在編寫程序的時(shí)候特別注意一下數(shù)據(jù)有效性,當(dāng)然用mysql也要注意
4. 沒有auto increment id,這個(gè)很不爽,不過可以通過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框架開發(fā)的話,這部分代碼已經(jīng)包含在里面了。
一個(gè)建議是如非必要,不要用mongodb里面獨(dú)有的特性,用的越多,綁的越緊,這些特性包括auto-sharding之類。
另外一個(gè)好消息是國內(nèi)第一本mongodb圖書出版了《MongoDB權(quán)威指南》,這是一本手冊(cè)性質(zhì)的指南,譯者是mongodb中國社區(qū)的負(fù)責(zé)人程顯峰,對(duì)于不喜歡E文的同學(xué)了解mongodb大有裨益,我也在讀。






6 Responses to “我為什么選擇MongoDB”