螞蟻變大象:淺談常規網站是如何從小變大的(三)

【 前一段時間寫了關於架構的總結,一共十篇,放在新浪博客上 :http://blog.sina.com.cn/zgwangbo001 ,今天放到csdn上】

也可以關注微信公衆號:simplemain



―――――――――――――繼續技術的分割線 ―――――――――――――

 

 

        【第七階段 : 拆分】

 

        到上面一個階段,我們初步接觸到了邏輯、存儲等的多機模式。這樣的結構,對於邏輯不是特別複雜的網站,足以撐起千萬級的壓力。所以大多數網站,只要能夠用好上面的結構就可以很好的應對服務壓力了。只不過還有很多細節的工作需要精細化,比如:多機的運維、穩定性的監控、日誌的管理、請求的分析與挖掘等。

        如果流量持續增長,或者是業務持續的擴展,上述的架構可能又將面臨挑戰。比如,多人開發常常出現版本衝突;對於數據庫的更新量變大;一個表裏面的記錄數已經超過千萬甚至過億等等。

        怎麼解決呢?還記得我們之前介紹過一個CAP理論嘛?三要素裏面有一個東東叫:分區容忍性(Partition tolerance)。其實,這個就是我們接下來解決問題的基礎:切分!

        一、從數據流向來看,切分包括:請求的切分、邏輯的切分、數據的切分。

        數據的切分:將不同的數據放到不同的庫中,將原來的單一的一個庫,切分成多個庫。

        邏輯的切分:將不同的業務邏輯拆分成多份代碼,用不同的代碼管理路徑來管理(如svn目錄)。

        請求的切分:將不同的邏輯請求分流到不同的機器上。比如:圖片請求、視頻請求、註冊請求等。

 

        二、從數據組織來看,切分包括:水平切分、垂直切分。

        數據庫的變大通常是朝着兩個方向來進行的,一個是功能增加,導致表結構橫向擴展;一個是提交數據持續增多,導致數據庫表裏的數據量持續縱向增加。




 

        數據量變大以後,單機性能會下降很明顯,因此我們需要在合適的時候對數據進行切分(這個我沒有太深入的研究過相關數據庫的最合適的切分點,只是從經驗上來講,單表的字段數控制在20個以內,記錄數控制在5千萬以內會比較好些)。

        垂直切分和水平切分,其實是挺糾結的兩個詞。我之前對這兩個詞經常搞混。後來自己畫了個圖,就很直接明瞭了。

 

        水平切分:


 


        水平切分就是因爲記錄數太多了,需要橫着來一刀,將原來一張表裏面的數據存入到多張表中,用於減少單張表裏的數據量。

 

        垂直切分:




        垂直切分就是因爲業務邏輯需要的字段太多,需要豎着來一刀,將原來放在一張表裏的所有字段,拆分成多張表,通過某一個Key來做關聯(如關係數據庫中的外鍵),從而避免大表的產生。

 

        (筆記本馬上沒電了,加上該做午飯了。暫時先到這兒吧。^_^)

        好了,有了上述的基礎以後,我們再來看實際問題如何來解決。

        假設,現在我們有一個博客網站,這個網站擁有多個功能,如:圖片、博客、用戶信息等的插查刪改操作。而現在博客數據膨脹比較厲害。

        首先,我們從數據流向來看,用戶訪問博客、圖片、用戶信息等這幾個邏輯沒有直接的耦合,對應的業務邏輯關聯也很少。

        因此,我們第一步從入口上就可以把三者分開。最簡單的方式就是通過域名來切分,比如:img.XXX.com、blog.XXX.com、user.XXX.com。然後通過不同的WebServer來接收這些請求。

        第二步,我們的業務邏輯代碼,很明顯可以將這些邏輯分開(從部署上分開)。一部分專門處理圖片的請求,如ImageUploadAction/ImageDisplayAction/ImageDeleteAction,一部分專門處理博客請求,如:BlogDisplayAction/BlogDeleteAction,一部分專門處理用戶相關請求,如:UserModifyAction/UserDisplayAction等等。

        第三步,從數據庫存儲上,將三者剝離開。簡單的就是分成三個不同的庫。

        這樣,從數據流向上,我們就按不同的功能,將請求進行了拆分。

 

        其次,從數據存儲上來看,由於博客數據量增長比較快,我們可以將博客的數據進行水平的拆分。拆分方法很多,比如常用的:

        1、按區間拆分。假定我們用blog_id作爲Key,那麼我們可以每1千萬,做一次切分。比如[1,1kw)、[1kw,2kw)等等。這樣做的好處就是可以不斷的增長。但訪問可能會因爲博客新舊的原因,集中到最新的幾個庫或表中。另外,要根據數據的增長動態的建表。

        2、按取模拆分。比如我們預估我們的blog_id最多不超過10億,如果每張表裏面我們預估存入1千萬的數據,那麼我們就需要100張表(或庫)。我們就可以按照blog_id % 100 這樣來做切分。這樣做的好處是簡單,表在一開始就全部建立好了。且每個表或者庫的訪問都比較均勻。但問題就是,如果數據持續擴張,超出預期,那麼擴展性就成爲最主要的問題。

        3、其他還有一些衍生的方式,比如按Hash值切分等等,大多大同小異。

 

        這樣一來,我們通過訪問模式、數據組織等多個維度的拆分以後,我們單機能夠提供服務的能力就變的比較強悍了。具體的架構如下圖。





        上述結構看似比較完美,但是在實際的使用中可能會遇到以下幾個問題:

        1、業務關聯問題。多個Service之間不可能沒有任何關聯,如果出現關聯,怎麼辦?特別是如果是提交的信息要修改多個業務的數據的時候,這個會比較頭疼。

        2、服務運維問題。這樣拆分以後,隨着機器數量的膨脹,對於機器的管理將會變的愈發的困難。這個問題直接會影響到整體架構的設計。面向運維的設計是架構設計中必須要考慮的重要因素。

        3、還有一個問題是我們WebServer始終是單機的,如果出現宕機等問題,那影響將是致命的。這個我們還沒有解決。

        這些問題都會在接下來的部分詳細來解決。


發佈了42 篇原創文章 · 獲贊 171 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章