王 錦,梁正和,王法強
(河海大學 計算機與信息學院,江蘇 南京 211110)
隨著互聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,移動網(wǎng)絡、局域網(wǎng)、廣域網(wǎng)、Internet得到了巨大的發(fā)展,集中部署的單機數(shù)據(jù)庫系統(tǒng)己經(jīng)不能夠適應這樣的環(huán)境[1],使用服務器集群來解決海量數(shù)據(jù)[2]成為必然趨勢,分布式數(shù)據(jù)庫應運而生。MyCat分布式數(shù)據(jù)庫中間件[3]由阿里巴巴的開源項目cobar[4]發(fā)展而來,其本身提供了分布式資源整合方案。該產(chǎn)品具有雙機熱備份、負載均衡、SQL語句重寫、讀寫分離[5]、查詢路由、多臺數(shù)據(jù)庫并行處理以及結(jié)果集合并等功能[6],并提供了對MySQL、PostGreSQL等應用廣泛的開源關(guān)系型數(shù)據(jù)庫的分布式支持。該分布式數(shù)據(jù)庫中間件為用戶提供廉價的數(shù)據(jù)庫集群,平滑地將現(xiàn)有的單機集中式數(shù)據(jù)庫和應用遷移到“云”[7]端,同時保留原有數(shù)據(jù)庫的查詢能力。
通過MyCat可以搭建以MySQL為底層節(jié)點的分布式數(shù)據(jù)庫系統(tǒng),系統(tǒng)通過MySQL的通信協(xié)議[8]與用戶以及底層數(shù)據(jù)庫通信。對于用戶,通過該中間件能夠透明地訪問整個集群,故而原有的基于MySQL開發(fā)的應用均無需修改,直接遷移到分布式系統(tǒng)中。該系統(tǒng)在中間件中建立了完整的Schema(模式)、Table(表)、User(用戶)的邏輯模型,將整套模型通過邏輯規(guī)則映射到每個數(shù)據(jù)節(jié)點上的MySQL實例中,并可以實現(xiàn)事務處理。
面對一些數(shù)據(jù)量巨大的表,可以通過MyCat對數(shù)據(jù)進行水平切分[9],在保證每個分片節(jié)點的表結(jié)構(gòu)一致的情況下,將表映射到不同的數(shù)據(jù)引擎上,從邏輯上實現(xiàn)數(shù)據(jù)庫容量的擴充。MyCat不支持跨分片連接查詢,需要將與其關(guān)聯(lián)的表設置為全局表分布在各個分片上。由于MyCat的弱Xa事務[10]機制,頻繁操縱全局表可能會導致異常情況的發(fā)生:某個用戶在修改好全局表提交的一瞬間,忽然某個節(jié)點出錯了,可能會出現(xiàn)某些節(jié)點已成功修改而出錯節(jié)點數(shù)據(jù)無變更,使得各個節(jié)點數(shù)據(jù)不一致的情況。對于一個大企業(yè),該類問題是難以忍受的。MyCat中的表廣播機制改變了原始的對全局表的操作邏輯,把原來的同時向多個節(jié)點發(fā)送的DML[11]消息,修改為只向全局表中的主節(jié)點發(fā)送廣播消息,待主節(jié)點接收消息后再向其他節(jié)點發(fā)送廣播,通知其他節(jié)點有新消息到達,實現(xiàn)各節(jié)點間的數(shù)據(jù)同步。若主節(jié)點在修改過程中突遇異常情況致使操作中斷,則所有節(jié)點均無修改操作;若其他節(jié)點在同步過程中出現(xiàn)意外中斷,待故障排除后,繼續(xù)未完成的同步工作,成功解決了多個節(jié)點數(shù)據(jù)不一致的問題。
MyCat中的事務主要包括SQL不跨分片事務和SQL跨分片事務[3]。對于SQL不跨分片這種情況,SQL僅僅是在一個數(shù)據(jù)節(jié)點上執(zhí)行,此時MyCat事務模式同標準的數(shù)據(jù)庫事務模式[12]完全一致,或提交、或回滾,能夠保證強一致性[13];對于SQL跨分片的事務,首先事務內(nèi)的SQL在各自的分片上執(zhí)行并返回狀態(tài)碼,若某個分片上的返回碼為ERROR,則MyCat認為事務失敗,應用端只能回滾(rollback)事務,MyCat收到回滾指令后,依次回滾事務中涉及到的所有分片;若事務中的所有SQL的執(zhí)行都返回成功(OK)的返回碼,則應用程序提交事務,由MyCat同時向事務中涉及到的節(jié)點發(fā)送提交事務的指令(commit),在commit的時候,若某個節(jié)點出錯,MyCat也無法等節(jié)點恢復后重新commit,出現(xiàn)部分節(jié)點commit成功而部分節(jié)點沒有commit的情況。由于跨分片事務的第二階段無法保證強一致性,稱MyCat是一種弱XA事務模式。
表廣播機制的實現(xiàn)主要分為三個步驟:
(1)用戶發(fā)送DML(數(shù)據(jù)操作語言)請求,主機接收到命令,向主節(jié)點發(fā)送廣播。主節(jié)點接收到消息,將消息記錄到二進制文件,并將消息發(fā)送給其他從節(jié)點。
(2)從節(jié)點讀取消息,并將消息寫入到自己的中繼日志。
(3)從節(jié)點重做中繼日志中的事件,并改變自己的數(shù)據(jù)。
如圖1所示,主機接受請求后向主節(jié)點發(fā)送廣播,主節(jié)點接收消息并記錄二進制文件。在每個事務更新數(shù)據(jù)完成之前,主節(jié)點在二日志文件中記錄這些改變。MySQL線程將事務串行地寫入二進制日志,在事件寫入完成后,主節(jié)點通知存儲引擎提交事務并向其他從節(jié)點發(fā)送廣播。
圖1 表廣播機制原理圖
從節(jié)點接收到消息,將主節(jié)點的二進制日志拷貝到自己的中繼日志。首先,從節(jié)點開始一個工作線程(I/O線程),I/O線程在主節(jié)點上打開一個普通的連接,然后開始二進制轉(zhuǎn)存。二進制轉(zhuǎn)存程序從主節(jié)點的二進制日志中讀取消息事件,如果沒有新的消息,它會睡眠并等待主節(jié)點發(fā)送新的廣播。
SQL從線程從中繼日志讀取消息事件,并重放其中的事件以更新從節(jié)點中的數(shù)據(jù),使其與主節(jié)點中的數(shù)據(jù)一致。
MyCat是一個開源的分布式數(shù)據(jù)庫系統(tǒng),是一個實現(xiàn)了MySQL協(xié)議的server,前端用戶可以把它看作一個數(shù)據(jù)庫代理[14],用MySQL客戶端工具和命令行訪問,而其后端可以用MySQL原聲(Native)協(xié)議[15]與多個MySQL服務器通信,也可以用JDBC協(xié)議與大多數(shù)主流數(shù)據(jù)庫服務器[16]通信。MyCat中有兩種典型類型的表,一種是按照某種給定的分片規(guī)則,將數(shù)據(jù)進行水平切分,把一個大表水平分割成N個小表,存儲在后端MySQL服務器或者其他不同的數(shù)據(jù)庫;另一種是全局表,MyCat接收外界發(fā)送來的SQL語句,將DML SQL語句分別發(fā)送到各個數(shù)據(jù)庫節(jié)點上依次執(zhí)行,圖2形象地描述了全局表的DML操作過程。若對全局表頻繁地進行增刪改操作,由于MyCat的弱XA機制,很容易發(fā)生各節(jié)點數(shù)據(jù)不一致的情況。
圖2 原始MyCat全局表的DML操作過程
MyCat中的表廣播機制是針對全局表的,為全局表新增了一個屬性,當該屬性值為true時,改變原始SQL語句的執(zhí)行邏輯。MyCat接收到DML命令,向主節(jié)點發(fā)送廣播,主節(jié)點執(zhí)行命令并保存二進制消息文件,同時向從節(jié)點推送消息,從節(jié)點接收到廣播,同步主節(jié)點的數(shù)據(jù)。實現(xiàn)了表廣播機制的MyCat即使在修改數(shù)據(jù)時出現(xiàn)節(jié)點異常的情況,待異常解除后,會主動讀取存放消息的日志文件、同步數(shù)據(jù),保證了強一致性。
圖3形象展示了DML操作在表廣播機制下的執(zhí)行過程,即當MyCat接收到插入類型的SQL語句時,只向主節(jié)點發(fā)送相應的SQL語句,再通過日志文件,同步到其他節(jié)點。
圖3 表廣播機制下的DML操作過程
MyCat啟動時,首先讀取配置文件,根據(jù)其中table標簽的設置信息,判斷各張表的類型。在配置文件schema.xml的table標簽中增加一個屬性“writeOneNode”作為啟用表廣播機制的標志,當邏輯表的類型是全局表即“type=globle”時,才啟用表廣播功能機制。
新增的屬性為布爾類型,默認值為“false”?!皐riteOneNode=true”時,過濾DML操作的SQL語句,通過表廣播作用于主節(jié)點;當“writeOneNode=false”時,DML操作的SQL語句按照原始邏輯作用于所有節(jié)點。
通過Java應用程序訪問XML時,要先把Java對象轉(zhuǎn)化成XML文件(稱作marshall),再將XML文件中的內(nèi)容轉(zhuǎn)化成相應的Java對象(稱作unmarshal),該對象需要用JAXB(Java architecture for XML binding,XML綁定的Java體系結(jié)構(gòu))注解來標注[17]。因此需要修改注解類Schemas.java,在其內(nèi)部類中添加“writeOneNode”的屬性設置,使配置文件“schema.xml”中的內(nèi)容unmarshal成Table類型的對象時,包含“writeOneNode”字段的相應信息。
初始化XML配置文件類XmlToYaml.java中,增加對參數(shù)“writeOneNode”的初始化功能,在啟動程序時加載配置文件,通過解析XML配置文件,對配置文件中設置的相關(guān)參數(shù)進行初始化,在Schemas的各個內(nèi)部靜態(tài)類中實例化本類對象,最后再通過HashMap存儲好所需要配置的Key-value鍵值對,對外提供本類實例化對象。
MyCat中的表廣播機制是針對于全局表的DML操作而提出的,且只有在writeOneNode=true時其功能才會奏效,因此需要增加新的SQL執(zhí)行邏輯。如圖4所示,MyCat對接收到的sql語句進行以下判斷:
圖4 MyCat中的表廣播機制執(zhí)行流程
(1)sql語句的類型是否為insert或update或delete;
(2)待插入的表是否為全局表;
(3)是否寫入單節(jié)點,即writeOneNode=true。
只有三個條件同時滿足,才能將原始的多節(jié)點插入功能修改為單節(jié)點插入,啟用表廣播功能。
為了分析表廣播機制在MyCat中的實現(xiàn)方案的可行性,在真實環(huán)境下進行實驗分析。
實驗環(huán)境:三臺配置完全相同的服務器。配置如下:操作系統(tǒng)為RedHat7.2;1*6 Core的CPU;內(nèi)存16 G;硬盤16*1 T;千兆網(wǎng)卡。
步驟1:新建數(shù)據(jù)庫和數(shù)據(jù)表。
實驗中的全局表“teacher”具有4個分片,分別位于4個不同的數(shù)據(jù)庫中,數(shù)據(jù)庫名稱分別為MyCat1,MyCat2,MyCat3,MyCat4,所屬服務器ip為172.172.0.104,并在各個數(shù)據(jù)庫中分別新建表“teacher”(含有字段:tid,name,sex,class;tid為關(guān)鍵字);在另外一臺ip為172.172.0.106的服務器上也新建4個數(shù)據(jù)庫:broadcastMyCat1、broadcastMyCat2、broadcastMyCat3、broadcastMyCat4,每個數(shù)據(jù)庫中也分別包含同樣表結(jié)構(gòu)的“teacher”表,并配置broadcastMyCat1為broadcastMyCat2、broadcastMyCat3、broadcastMyCat4的主數(shù)據(jù)庫,broadcastMyCat2、broadcastMyCat3、broadcastMyCat4為broadcastMyCat1的從數(shù)據(jù)庫,啟用表廣播功能。
步驟2:安裝MyCat。
在ip為172.172.0.107的服務器上分別安裝官方MyCat(端口號為8068,命名為MyCat_8068)和實現(xiàn)表廣播機制的MyCat(端口號為8069,命名為broadcastMyCat_8069),進行正確的配置文件設置,兩者的區(qū)別如下:
MyCat_8068的schema.xml部分配置如下:
broadcastMyCat_8069中的schema.xml配置如下:
完成配置文件的設置后,分別啟動MyCat_8068和broadcastMyCat_8069。
實驗1:為驗證MyCat中的表廣播機制,實現(xiàn)了原始MyCat中全局表功能,通過程序分別向MyCat_8068和broadcastMyCat_8069中的teacher表中連續(xù)作插入操作。一段時間后,分別到本地的各個數(shù)據(jù)庫中查詢teacher表中的數(shù)據(jù),對各個表中的記錄總數(shù)和數(shù)據(jù)內(nèi)容進行對比,結(jié)果如表1所示。
表1 正常插入時的數(shù)據(jù)對比表
由表1可知,各個表中的記錄數(shù)量幾乎相同,同一個MyCat下各個節(jié)點中的數(shù)據(jù)均一致。結(jié)果表明,在各個數(shù)據(jù)節(jié)點運行正常的情況下,原始的MyCat和實現(xiàn)表廣播機制的MyCat均可以做到數(shù)據(jù)的高效插入,且保證了各個節(jié)點間的數(shù)據(jù)一致性。
實驗2:為驗證在DML操作過程中出現(xiàn)節(jié)點異常后實現(xiàn)表廣播機制的MyCat仍舊能保證各節(jié)點間的數(shù)據(jù)一致性,清空各個數(shù)據(jù)表中的數(shù)據(jù)后,通過程序分別向MyCat_8068和MyCat_8069中的teacher表中連續(xù)作插入操作,在插入過程中,關(guān)閉MyCat2和broadcastMyCat2兩臺數(shù)據(jù)庫,一段時間后恢復兩臺數(shù)據(jù)庫,多次嘗試此操作,并對比各個MySQL數(shù)據(jù)庫中的數(shù)據(jù)狀況。
表2記錄了各個節(jié)點異常消除后的數(shù)據(jù)情況,原始MyCat下的異常節(jié)點中的數(shù)據(jù)明顯少于其他節(jié)點中的數(shù)據(jù),而實現(xiàn)表廣播機制的MyCat下的四個數(shù)據(jù)節(jié)點中的數(shù)據(jù)始終一致。
表2 異常解除后的數(shù)據(jù)對比表
由實驗2結(jié)果可以看出,MyCat的弱XA機制,確實導致了節(jié)點間的數(shù)據(jù)不一致,而實現(xiàn)了表廣播機制的MyCat,在異常節(jié)點恢復正常后,成功同步數(shù)據(jù),保證與主節(jié)點的數(shù)據(jù)同步。
以上實驗表明,實現(xiàn)表廣播機制的MyCat的可靠性較高,在保證數(shù)據(jù)高效插入的同時,也保證了數(shù)據(jù)一致性。
提出了一種表廣播機制在MyCat中的實現(xiàn)方案,通過對MyCat提供的操作全局表的相關(guān)功能進行優(yōu)化,把對多個節(jié)點的操作修改為對單個節(jié)點的操作,有效解決了MyCat面臨的弱XA問題。實驗結(jié)果表明,該方案在實現(xiàn)全局表原有功能的同時,有效提高了全局數(shù)據(jù)表中各節(jié)點數(shù)據(jù)的一致性。
目前,對于分庫表的查詢操作,MyCat只會返回各分庫合并后的數(shù)據(jù),在排序、分頁等功能上做得還不夠完善,因此,未來計劃運用其他的方法解決這類問題。
[1] 莊天紅.常用數(shù)據(jù)庫系統(tǒng)性能解析[J].微型電腦應用,1999,15(2):52-54.
[2] BOYD D, CRAWFORD K. Critical questions for big data[J].Information Communication & Society,2012,15(5):662-679.
[3] 項 凱.面向海量高并發(fā)數(shù)據(jù)庫中間件的研究與應用[D].上海:上海交通大學,2015.
[4] 邱 碩.Cobar的架構(gòu)與實踐[J].程序員,2012(9):90-93.
[5] 祝雄鋒.數(shù)據(jù)庫集群中間件MySQL Proxy研究與分析[D].武漢:武漢理工大學,2011.
[6] 王 蔥.基于MyCAT的分布式數(shù)據(jù)存儲研究與應用[D].上海:東華大學,2016.
[7] HAYES B.Cloud computing[J].Communications of the ACM,2008,51(7):9-11.
[8] 安延文.數(shù)據(jù)庫審計系統(tǒng)中MySQL協(xié)議的研究與解析[D].北京:華北電力大學,2016.
[9] 楊 晶,劉天時,馬 剛.分布式數(shù)據(jù)庫數(shù)據(jù)分片與分配[J].現(xiàn)代電子技術(shù),2006,29(18):119-121.
[10] 趙 艷,李 鈞.異構(gòu)數(shù)據(jù)源分布式事務處理研究[J].計算機工程,2009,35(4):69-71.
[11] 胡百敬,陳俊宇,楊先民,等.SQL Server 2005 T-SQL數(shù)據(jù)庫設計[M].北京:電子工業(yè)出版社,2008.
[12] 黃雅萍,劉曉強,吳成義.基于MySQL和PHP的分布式事務處理[J].東華大學學報:自然科學版,2011,37(1):81-85.
[13] 張旭剛,李東輝,俞 俊,等.基于zookeeper和強一致性復制實現(xiàn)MySQL分布式數(shù)據(jù)庫集群[J].微型電腦應用,2016,32(1):77-80.
[14] 徐 恪,劉亞霄,劉衛(wèi)東.數(shù)據(jù)庫應用系統(tǒng)中的安全訪問代理的設計與實現(xiàn)[J].計算機工程與應用,2000,36(1):105-107.
[15] 李曙強,蔣樹春,呂 兵.一種基于mysql數(shù)據(jù)庫的sql信息采集審計系統(tǒng):CN,CN103488797A[P].2013-10-14.
[16] 黃春華.常用數(shù)據(jù)庫的比較[J].科技信息,2011(14):200.
[17] 李占波,李 娜.XML數(shù)據(jù)在關(guān)系數(shù)據(jù)庫中的存儲[J].微計算機信息,2007,23(27):192-194.