--------本文是同事在程序員發(fā)表的文章,記錄下來。
【摘要】 本文提出了一種通過引入內(nèi)存數(shù)據(jù)庫層,建立兩層多分區(qū)分布式數(shù)據(jù)庫架構。此方案用于解決海量高并發(fā)系統(tǒng)的數(shù)據(jù)存儲和訪問問題,尤其適用于電子商務等數(shù)據(jù)模型復雜且業(yè)務復雜的互聯(lián)網(wǎng)站。
這些年互聯(lián)網(wǎng)站發(fā)展迅猛,為應對海量數(shù)據(jù)下的高并發(fā)訪問,產(chǎn)生了各種分布式架構設計思想,例如Key-Value引擎,數(shù)據(jù)分區(qū)等。而對于電子商務類網(wǎng)站,海量數(shù)據(jù)問題還有一個重要特點,就是數(shù)據(jù)結構化及數(shù)據(jù)之間的關聯(lián),淘寶如此,阿里巴巴也是如此,這是與社區(qū)、視頻、 博客等互聯(lián)網(wǎng)站的顯著差異。
NoSQL、Key-Value 引擎如BigTable、Cassendra等在很多大型網(wǎng)站被采用,很好的解決了海量數(shù)據(jù)存儲和訪問問題。而對于電子商務類網(wǎng)站,Key-Value和NoSQL并不是解決此問題的靈丹妙藥。最多它們僅能用于一些數(shù)據(jù)模型較為簡單的應用。
原因有兩個方面:
1)數(shù)據(jù)模型復雜
淘寶和阿里巴巴的會員、寶貝、供求、訂單等核心實體數(shù)據(jù)模型復雜,屬性個數(shù)幾十到上百個。例如:會員(Member)就包含基本信息、聯(lián)系、工商、賬戶等多個域的信息;另外,核心實體之間,外圍實體與核心實體之間還存在復雜的關聯(lián)。
2)業(yè)務復雜:
模型的復雜源于業(yè)務和邏輯的復雜。電子商務網(wǎng)站大量查詢場景是結構化查詢,例如:
在淘寶上查詢“賣家在江浙滬,價格在50-200元的男士T恤”,
在阿里巴巴上“列出某個會員所有待發(fā)貨的訂單”
這類查詢(當然,阿里巴)主要針對多個非主鍵字段, 即便對于BigTable、Cassandra 這樣的基于Column的Key-Value數(shù)據(jù)庫,其簡單的Query API還無法勝任此類需求。 因此在阿里巴巴和淘寶,Oracle、MySQL 等關系數(shù)據(jù)庫將仍然扮演重要角色。
引入K-V引擎等非關系數(shù)據(jù)庫無非是要解決海量數(shù)據(jù)在高并發(fā)環(huán)境下的高效讀寫問題,最大程度在可靠的持久化(Durable)與高訪問性能 (Performance) 之間選擇一個平衡點。在高度結構化系統(tǒng)中,同樣的考慮驅(qū)使我們需要考慮另外的解決方案。
目前一種通行的做法是 MySQL 讀寫分離式集群,1個或少數(shù)Master寫,多數(shù)Slave讀,Master與Slave進行變更數(shù)據(jù)的同步。首先,這種方案經(jīng)過大量的實踐,可靠且可行。
然而,直接向DB執(zhí)行寫操作,仍然比較耗時(參見表1,表2),數(shù)據(jù)復制,也可能存在不一致延時的情形。是否還有更快的方案?
可靠的持久化指數(shù)據(jù)存儲到磁盤等設備上。圖1展示了傳統(tǒng)磁盤數(shù)據(jù)庫的基本訪問模式。
圖1
拋開持久化的可靠性,即數(shù)據(jù)可以先不存儲到磁盤上(Disk),內(nèi)存存儲的性能遠高于磁盤存儲。下表展示了針對Oracle和Altibase所做的性能對比,后者在插入和查詢上性能是Oracle的5-7倍。
數(shù)據(jù)庫 | 測試結果 | TPS |
Oracle | 203秒 | 246條/秒 |
Altibase | 28.32秒 | 1785條/秒 |
表1. Oracle、Altibase性能對比 -插入5萬條 【7】
數(shù)據(jù)庫 | 測試結果 | TPS |
Oracle | 885秒 | 112條/秒 |
Altibase | 170秒 | 588條/秒 |
表2 Oracle、Altibase性能對比 – 關聯(lián)查詢10萬條【7】
由此可見:Pm >>> Pd
(Pm - 內(nèi)存數(shù)據(jù)庫讀寫性能, Pd - 磁盤數(shù)據(jù)庫讀寫性能)
結合前面分析的模型復雜性和業(yè)務復雜性原因,關系數(shù)據(jù)庫(RDBMS)必須采用。因此,這兩點考慮可以推導出另一個解決思路:內(nèi)存型關系數(shù)據(jù)庫。
磁盤型關系數(shù)據(jù)庫 | Key-Value引擎 | 內(nèi)存型關系數(shù)據(jù)庫 | |
功能 -結構化操作和查詢等 | Y | N | Y |
性能 | 低 | 高 | 高 |
表3. DB選型對比分析
這個方案里,我們可以將內(nèi)存先看做一種“磁盤”,讀寫操作都針對內(nèi)存數(shù)據(jù)庫進行,不再直接與磁盤數(shù)據(jù)庫交互,這較好的避免了單純MySQL 讀寫分離架構存在的時間延遲和一致性問題。如下圖所示:
圖2
數(shù)據(jù)最終還是要存儲到磁盤(Disk)上,內(nèi)存數(shù)據(jù)庫中的數(shù)據(jù)變化需要復制到與磁盤數(shù)據(jù)庫上。這時,從內(nèi)存向磁盤復制數(shù)據(jù)的過程可以看作原始寫操作的異步操作,顯然,異步操作使得前端的寫操作顯得更快。如下圖所示:
圖3
在事務型(OLTP)系統(tǒng)中,內(nèi)存數(shù)據(jù)庫中在啟動時需要和磁盤數(shù)據(jù)庫保持一致。 因此,內(nèi)存數(shù)據(jù)庫需要有相同的庫表定義;并且在第一啟動時,將所需庫表數(shù)據(jù)加載到內(nèi)存數(shù)據(jù)庫中。
5. 內(nèi)存數(shù)據(jù)庫集群化
目前,經(jīng)典的MySQL集群,通過讀寫分離,水平切分,實現(xiàn)海量數(shù)據(jù)存儲。為應對海量數(shù)據(jù)存儲,內(nèi)存數(shù)據(jù)庫同樣需要做集群。垂直和水平切分策略,可用性策略與MySQL集群架構設計基本相同。如下圖所示,其中 Ameoba 是分布式數(shù)據(jù)庫代理,它進行數(shù)據(jù)路由等控制。
唯一的不同是,由于內(nèi)存數(shù)據(jù)庫的高性能,可以不再進行讀寫分離設計。
圖4
接第4節(jié)的分析,內(nèi)存數(shù)據(jù)最終仍需要持久化到磁盤。這里需要一種混合分區(qū)(Hybrid Shard)來解決。即原來一個MySQL節(jié)點承擔的一個水平分區(qū),將由一個內(nèi)存數(shù)據(jù)庫節(jié)點和一個MySQL節(jié)點共同組成。
H-Shard = MDB + MySQL.
這種數(shù)據(jù)庫架構將形成由兩級數(shù)據(jù)庫(2LDB),混合分區(qū)構成的集群。的如下圖所示:
圖5
常見的內(nèi)存數(shù)據(jù)庫產(chǎn)品包括商業(yè)版和免費版兩類。商業(yè)版如:Altibase,Timesten,Berkley DB等。他們在電信,金融,證券等高性能計算應用中運用較為廣泛。商業(yè)版功能強大,然而,價格比較昂貴,不適合目前“廉價PC+免費軟件”的架構搭建思想。
筆者曾就職與中國移動系統(tǒng)提供商,其中計費、運營等系統(tǒng)就運用Timesten提供高性能運算,但還主要用于高頻度小數(shù)據(jù)計算,如計費批價,優(yōu)惠計算,信控等,采用單節(jié)點模式使用。
開源領域產(chǎn)品主要有H2,HsqlDB,Derby等。在混合分區(qū)架構中,內(nèi)存數(shù)據(jù)庫將承擔OLTP的職責,因此除了讀寫性能外,功能的完備,事務等都需要作為優(yōu)先評估的因素。
通過引入內(nèi)存數(shù)據(jù)庫作為中間持久層,再加入分布式架構以支撐海量數(shù)據(jù)訪問,這種架構設計頗具挑戰(zhàn)。最先而易見的情況就是新架構的復雜度,正如大規(guī)模MySQL集群架構誕生初始一樣。
我們以 H2 ,一個開源的高性能內(nèi)存數(shù)據(jù)庫為例說明:
1) 整合 Ameoba 與 H2
Ameoba 是分布式數(shù)據(jù)庫代理,它與 MySQL 整合已經(jīng)在阿里巴巴核心業(yè)務中成功運用。如果僅將數(shù)據(jù)庫節(jié)點看作一個存儲,MySQL Node 和 H2 Node 并無本質(zhì)區(qū)別。JDBC驅(qū)動,DB切分,路由,皆由Ameoba 統(tǒng)一負責。
2) 異步持久化
每個邏輯混合分區(qū)= H2 + MySQL,誰來完成H2 中的數(shù)據(jù)變更異步寫入 MySQL?
比較好的方案是內(nèi)存數(shù)據(jù)庫提供實時增量的復制器(Replicator) ,例如:基于聯(lián)機日志復制的雙機熱備機制。AltiBase 等產(chǎn)品就提供了此功能。
3)高可用性
內(nèi)存數(shù)據(jù)庫一旦崩潰,數(shù)據(jù)不復存在。因此首先要做到數(shù)據(jù)快速異步寫入MySQL作持久化存儲。同時要有健壯的容錯和Failover機制,保證一個H2節(jié)點崩潰,同一邏輯分區(qū)中的替補H2節(jié)點立即頂替工作。
一種方案是分布式數(shù)據(jù)庫代理如 Ameoba 來解決,例如:每個Shard,H2至少設2個節(jié)點,采用Primary-Secondary模式,如圖6所示:
圖6
另一種方案是前面提到的內(nèi)存數(shù)據(jù)庫實時復制功能。
雖然有些內(nèi)存DB如H2自身能支持內(nèi)存,磁盤兩級存儲,但其自身提供的磁盤存儲和訪問方案可靠性不如 MySQL。因此,使用內(nèi)存式Primary-Secondary 模式更為可行。
4)分布式事務
數(shù)據(jù)庫切分架構帶來分布式事務問題,對一些事務要求較高的場景,這頗具挑戰(zhàn)。Ameoba 目前還在解決中。Ameoba + H2組合面臨同樣的挑戰(zhàn)。
目前一種比較一致意見和做法就是冷處理——盡量不用事務。 一致性問題根據(jù)業(yè)務的特點,采用數(shù)據(jù)訂正來解決;個別業(yè)務使用補償事務。因為目前大部分應用,即便是核心業(yè)務,對事務的要求也不高。
1) 多種數(shù)據(jù)切分模式
在一個大型互聯(lián)網(wǎng)站,不同的應用和數(shù)據(jù)需要做不同的處理。在總體垂直切分模式基礎上,選擇數(shù)據(jù)量大的功能進行水平切分,例如:供求、訂單、交易記錄。
2)數(shù)據(jù)緩存(Data Cache)
雖然內(nèi)存數(shù)據(jù)庫層(MDB)能更高效支撐交易型數(shù)據(jù)庫,特別是應對結構化應用及復雜查詢服務,但對高頻度的查詢(Query)和實體查找(Find),Key-Value緩存仍然是一項必要的設計。Cache能提供更高的查詢速度,并減少對MDB的訪問壓力,特別是讀寫密集的高并發(fā)場景。因為這個架構中,內(nèi)存數(shù)據(jù)庫仍然作為一種存儲Store,而不是Cache。
圖7
上圖展示了,MDB層之上還需要DCL層來提供高性能緩存服務。
本文提出了一種通過引入內(nèi)存數(shù)據(jù)庫層,并建立兩層,多分區(qū)的分布式數(shù)據(jù)庫架構。此方案用于解決海量高并發(fā)系統(tǒng)的高性能數(shù)據(jù)存儲和訪問問題,尤其是電子商務類等業(yè)務復雜的互聯(lián)網(wǎng)站。其核心思想是:
1)高性能:是通過內(nèi)存數(shù)據(jù)庫提供高性能關系數(shù)據(jù)庫存取服務,這是此架構的最主要目標;
2)持久化:通過兩級數(shù)據(jù)庫及異步寫完成持久化;
3)海量數(shù)據(jù)支撐:通過垂直和水平分區(qū)實現(xiàn)海量數(shù)據(jù)的支撐;
4)高可用性:在Ameoba基礎上,通過主備節(jié)點進一步實現(xiàn)MDB的高可用性;二級磁盤數(shù)據(jù)庫可以實現(xiàn)數(shù)據(jù)的快速恢復。
【參考資料】
1. 阿里巴巴 Ameoba分布式數(shù)據(jù)庫設計和實踐
2. 岳旭強, 《淘寶網(wǎng)架構師岳旭強的年度展望》, http://www.infoq.com/cn
3. 廣東移動BOSS2.0分布式數(shù)據(jù)庫架構方案,計費系統(tǒng)設計和實踐.
4. Cassandra,http://cassandra.apache.org/
5. Oracle, Timesten 官方文檔, http://www.oracle.com/timesten/index.html
6. Fenng,《Oracle 內(nèi)存數(shù)據(jù)庫-TimesTen》, http://www.dbanotes.net/database/oracle_timesten.html
7. 張澄,包文菖,《內(nèi)存數(shù)據(jù)庫在BSS賬務處理中的應用》,《計費&OSS世界》,http://database.51cto.com/art/200612/36973.htm
8. Titan,《常用內(nèi)存數(shù)據(jù)庫介紹》,http://titan.iteye.com/blog/364345
9. Ricky Ho, 《NoSQL的模式》,程序員2010-1;《NoSQL 數(shù)據(jù)庫的查詢處理》,程序員2010-2
問題:
這個模型是有很多可用場景的,樓主關于電子商務網(wǎng)站與SNS博客等網(wǎng)站的分析是很合理的,NOSQL在很多電子商務的場景下應用有局限,我們在搞國際交易的時候確實也遇到,特別是很多運營類的活動場景中,業(yè)務邏輯糾結的很。
以下有幾個的疑問探討下:
1) 高性能:是通過內(nèi)存數(shù)據(jù)庫提供高性能關系數(shù)據(jù)庫存取服務,這是此架構的最主要目標;
~~~~RMDB的工作讓Ameoba 這個分布式數(shù)據(jù)庫代理在處理了。我認為最終的瓶頸會是AMEOBA,AMEOBA就是一個中心,擴展性怎么樣,維護成本怎么樣?為了實現(xiàn)切分和路由,很多數(shù)據(jù)還是依賴DB類的設備吧?
2) 持久化:通過兩級數(shù)據(jù)庫及異步寫完成持久化;
~~~~~兩級數(shù)據(jù)庫的數(shù)據(jù)一致性怎么保證?是最終一致性嗎?同一個數(shù)據(jù)會復制幾片?數(shù)據(jù)冗余策略可調(diào)嗎?不同的應用場景對CPA的需求是不同,有些場景對數(shù)據(jù)一致性要求嚴一些,比如交易過程。
3) 海量數(shù)據(jù)支撐:通過垂直和水平分區(qū)實現(xiàn)海量數(shù)據(jù)的支撐;
~~~~~如果需要通過拆分來實現(xiàn)數(shù)據(jù)擴展,那么海量的級別還是有很多約束的;加一臺機器是不是要停機?重新分配拆分策略時所有機器的數(shù)據(jù)是不是要REOLAD?
4)高可用性:在Ameoba基礎上,通過主備節(jié)點進一步實現(xiàn)MDB的高可用性;二級磁盤數(shù)據(jù)庫可以實現(xiàn)數(shù)據(jù)的快速恢復。
~~~~~主備節(jié)點之間異步方式實現(xiàn) 數(shù)據(jù)同步嗎?以后擴展數(shù)據(jù)或重新拆分數(shù)據(jù)的時候,主備節(jié)點都要重新劃分數(shù)據(jù),會不會需要停機?備機只有主機宕機的時候才啟用吧?讀請求還是無法分散到備機上。平時備機的利用率是否有辦法提升?
回答:
Q1.數(shù)據(jù)路由層的運維成本。路由的實現(xiàn)方式?
Q2.數(shù)據(jù)節(jié)點層的運維成本。
A1.路由層跟普通的java應用部署類似,是一個多臺pc組成的集群,路由軟件的升級、機器的維護都跟集群維護類似,可以單個單個的處理,而且擴展非常方便。
路由的實現(xiàn)不是查路由表,不需要保存到數(shù)據(jù)庫里,而是用簡單的哈希算法來路由。
這樣路由層的每個節(jié)點就沒有持久化的數(shù)據(jù),也就是無狀態(tài)的。
A2.數(shù)據(jù)節(jié)點間的切換和維護有路由層擋在前面,所以對應用來說數(shù)據(jù)節(jié)點層的運維幾乎是透明的。
我們現(xiàn)在采用的是一種簡化了的一致哈希算法,所以增加數(shù)據(jù)節(jié)點的時候,對數(shù)據(jù)的遷移很少。
Q3.對一致性要求高的場景,雙層數(shù)據(jù)結構能支持嗎?
Q4.備機能否利用起來分擔部分讀的壓力。
A3.不能,要保證一致性就要事務,數(shù)據(jù)就要同時寫,不能異步寫,要事務就架構復雜而且還會有很大延時,幾乎沒有什么寫業(yè)務能忍受這樣的延時。
A4.不能,數(shù)據(jù)從主機到備機是有延時的,秒級到分鐘級不等,幾乎沒有什么業(yè)務能忍受這樣的延時。
當然也有業(yè)務能忍受,就是類似中文站和國際站的【數(shù)據(jù)管家】業(yè)務,數(shù)據(jù)都是報表類型的,每天夜間生成,白天提供只讀服務,這樣的業(yè)務完全可以用備機來分擔部分壓力,甚至主備之間直接做負載均衡。
聯(lián)系客服