MongoDB的模型設(shè)計(jì)方法論
雖然說mongoDB不像傳統(tǒng)的關(guān)系型數(shù)據(jù)庫趾牧,沒有固定的schema,但是在項(xiàng)目中實(shí)際運(yùn)用時(shí)果善,還是需要進(jìn)行一定程度的模型設(shè)計(jì)都办,一般來說模型設(shè)計(jì)分為三步,即概念模型(描述系統(tǒng)要管理的對(duì)象)镜会,邏輯模型(列出所有對(duì)象的所有屬性以及對(duì)象之間的關(guān)系)和物理模型(數(shù)據(jù)庫表的物理結(jié)構(gòu))檬寂,mongoDB的模型設(shè)計(jì)只需要到邏輯模型就可以了。
在進(jìn)行mongoDB模型設(shè)計(jì)的時(shí)候可以按照三步來戳表,首先是基礎(chǔ)設(shè)計(jì)桶至,將即邏輯模型落地成一個(gè)基本的文檔模型;然后是第二步工況細(xì)化匾旭,根據(jù)應(yīng)用中的實(shí)際使用來進(jìn)行模型的優(yōu)化镣屹,比如一個(gè)文檔中的一個(gè)數(shù)組字段存的值是通用的,并且需要經(jīng)常進(jìn)行變更季率,這樣一次變更就需要對(duì)多個(gè)文檔進(jìn)行變更(比如文檔中保存多對(duì)多的分組信息野瘦,而分組名變化時(shí)該分組下的所有文檔都需要更新),這時(shí)候就可以把數(shù)組中存儲(chǔ)的信息改為引用以提高更新效率;第三步就是模式套用鞭光,即套用一些已有的經(jīng)典設(shè)計(jì)模式以提高模型查詢效率吏廉。
經(jīng)典模式舉例
1.一個(gè)大文檔,有很多字段惰许,每個(gè)字段都需要索引席覆,導(dǎo)致索引很多寫入效率緩慢。此時(shí)可以用列轉(zhuǎn)行的模式汹买。比如一個(gè)商品要記錄每個(gè)地區(qū)的價(jià)格佩伤,開始的結(jié)構(gòu)可能是:
{price_sc:123,price_hb:222,price_gz:342}
列轉(zhuǎn)行后的模型變?yōu)椋?/p>
{price_info:[{area:"sc",price:123},{area:"hb",price:222},{area:"gz",price:342}]}
2.靈活模型由于可以每個(gè)應(yīng)用版本自由得增減文檔字段,為了更好進(jìn)行管理就可以增加一個(gè)版本字段晦毙,以識(shí)別每個(gè)文檔所處的版本
3.對(duì)于需要頻繁寫入但又對(duì)數(shù)據(jù)準(zhǔn)確性要求不高的數(shù)據(jù)可以使用近似計(jì)算來提高效率生巡,比如如果需要進(jìn)行某個(gè)按鈕點(diǎn)擊次數(shù)的統(tǒng)計(jì)但又并不需要非常精確的數(shù)據(jù),就可以使用if(rand(10)=0) count+=10這樣的方式進(jìn)行近似計(jì)算
4.如果有需要頻繁進(jìn)行聚合查詢的數(shù)據(jù)见妒,而由于數(shù)據(jù)量大聚合操作很耗時(shí)孤荣,就可以進(jìn)行預(yù)聚合的模式,即保存一個(gè)聚合字段须揣,每次更新數(shù)據(jù)的時(shí)候也更新聚合字段盐股,這樣在查詢時(shí)就不需要再進(jìn)行聚合操作了。當(dāng)然這樣也會(huì)增加寫入數(shù)據(jù)的消耗耻卡,所以適用聚合查詢很多且確實(shí)是主要性能瓶頸的情況疯汁。
MongoDB寫事務(wù)
mongo的寫事務(wù)是通過配置writeConcern參數(shù)來實(shí)現(xiàn)的,writeConcern有幾個(gè)可以配置的值:0卵酪,1-集群最大節(jié)點(diǎn)數(shù)或者majority幌蚊,如果配置為0意思是客戶端只發(fā)起寫操作并不關(guān)心寫操作是否成功,這種配置下數(shù)據(jù)的安全性最低溃卡,不推薦配置成該值霹肝,如果配置為1-集群最大節(jié)點(diǎn)數(shù)(n)的話,就是至少保證有n個(gè)節(jié)點(diǎn)寫入成功才返回客戶端成功塑煎,意思是如果配置成集群節(jié)點(diǎn)數(shù)的話,一次寫入會(huì)在數(shù)據(jù)同步到集群所有節(jié)點(diǎn)上之后才算成功臭蚁,這樣固然數(shù)據(jù)是最安全的最铁,但是會(huì)大大影響寫入的效率,所以一般也不建議這樣使用垮兑。writeConcern最常見的配置就是majority冷尉,意為大多數(shù)節(jié)點(diǎn)寫入成功即返回成功,比如集群中有5個(gè)節(jié)點(diǎn)系枪,那么有3個(gè)節(jié)點(diǎn)寫入成功即會(huì)返回客戶端成功寫入雀哨,這種配置兼顧了安全性和寫入性能的保證。
MongoDB讀事務(wù)
MongoDB的讀事務(wù)主要涉及到兩個(gè)參數(shù),第一個(gè)是readPreference雾棺,另一個(gè)是readConcern
1.readPreference
readPreference的配置主要作用是配置讀操作時(shí)更加傾向讀取的節(jié)點(diǎn)膊夹。可能取值有primary捌浩,primaryPreferred放刨,secondary,secondaryPreferred尸饺,nearest进统。primary為只讀取主節(jié)點(diǎn);primaryPreferred為優(yōu)先讀取主節(jié)點(diǎn)浪听,主節(jié)點(diǎn)不可用時(shí)讀取子節(jié)點(diǎn)螟碎;secondary為只讀取子節(jié)點(diǎn);secondaryPreferred為優(yōu)先讀取子節(jié)點(diǎn)迹栓,子節(jié)點(diǎn)不可用時(shí)讀取主節(jié)點(diǎn)掉分;nearest為讀取最近的節(jié)點(diǎn),主要用于數(shù)據(jù)跨區(qū)域存儲(chǔ)迈螟。
2.readConcern
readConcern的主要作用就是用于讀取時(shí)判斷節(jié)點(diǎn)上哪些數(shù)據(jù)是可讀的叉抡,類似于關(guān)系型數(shù)據(jù)庫中的隔離級(jí)別,可選值有available答毫,local褥民,majoyrity,linearizable和snapshot洗搂。available和local在復(fù)制集中的作用大致上都是一樣的消返,即都是讀屬于當(dāng)前分片的數(shù)據(jù);majoyrity意思是讀已經(jīng)被大多數(shù)分片保存到的數(shù)據(jù)耘拇,這個(gè)類似于關(guān)系型數(shù)據(jù)庫隔離級(jí)別中的讀已提交撵颊,在讀寫分離的場景中可能會(huì)遇到往主節(jié)點(diǎn)中完成了寫入數(shù)據(jù)之后在子節(jié)點(diǎn)中無法馬上找到該數(shù)據(jù),這個(gè)時(shí)候可以通過配置writeConcern和readConcern都為majoyrity來解決這個(gè)問題惫叛;linearizable和majoyrity的不同是它會(huì)保證操作的線性順序倡勇,及寫操作之后的讀一定能讀到寫操作寫入的數(shù)據(jù),比如有這樣的情況嘉涌,一個(gè)主節(jié)點(diǎn)在集群中與其他節(jié)點(diǎn)失聯(lián)妻熊,而其他節(jié)點(diǎn)此時(shí)已經(jīng)重新選出了一個(gè)主節(jié)點(diǎn),但失聯(lián)的主節(jié)點(diǎn)并沒有意識(shí)到出現(xiàn)了問題依然在接受請(qǐng)求仑最,則此時(shí)在新的主節(jié)點(diǎn)中寫入的數(shù)據(jù)在失聯(lián)的主節(jié)點(diǎn)中是查詢不到的扔役,而如果配置了linearizable,讀操作會(huì)在保證讀的節(jié)點(diǎn)與其他節(jié)點(diǎn)的連接性警医。snapshot則是讀取最近的一次數(shù)據(jù)庫快照亿胸,類似于可重復(fù)讀坯钦。