1. 程式人生 > >高並發系統數據庫設計

高並發系統數據庫設計

部分 主從數據庫 數據庫拆分 數量級 復雜 分拆 站點 擴展性 數據分區

在WEB網站的規模從小到大不斷擴展的過程中,數據庫的訪問壓力也不斷的增加,數據庫的架構也需要動態擴展,在數據庫的擴展過程基本上包含如下幾步,每一個擴展都可以比上一步驟的部署方式的性能得到數量級的提升。

1、WEB應用和數據庫部署在同一臺服務器上

一般的小規模的網站采用這種方式,用戶量、數據量、並發訪問量都比較小,否則單臺服務器無法承受,並且在遇到性能瓶頸的時候升級硬件所需要的費用非常高昂,在訪問量增加的時候,應用程序和數據庫都來搶占有限的系統資源,很快就又會遇到性能問題。



2、WEB應用和數據庫部署在各自獨立的服務器上

web應用和數據庫分開部署,WEB應用服務器和數據庫服務器各司其職,在系統訪問量增加的時候可以分別升級應用服務器和數據庫服務器,這種部署方式是一般小規模網站的典型部署方式。在將應用程序進行性能優化並且使用數據庫對象緩存策略的情況下,可以承載較大的訪問量,比如2000用戶,200個並發,百萬級別的數據量。



3、數據庫服務器采用集群方式部署(比如Oracle的一個數據庫多個實例的情況)

數據庫集群方式能承擔的負載是比較大的,數據庫物理介質為一個磁盤陣列,多個數據庫實例以虛擬IP方式向外部應用服務器提供數據庫連接服務。這種部署方式基本上可以滿足絕大多數的常見WEB應用,但是還是不能滿足大用戶量、高負載、數據庫讀寫訪問非常頻繁的應用。



4、數據庫采用主從部署方式

在面向大眾用戶的博客、論談、交友、CMS等系統中,有上百萬的用戶,有上千萬的數據量,存在眾多的數據庫查詢操作,也有較多的數據庫寫操作,並且在多數情況下都是讀操作遠大於寫操作的。在這個時候,假如能將數據庫的讀寫操作分離的話,對於系統來講是一個很大的提高啦。數據庫的主從部署方式就走到我們面前啦。

主從復制:

幾乎所有的主流數據庫都支持復制,這是進行數據庫簡單擴展的基本手段。下面以Mysql為例來說明,它支持主從復制,配置也並不復雜,只需要開啟主服務器上的二進制日誌以及在主服務器和從服務器上分別進行簡單的配置和授權。Mysql的主從復制是一句主服務器的二進制日誌文件進行的,主服務器日誌中記錄的操作會在從服務器上重放,從而實現復制,所以主服務器必須開啟二進制日誌,自動記錄所有對於主數據庫的更新操作,從服務器再定時到主服務器取得二進制日誌文件進行重放則完成了數據的復制。主從復制也用於自動備份。

讀寫分離:

為保證數據庫數據的一致性,我們要求所有對於數據庫的更新操作都是針對主數據庫的,但是讀操作是可以針對從數據庫來進行。大多數站點的數據庫讀操作比寫操作更加密集,而且查詢條件相對復雜,數據庫的大部分性能消耗在查詢操作上了。
主從復制數據是異步完成的,這就導致主從數據庫中的數據有一定的延遲,在讀寫分離的設計中必須要考慮這一點。以博客為例,用戶登錄後發表了一篇文章,他需要馬上看到自己的文章,但是對於其它用戶來講可以允許延遲一段時間(1分鐘/5分鐘/30分鐘),不會造成什麽問題。這時對於當前用戶就需要讀主數據庫,對於其他訪問量更大的外部用戶就可以讀從數據庫。

數據庫反向代理:

在讀寫分離的方式使用主從部署方式的數據庫的時候,會遇到一個問題,一個主數據庫對應多臺從服務器,對於寫操作是針對主數據庫的,數據庫個數是唯一的,但是對於從服務器的讀操作就需要使用適當的算法來分配請求啦,尤其對於多個從服務器的配置不一樣的時候甚至需要讀操作按照權重來分配。
對於上述問題可以使用數據庫方向代理來實現。就像WEB方向代理服務器一樣,MYsql Proxy同樣可以在SQL語句轉發到後端的Mysql服務器之前對它進行修改。

5、數據庫垂直分割

主從部署數據庫中,當寫操作占了主數據庫的CPU消耗的50%以上的時候,我們再增加從服務器的意義就不是很大了,因為所有的從服務器的寫操作也將占到CPU消耗的50%以上,一臺從服務器提供出來查詢的資源非常有限。數據庫就需要重新架構了,我們需要采用數據庫垂直分區技術啦。
最簡單的垂直分區方式是將原來的數據庫中獨立的業務進行分拆(被分拆出來的部分與其它部分不需要進行Join連接查詢操作),比如WEB站點的BLOG和論壇,是相對獨立的,與其它的數據的關聯性不是很強,這時可以將原來的的數據庫拆分為一個BLog庫,一個論壇庫,以及剩余的表所組成的庫。這三個庫再各自進行主從數據庫方式部署,這樣整個數據庫的壓力就分擔啦。
另外查詢擴展性也是采用數據庫分區最主要的原因之一。將一個大的數據庫分成多個小的數據庫可以提高查詢的性能,因為每個數據庫分區擁有自己的一小部分數據。假設您想掃描1億條記錄,對一個單一分區的數據庫來講,該掃描操作需要數據庫管理器獨立掃描一億條記錄,如果您將數據庫系統做成50個分區,並將這1億條記錄平均分配到這50個分區上,那麽每個數據庫分區的數據庫管理器將只掃描200萬記錄。

6、數據庫水平分割

在數據庫的垂直分區之後,假如我們的BLOG庫又再次無法承擔寫操作的時候,我們又該怎麽辦呢?數據庫垂直分區這種擴展方式又無能為力了,我們需要的是水平分區。
水平分區意味著我們可以將同一個數據庫表中的記錄通過特定的算法進行分離,分別保存在不同的數據庫表中,從而可以部署在不同的數據庫服務器上。很多的大規模的站點基本上都是主從復制+垂直分區+水平分區這樣的架構。水平分區並不依賴什麽特定的技術,完全是邏輯村面的規劃,需要的是經驗和業務的細分。
如何分區呢?對於大型的WEB站點來說,必須分區,並且對於分區我們沒有選擇的余地,對於那些頻繁訪問導致站點接近崩潰的熱點數據,我們必須分區。
在對數據分區的時候,我們必須要存在一個分區索引字段,比如USER_ID,它必須和所有的記錄都存在關系,是分區數據庫中的核心表的主鍵,在其它表中作為外鍵,並且在使用主鍵的時候,該主鍵不能是自增長的,必須是業務主鍵才可以。

余數分區:

我們可以將User_ID%10後的值為依據存入到不同的分區數據庫中,該算法簡單高效,但是在分區數據庫個數有變動的時候,整個系統的數據需要重新分布。

範圍分區:

我們可以將User_ID的範圍進行分區,比如1-100000範圍為一個分區數據庫,100001-200000範圍為一個分區數據庫,該算法在分區數據庫個數有變動的時候,系統非常有利於擴展,但是容易導致不同分區之間的壓力不同,比如老用戶所在的分區數據庫的壓力很大,但是新用戶的分區數據庫的壓力偏小。

映射關系分區:

將對分區索引字段的每個可能的結果創建一個分區映射關系,這個映射關系非常龐大,需要將它們寫入數據庫中。比如當應用程序需要知道User_id為10的用戶的BLOG內容在那個分區時,它必須查詢數據庫獲取答案,當然,我們可以使用緩存來提高性能。
這種方式詳細保存了每一個記錄的分區對應關系,所以各個分區有非常強的可伸縮性,可以靈活的控制,並且將數據庫從一個分區遷移到另一個分區也很簡單,也可以使各個分區通過靈活的動態調節來保持壓力的分布平衡。

--

來源:http://www.cnblogs.com/lihaozy/archive/2013/08/02/3231776.html

高並發系統數據庫設計