《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技术 > 设计应用 > 分布式应用层中间件的设计
分布式应用层中间件的设计
来源:微型机与应用2011年第5期
李文杰,周剑华
(武汉科技大学 计算机科学与技术学院,湖北 武汉 430065)
摘要: 针对如何在非分布式数据库管理系统中应用分布式特性,提出了分布式数据层中间件DDLM的设计方案。在数据持久化框架和JDBC之间引入一个分库分表的中间件,从而把数据拆分到多个数据库的多个表中,在用户看来这些数据仍然存在于一张表中,从而在应用层透明地解决了海量数据的读写问题。
Abstract:
Key words :

摘  要: 針對如何在非分布式數(shù)據(jù)庫管理系統(tǒng)中應(yīng)用分布式特性,提出了分布式數(shù)據(jù)層中間件DDLM的設(shè)計方案。在數(shù)據(jù)持久化框架和JDBC之間引入一個分庫分表的中間件,從而把數(shù)據(jù)拆分到多個數(shù)據(jù)庫的多個表中,在用戶看來這些數(shù)據(jù)仍然存在于一張表中,從而在應(yīng)用層透明地解決了海量數(shù)據(jù)的讀寫問題。
關(guān)鍵詞: 分布式數(shù)據(jù)層;邏輯表;物理表

 隨著互聯(lián)網(wǎng)應(yīng)用業(yè)務(wù)的高速增長,搜索引擎、電子商務(wù)、門戶網(wǎng)站等大型互聯(lián)網(wǎng)公司的網(wǎng)絡(luò)信息流量直線上升,日訪問量甚至突破億次大關(guān),從而產(chǎn)生了海量信息和對這些信息的海量讀寫,集中式數(shù)據(jù)庫越來越難以滿足互聯(lián)網(wǎng)公司對海量信息的高可靠性、高擴展性的需求。
 分布式數(shù)據(jù)庫通過對數(shù)據(jù)進行垂直分片和水平分片,讓數(shù)據(jù)存儲在多個數(shù)據(jù)庫中,能夠解決海量數(shù)據(jù)的存儲和管理問題。所謂垂直分片是把一個全局關(guān)系的屬性集分成若干子集,并在這些子集上作投影運算,每個投影稱為垂直分片。屬性集數(shù)目是一定的,垂直拆分只能適合一定規(guī)模的擴展,當(dāng)對每個垂直分片的訪問超過單數(shù)據(jù)庫所能承受的負(fù)載時,就需要水平分片。水平分片是按一定的條件把全局關(guān)系的所有元組劃分成若干不相交的子集,每個子集為關(guān)系的一個片段。
 目前市場上Oracle、DB2等商用分布式數(shù)據(jù)庫的價格昂貴,一般企業(yè)僅僅將商用分布式數(shù)據(jù)庫用來管理企業(yè)最核心的數(shù)據(jù),而非核心的數(shù)據(jù)則存放在PostgreSQL、MySql等開源數(shù)據(jù)庫中。然而大多數(shù)開源數(shù)據(jù)庫分布式功能不夠強大,甚至不具備分布式的功能。為了解決這個問題,本文提出了分布式數(shù)據(jù)層中間件的設(shè)計方案,在應(yīng)用層把數(shù)據(jù)垂直、水平拆分到多個數(shù)據(jù)庫、多張表中,使應(yīng)用層具備了分布式的功能,和底層數(shù)據(jù)庫是否具有分布式特性沒有關(guān)系,從而使底層的開源數(shù)據(jù)庫能夠通過分布式數(shù)據(jù)層中間件具有分布式的特性。
1 分布式數(shù)據(jù)層中間件的設(shè)計原理
 傳統(tǒng)的持久化框架是基于JDBC的,如JPA(Java Persistence API)、Hibernate和TopLink等。對象關(guān)系映射(ORM)框架是根據(jù)對象的屬性生成Sql語句,然后調(diào)用JDBC API完成數(shù)據(jù)的持久化操作。Ibatis是個JDBC模板,相當(dāng)于半自動化ORM映射工具,也是調(diào)用JDBC接口來完成對數(shù)據(jù)的持久化操作的。
 所有Java持久化框架對數(shù)據(jù)庫的持久化操作都是直接或者間接地調(diào)用JDBC API執(zhí)行Sql語句來完成對數(shù)據(jù)的CRUD操作,每條Sql語句通常只操作單數(shù)據(jù)庫。在持久化框架(如Hibernate)和JDBC之間設(shè)計一個分布式數(shù)據(jù)層中間件DDLM(Distributed Data Layer MiddleWare),DDLM層把業(yè)務(wù)邏輯層的每條Sql語句(下文記作邏輯Sql語句)按照垂直、水平拆分的策略解釋成多個Sql語句,解釋后的每條Sql語句(下文記作物理Sql語句)對一個數(shù)據(jù)源進行操作,從而一條邏輯Sql語句被解釋成多條物理Sql語句,因此DDLM具有分布式的特性。
 分布式數(shù)據(jù)層中間件的原理如圖1所示。圖中把持久化層分為四個子層:持久化框架、分布式數(shù)據(jù)層、JDBC、數(shù)據(jù)庫。例如:JPA把根據(jù)ORM映射規(guī)則生成的Sql語句交給分布式數(shù)據(jù)層,分布式數(shù)據(jù)層中間件把Sql語句解釋為多個物理Sql語句交給JDBC接口,JDBC接口完成對數(shù)據(jù)庫的CRUD操作。

 這樣分布式數(shù)據(jù)層就能夠完成原本只有分布式數(shù)據(jù)庫才能完成的垂直分片、水平分片、合并排序等分布式操作。用戶不需要使用新的管理工具,只需要利用原有數(shù)據(jù)庫的管理工具與分布式數(shù)據(jù)層中間件交互。該層把對多個物理數(shù)據(jù)庫的操作透明化。
2 分布式數(shù)據(jù)層中間件的設(shè)計方案
 在DDLM設(shè)計中,不需進行垂直分片。一個全局關(guān)系對應(yīng)一張數(shù)據(jù)庫表,這樣就能滿足應(yīng)用中的大多數(shù)需求。而且按照一個關(guān)系映射一張表的原則拆分,邏輯簡單清晰,簡化了數(shù)據(jù)庫模型的設(shè)計。DDLM的研究重點是對表的水平分片以及水平分片后產(chǎn)生的問題的解決。
 水平分片把關(guān)系模式R的記錄拆分到n(n≥1)個物理數(shù)據(jù)庫中,每個物理數(shù)據(jù)庫有m(m≥1)張數(shù)據(jù)表,模式R的記錄被路由到n×m張模式相同的物理數(shù)據(jù)庫表中。
水平分片后,記錄存在于不同的物理數(shù)據(jù)庫,隨之產(chǎn)生了兩個問題:查詢數(shù)據(jù)時需要合并并且排序、主鍵需要全局唯一生成。
2.1 分庫策略
 一個數(shù)據(jù)庫所能存放的表數(shù)目會受到文件系統(tǒng)的限制,有必要把一張邏輯表的數(shù)據(jù)拆分到多個物理數(shù)據(jù)庫中。為了實現(xiàn)此功能,在表模式中添加一個整數(shù)類型的db_num字段,db_num字段的值指示了記錄(也稱作元組)被路由的目標(biāo)數(shù)據(jù)庫。下面舉例說明db_num字段的作用:
 設(shè)關(guān)系模式為R(id,…,db_num,…),該模式對應(yīng)的表的數(shù)據(jù)需要被路由到N(N×1)個物理數(shù)據(jù)庫內(nèi),任意一條記錄(id_value,…,n,…)存在于第n個物理數(shù)據(jù)庫的某張表中(0<n≤N,n為db_num字段的值)。
2.2 分表策略
 數(shù)據(jù)庫表存放記錄數(shù)量的最大值在理論上可以取很大的值,但在實際應(yīng)用中通常受到文件系統(tǒng)的限制。當(dāng)一張表的數(shù)據(jù)記錄數(shù)達到一個閾值時,操作該表的速率會急劇下降。在MySql數(shù)據(jù)庫中,當(dāng)表記錄數(shù)達到1 000萬條時,查詢該表的速率明顯地下降。
 在同一個數(shù)據(jù)庫建立多張模式相同的表,數(shù)據(jù)被路由到不同的表中,從而可以很好地解決表記錄過多引起速率下降的問題。每條記錄要唯一地標(biāo)示它所在表的編號,因此必須引入某種編碼手段存放該記錄的編號。有兩種常用的策略:(1)用記錄的主鍵標(biāo)示該記錄所在表的編號,也就是數(shù)據(jù)庫表主鍵拆分策略;(2)特意引進一個日期字段標(biāo)示記錄所在表的編號,也就是數(shù)據(jù)庫表日期字段拆分策略。
2.2.1 數(shù)據(jù)庫表主鍵拆分策略
 假設(shè)邏輯表模式R的記錄在一個數(shù)據(jù)庫中需要分別路由到M(M≥1)張物理表中,設(shè)邏輯表R的表名為logic_table_name,物理表的表名分別是table_1,table_2, …,table_M。
 設(shè)表R的模式為R(id,…),其中id是模式的主鍵,其數(shù)據(jù)類型為整數(shù)類型。R的任意一條記錄r(x,…),其主鍵值為x,r被路由到物理表table_y中(y的值為x和M取模的結(jié)果,即:y=x%M)。
 隨著記錄主鍵值id的增加,記錄可以非常均勻地路由到M張物理表中。然而,如果需要動態(tài)增加M的值,如M的值由M增加到M’,則記錄就不會均勻地分配到M’張物理表中。此時可以采取表日期字段拆分法。
2.2.2 數(shù)據(jù)庫表日期字段拆分
 按照表的日期字段拆分?jǐn)?shù)據(jù)是另一種常用的拆分策略,當(dāng)數(shù)據(jù)量比較大時,暫時無法估算到底需要多少張物理表才能存放一個模式的所有記錄,此時可以采取按表日期字段拆分策略。
設(shè)數(shù)據(jù)庫表模式為R(id,column1,…,update_time),update_time字段是該記錄創(chuàng)建時的系統(tǒng)時間,任意一條記錄r(x,column1_vlaue,…,update_time_value)。在應(yīng)用層讀取系統(tǒng)的時間可以計算得到update_time_value時間值是一年中的某天day_of_year,這樣就可以把數(shù)據(jù)拆分到365(或366)張表中,物理表名分別為table_name_0,table_name_1,…,table_name_day_of_year,…,table_name_365(或365)。
除了按照取得update_time_value的day_of_year值,也可以取得update_time_value在星期中的某天day_of_week和在月的某天day_of_month。DDLM中間支持按照時間的各種策略。
 為了最大化地拆分?jǐn)?shù)據(jù),DDLM還提供以上策略的二級拆分。
2.3 數(shù)據(jù)合并排序策略
 分庫分表后,一張邏輯表table_name的數(shù)據(jù)存儲在不同的物理表中,在對表進行查詢、刪除和更新時,一條Sql語句可能會同時對一張或者多張物理表的數(shù)據(jù)產(chǎn)生影響。對于刪除、更新操作,分別針對每個物理數(shù)據(jù)庫執(zhí)行對應(yīng)的刪除、更新語句,然而對于查詢語句涉及到多個物理數(shù)據(jù)庫時,不能簡單地針對每個數(shù)據(jù)庫執(zhí)行查詢語句,還需要合并所有的查詢結(jié)果并且排序。下面舉例說明查詢合并以及排序策略。
 假設(shè)物理表表名分別為table_name0,table_name1, …,table_nameN,同時設(shè)Sql語句為SELECT*FROM talbe_name WHERE update_time=today OR update_time=yesterday ORDER By id LIMIT a,b(其中a,b為自然數(shù)),又假設(shè)該邏輯表table_name是按update_time日期字段水平分片的,則Sql的查詢會涉及到物理表中的兩張表記為table_nameX(0≤X≤N),table_name_Y(0≤X≤N)。該Sql的執(zhí)行流程如下:
 1)對表table_nameX查詢操作SELECT*FROM table_nameX WHERE update_time=today得到結(jié)果集ResultSet1,并對表table_nameY執(zhí)行和SELECT*FROM table_nameY WHERE update_time=yesterday得到結(jié)果集ResultSet2。
 (2)從結(jié)果ResultSet1和ResultSet2讀取數(shù)據(jù)存放在一個集合Result中,按照id字段排序。
 (3)在集合Result中,讀取id分布在區(qū)間[a,a+b]上的記錄作為返回結(jié)果。
通過上述查詢合并排序策略,當(dāng)在查詢過程中涉及到多張物理表時,能夠分別讀取多張物理數(shù)據(jù)庫表的數(shù)據(jù),然后在內(nèi)存中對數(shù)據(jù)分別執(zhí)行合并、排序和分頁操作。合并排序需要一定的時間和空間,所以在查詢時,盡量不要同時涉及到兩個或者以上的數(shù)據(jù)庫。
2.4 主鍵生成策略設(shè)計
 在DDLM中,數(shù)據(jù)被路由到多個數(shù)據(jù)庫的多張表中,為了確保主鍵的全局唯一性,不能借助于數(shù)據(jù)庫管理系統(tǒng)DBMS來生成主鍵,因為DBMS生成的主鍵只在當(dāng)前數(shù)據(jù)庫中具有唯一性,不能確保主鍵的全局唯一性。有兩種策略可以生成具有全局唯一性的主鍵:(1)采用通用的UUID生成策略,UUID是借助主機的時間戳、IP地址和網(wǎng)卡Mac地址等生成分布式唯一標(biāo)示符的算法,但是該策略生成的唯一標(biāo)示符需要用32個字符來存儲,非常浪費空間;(2)借助分庫分表的信息生成主鍵,該策略非常有效地利用了分庫分表的路由信息,巧妙地生成全局唯一主鍵。下面將詳細(xì)地介紹該策略。
 假設(shè)一張邏輯表logic_name的數(shù)據(jù)分別存儲在數(shù)據(jù)庫db_1,db_2,…,db_s(s為大于1的正整數(shù))中,每個數(shù)據(jù)庫中有相同的表table_1,table_2,…,table_t(t為大于1的正整數(shù))。用三位作為數(shù)據(jù)庫的編號、三位作為表的編號以及一個隨機字段來構(gòu)成全局唯一主鍵。數(shù)學(xué)表達式為xxxyyym…m,xxx為數(shù)據(jù)庫的編號,yyy為表的編號,m…m為隨機數(shù)。該主鍵生成策略有兩個優(yōu)點:(1)實現(xiàn)方便,通常一張邏輯表的數(shù)據(jù)不會多得需要被路由到1 000個物理數(shù)據(jù)庫以上,也不會路由到1 000張表以上;(2)主鍵本身就包含有路由信息。使用此策略,由主鍵信息就能路由該記錄,而不必查詢配置信息。假設(shè)一條數(shù)據(jù)庫記錄的主鍵為10020012345,取出前三位為100,則該記錄應(yīng)該路由到編號為100的數(shù)據(jù)庫(記為db100),取出4~6位為200,則該記錄應(yīng)該路由到db100的編號為200的表。
 DDLM在應(yīng)用層透明地把邏輯數(shù)據(jù)庫表的數(shù)據(jù)拆分到多個物理數(shù)據(jù)庫的多張表中,同時提供合并查詢排序、主鍵生成等功能,從而可以在不支持分布特性的數(shù)據(jù)庫管理系統(tǒng)應(yīng)用分布式特性。
參考文獻
[1] 林昊.分布式Java應(yīng)用:基礎(chǔ)與實踐[M].北京:電子工業(yè)出版社,2010.
[2] 何坤.基于內(nèi)存數(shù)據(jù)庫的分布式數(shù)據(jù)庫架構(gòu)[J].程序員,2010(7):116.
[3] 潘群華,吳秋云,陳宏盛.分布式數(shù)據(jù)庫系統(tǒng)中數(shù)據(jù)一致性的維護方法[J].計算機工程,2002(9):12-15.
[4] 習(xí)周龍.分布式數(shù)據(jù)庫管理系統(tǒng)實現(xiàn)技術(shù)[M].北京:科學(xué)出版社,1999.
[5] 趙致格.?dāng)?shù)據(jù)庫系統(tǒng)與應(yīng)用[M].北京:高等教育出版社,1994.

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。