帶你深入瞭解Web網站資料庫的分布儲存

來源:互聯網
上載者:User

作者:finalbsd
原載: http://www.sanotes.net/html/y2009/358.html

在Web 2.0時代,網站將會經常面臨著快速增加的訪問量,但是我們的應用如何滿足使用者的訪問需求,而且基本上我們看到的情況都是效能瓶頸都是在資料庫上,這個不怪資料庫,畢竟要滿足很大訪問量確實對於任何一款資料庫都是很大的壓力,不論是商務資料庫Oracle、MS sql Server、DB2之類,還是開源的MySQL、PostgreSQL,都是很大的挑戰,解決的方法很簡單,就是把資料分散在不同的資料庫上(可以是硬 件上的,也可以是邏輯上的),本文就是主要討論如何資料庫分散儲存的的問題。

目前主要分布儲存的方式都是按照一定的方式進行切分,主要是垂直切分(縱向)和水平切分(橫向)兩種方式,當然,也有兩種結合的方式,達到更貼切的切分粒度。

1. 垂直切分(縱向)資料是資料庫切分按照網站業務、產品進行切分,比如使用者資料、部落格文章資料、照片資料、標籤資料、群組資料等等每個業務一個獨立的資料庫或者資料庫伺服器。

2. 水平切分(橫向)資料是把所有資料當作一個大產品,但是把所有的平面資料按照某些Key(比如使用者名稱)分散在不同資料庫或者資料庫伺服器上,分散對資料訪問的壓力,這種方式也是本文主要要探討的。

本文主要針對的的 MySQL/PostgreSQL 類的開來源資料庫,同時平台是在 linux/FreeBSD,使用 php/Perl/Ruby/Python 等指令碼語言,搭配 Apache/Lighttpd 等Web伺服器 的平台下面的Web應用,不討論靜態檔案的儲存,比如視頻、圖片、CSS、JS,那是另外一個話題。

說明:下面將會反覆提到的一個名次“節點”(Node),指的是一個資料庫節點,可能是物理的一台資料庫伺服器,也可能是一個資料庫,一般情況是指一台資料庫伺服器,並且是具有 Master/Slave 結構的資料庫伺服器,我們查看一片,瞭解這樣節點的架構:

一、基於散列的分布方式

1. 散列方式介紹

基於散列(Hash)的分布儲存方式,主要是依賴主要Key和散列演算法,比如以使用者為主的應用主要的角色就是使用者,那麼做Key的就可以是使用者ID或者是用 戶名、郵件地址之類(該值必須在網站中隨處傳遞),使用這個唯一值作為Key,通過對這個Key進行散列演算法,把不同的使用者資料分散在不同的資料庫節點 (Node)上。

我們通過簡單的執行個體來描述這個問題:比如有一個應用,Key是使用者ID,擁有10個資料庫節點,最簡單的散列演算法是我們 使用者ID數模以我們所有節點數,餘數就是對應的節點機器,演算法:所在節點 = 使用者ID % 總節點數,那麼,使用者ID為125的使用者所在節點:125 % 10 = 5,那麼應該在名字為5的節點上。同樣的,可以構造更為強大合理的Hash演算法來更均勻的分配使用者到不同的節點上。

2. 散列分布儲存方式的擴容

我們知道既然定義了一個散列演算法,那麼這些Key就會按部就班的分散到指定節點上,但是如果目前的所有節點不夠滿足要求怎麼辦?這就存在一個擴容的問題,擴容首當其衝的就是要修改散列演算法,同時資料也要根據散列演算法進修遷移或者修改。

(1) 遷移方式擴容:修 改散列演算法以後,比如之前是10個節點,現在增加到20個節點,那麼Hash演算法就是[模20],相應的存在一個以前的節點被分配的資料會比較多,但是新 加入的節點資料少的不平衡的狀態,那麼可以考慮使用把以前資料中的資料按照Key使用新的Hash演算法進行運算出新節點,把資料移轉到新節點,缺點但是這 個成本相應比較大,不穩定性增加;好處是資料比較均勻,並且能夠充分利用新舊節點。

(2) 充分利用新節點:增 加新節點以後,Hash演算法把新加入的資料全部Hash到新節點上,不再往舊節點上分配資料,這樣不存在遷移資料的成本。優點是只需要修改Hash演算法, 無須遷移資料就能夠簡單的增加節點,但是在查詢資料的時候,必須使用考慮到舊Key使用舊Hash演算法,新增加的Key使用新的Hash演算法,不然無法查 找到資料所在節點。缺點很明顯,一個是Hash演算法複雜度增加,如果頻繁的增加新節點,演算法將非常複雜,無法維護,另外一個方面是舊節點無法充分利用資源 了,因為舊節點只是單純的保留舊Key資料,當然了,這個也有合適的解決方案。

總結來說,散列方式分布資料,要新增節點比較困難和繁瑣,但是也有很多適合的場合,特別適合能夠預計到未來資料量大小的應用,但是普遍 Web2.0 網站都無法預計到資料量。

二、基於全域節點分配方式

1. 全域節點分配方式介紹

就是把所有Key資訊與資料庫節點之間的映射關聯性記錄下來,儲存到全域表中,當需要訪問某個節點的時候,首先去全域表中尋找,找到以後再定位到相應節點。全域表的儲存方式一般兩種:

(1) 採用節點資料庫本身(MySQL/PostgreSQL)儲存節點資訊,能夠遠端存取,為了保證效能,同時配合使用 Heap(MEMORY) 記憶體表,或者是使用 Memcached 緩衝方式來緩衝,加速節點尋找

(2) 採用 BDB(BerkeleyDB)、DBM/GDBM/NDBM 這類本地檔案資料庫,基於 key=>value 雜湊資料庫,尋找效能比較高,同時結合 APC、Memcached 之類的緩衝加速。

第 一種儲存方式是容易查詢(包括遠程查詢),缺點是效能不太好(這個是所有關係型資料庫的通病);第二種方式的有點是本地查詢速度很快(特別是hash型數 據庫,時間複雜度是O(1),比較快),缺點是無法遠程使用,並且無法在多台機器中間同步共用資料,存在資料一致的情況。

我們來描述實施 大概結構:假如我們有10個資料庫節點,一個全域資料庫用於儲存Key到節點的映射資訊,假設全域資料庫有一個表叫做 AllNode ,包含兩個欄位,Key 和 NodeID,假設我們繼續按照上面的案例,使用者ID是Key,並且有一個使用者ID為125的使用者,它對應的節點,我們查詢表獲得:

Key NodeID
13 2
148 5
22 9
125 6

可以確認這個使用者ID為125的使用者,所在的節點是6,那麼就可以迅速定位到該節點,進行資料的處理。

我們來查看一下分布儲存結構圖:

2. 全域節點分布方式的擴容

全域節點分配方式同樣存在擴容的問題,不過它早就考慮到這個問題,並且這麼設計就是為了便於擴容,主要的擴容方式是兩種:

(1) 通過節點自然增加來分配Key到節點的映射擴容

這 種是最典型、最簡單、最節約機器資源的擴容方式,大致就是按照每個節點分配指定的資料量,比如一個節點儲存10萬使用者資料,第一個節點儲存0-10w使用者 資料,第二個節點儲存10w-20w使用者資料,第三個節點儲存20w-30w使用者資訊,依此類推,使用者增加到一定資料量就增加節點伺服器,同時把Key分 配到新增加的節點上,映射關聯性記錄到全域表中,這樣可以無限的增加節點。存在的問題是,如果早期的節點使用者訪問頻率比較低,而後期增加的節點使用者訪問頻率 比較高,則存在節點伺服器負載不均衡的現象,這個也是可以想方案解決的。

(2) 通過機率演算法來映射Key到節點的的擴容

這種方式是在既然有的節點基礎上,給每個節點設定一個被分配到Key的機率,然後分配Key的時候,按照每個節點被指定的機率進行分配,如果每個節點平均的資料容量超過了指定的百分比,比如50%,那麼這時候就考慮增加新節點,那麼新節點增加Key的機率要大於舊節點。

一般情況下,對於節點的被分配的機率也是記錄在資料庫中的,比如我們把所有的機率為100,共有10個節點,那麼設定每個節點被分配的資料的機率為10,我們查看資料表結構:

NodeID Weight
1 10
2 10
3 10

現在新加入了一個 節點,新加入的節點,被分配Key的幾率要大於舊節點,那麼就必須對這個新加入的節點進行機率計算,計算公式:10х+у=100, у>х,得出:у{10…90},х{1…9},x是單箇舊節點的機率,舊節點的每個節點的機率是一樣的,y是新節點的機率,按照這個計算 公式,推算出新節點y的機率的範圍,具體按照具體不同應用的機率公式進行計算。

三、存在的問題

現在我們來分析和解決一下我們上面兩種分布儲存方式的存在的問題,便於在實際考慮架構的時候能夠避免或者是融合一些問題和缺點。

1. 散列和全域分配方式都存在問題

(1) 散列方式擴容不是很方便,必須修改散列演算法,同時可能還需要對資料進行遷移,它的優點是從Key定位一個節點非常快,O(1)的時間複雜度,而且基本不需要查詢資料庫,節約回應時間。

(2) 全域分配方式存在的問題最明顯的是單點故障,全域資料庫down掉將影響所有應用。另外一個問題是查詢量大,對每個Key節點的操作都必須經過全域資料庫,壓力很大,優點是擴容方便,增加節點簡單。

2. 分布儲存帶來的搜尋和統計問題

(1) 一般搜尋或統計都是對所有資料進行處理,但因為拆分以後,資料分散在不同節點機器上,無法進行全域尋找和統計。解決方案一是對主要的基礎資料存放區在全域表中,便於尋找和統計,但這類資料不宜太多,部分核心資料。

(2) 採用站內搜尋引擎來索引和記錄全部資料,比如採用 Lucene 等開源索引系統進行所有資料的索引,便於搜尋。 對於統計操作可以採用後台非即時統計,可採用遍曆所有節點的方式,但效率低下。

3. 效能最佳化問題

(1) 散列演算法,節點機率和分配等為了提高效能都可以使用編譯語言開發,做成lib或者是所有php擴充形式。

(2) 對於採用 MySQL 的情況,可以採用自訂的資料庫連接池,採用 Apache Module 形式載入,能夠自由定製的採用各種串連方式。

(3) 對於全域資料或都頻繁訪問的資料,可以採用APC、Memcache、DBM、BDB、共用記憶體、檔案系統等各種方式進行緩衝,減少資料庫的訪問壓力。

(4) 採用資料本身的強大處理機制,比如 MySQL5 的表分區或者是 MySQL5 的Cluster 。另外建議在實際架構中採用InnoDB表引擎作為主要儲存引擎,MyISAM作為一些日誌、統計資料等場合,不論在安全、可靠性、速度都有保障。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.