當(dāng)前位置:首頁 >  站長 >  網(wǎng)站運營 >  正文

大型網(wǎng)站架構(gòu)系列之三 多對多關(guān)系的優(yōu)化設(shè)計

 2008-09-18 14:02  來源:   我來投稿 撤稿糾錯

  域名預(yù)訂/競價,好“米”不錯過

接上篇,大型網(wǎng)站架構(gòu)系列之二 底層架構(gòu)概論

上篇以用戶數(shù)據(jù)表為例介紹了基本的數(shù)據(jù)分割方案以及基本的配置方案。但是在2.0時代,這種簡單的列表索引已經(jīng)遠遠實現(xiàn)起來是問題的,多對多關(guān) 系將是最常見的關(guān)系?,F(xiàn)在我們針對web2.0數(shù)據(jù)中廣泛存在的多對多關(guān)系進行闡述和具體行為判斷,比如一個很簡單的例子,在2.0時代,好友功能是最常 被用到的,每個用戶會有很多的好友,同時也會是很多人的好友,那么這個數(shù)據(jù)量將會是用戶數(shù)的平方的級別。同樣,對于文章標(biāo)簽,每個文章可以有多個標(biāo)簽,而 每個標(biāo)簽又可以有多個文章,這又是一個幾何乘積,數(shù)據(jù)量又會是個天文數(shù)字。

傳統(tǒng)的處理方案有兩種,一種是通過SEARCH的方法來實現(xiàn),一種是通過另建一個索引表,存貯對應(yīng)的ID以進行存貯。對于第一種方案,因為要涉 及大量的LIKE查詢,性能不敢恭維,第二種的情況下,數(shù)據(jù)庫的行的數(shù)量也是驚人海量級別的,并且要跨表跨區(qū)查詢,還要維護數(shù)據(jù)的唯一性,數(shù)據(jù)處理過程相 當(dāng)?shù)膹?fù)雜性能也就不言而喻了。

文入正題,下面對數(shù)據(jù)多對多關(guān)系舉出來具體的解決方案,我們這里以標(biāo)簽和文章之間的多對多關(guān)系為例來講解,大家可以舉一反三的思考群組和用戶之間,相冊和被圈用戶之間等等復(fù)雜的多對多關(guān)系。

首先濾清一下流程,我們以傳統(tǒng)方案的第二種為例,在傳統(tǒng)的數(shù)據(jù)庫設(shè)計中我們是如下走的:當(dāng)一篇博文發(fā)布的時候并插入標(biāo)簽的時候一般是三步走(也 可以理解為四步,以為還要判斷標(biāo)簽是否存在的問題),第一步插入文章數(shù)據(jù)庫并獲取文章的ID,第二步插入標(biāo)簽數(shù)據(jù)庫同時查詢標(biāo)簽是否存在,如果存在就取出 標(biāo)簽的ID,否則的話插入新標(biāo)簽并取出ID,第三部,將文章的ID和標(biāo)簽的ID插入索引表來建立關(guān)聯(lián)。如果這個時候在索引表上建立了索引的話就是災(zāi)難性 的,特別是在數(shù)據(jù)量大的情況下,盡管它可以有效的提高查詢速度,但是發(fā)布的速度可能就會讓人無法忍受了。

我們處理的方法也是三部曲,對多對多關(guān)系進行進一步的處理。

用標(biāo)簽的時候,我們用的最多的就是查詢標(biāo)簽下的文章和顯示文章的標(biāo)簽,所以我們實現(xiàn)這例就成了。

第一步,拋棄索引表。

對文章做冗余字段,加一個TAG列,我們可以講TAG的標(biāo)簽如下寫[TagID,TagName]| [TagID,TagName]| [TagID,TagName] 同樣 對于TAG表,我們做如下冗余加個Article字段,如下內(nèi)容[ArticleID,Title]| [ArticleID, Title]| [ArticleID, Title],在需要增加的時候我們只要APPEND一下就可以了,至于ARTICLE的結(jié)構(gòu)和TAG的結(jié)構(gòu)可以參考我上一篇文章的介紹。其實根據(jù)需要還 可以存貯更多。

有人會問,為什么要存貯TagName和ArticleTitle呢,其實是為了避免跨表查詢和INNERJOIN查詢來做的,In查詢和跨表查詢會造成全表遍歷,所以我們在執(zhí)行的時候In查詢是必須要找到一個有效的替代方法的。

第二部:異步加載。

在設(shè)計模式下我們常思考的是單件模式,我們采用另類的單件模式來處理,也就是把文章和標(biāo)簽之間的索引作為專門的進程來做,異步的實現(xiàn)。

為了避免文章在發(fā)布的時候以為要檢查TAG表而造成的線程擁堵,我們需要采取延遲加載的方案來做。服務(wù)器應(yīng)該維護一個進程專業(yè)的對標(biāo)簽和文章地段的查詢和索引,我們在發(fā)布文章的時候應(yīng)該把標(biāo)簽同步這一塊托管給另外的一個程序進行處理,并進行索引。

第三部:標(biāo)簽緩存索引:

對于頻繁的判斷標(biāo)簽去或者熱門的標(biāo)簽我們還可以組織一套有效的索引,比如對于標(biāo)簽“瘋狂代碼”和”傲博知識庫”,我們用樹來把它表示出來。對于 瘋狂代碼我們索引一個瘋,其實用程序表達就是瘋狂代碼[0],同樣傲博知識庫就是傲博知識庫[0]。而在數(shù)組”瘋”中存貯以瘋開頭的標(biāo)簽組,以”傲”的數(shù) 組中存貯以”傲”開頭的標(biāo)簽。如果量更大的話還可以再做二級索引。

這涉及另外一個話題了就是分詞,上面是一個簡單的分詞方案,大家在進行GOOGLE搜索的時候應(yīng)該很輸入它的Suggest方法吧,就是這個道理。最終講標(biāo)簽有效的索引,并提取熱門的作為一個全局靜態(tài)變量,我們就可以繞過數(shù)據(jù)查詢這一關(guān),對第二部的單件模式又是一個進化。

以上是對多對多關(guān)系的一個簡單的架構(gòu)說明,肯定有人會問,如果這樣做的話工作量不是太大了嗎,分詞處理什么的,對每個多對多關(guān)系進行處理。

OK,咱們可以進一步的把它來抽象化,我們用TableA 表示Article表,用TagbleT表示Tag表,我們可以講字段抽象化出來,也就是一個ID,一個Tag的String 同理對于標(biāo)簽表也是如此。朋友們應(yīng)該可以理解我的意思了。

對,就是做個代碼生成器把對應(yīng)的多對多關(guān)系給生成出來,這個很好寫的,幾個Append就可以搞定。如果想更方便的處理,那么把這個東西做成單件的模式抽象化出來,然后再違反一下原則,做成基類,其他關(guān)系繼承這個基類。。。。。剩下的應(yīng)該很簡單了,具體實現(xiàn)大家思考吧。

請參照第二篇的文章進行進一步優(yōu)化設(shè)計來實現(xiàn)更高的負載性能

下章接著講述數(shù)據(jù)分割和散列方面的內(nèi)容

瘋狂代碼原創(chuàng)發(fā)布,同步發(fā)布于 和

轉(zhuǎn)載請注明出處

申請創(chuàng)業(yè)報道,分享創(chuàng)業(yè)好點子。點擊此處,共同探討創(chuàng)業(yè)新機遇!

相關(guān)文章

熱門排行

信息推薦