摘要:多層軟件結構中已經成功地應用了集群,但在后臺數據庫上還缺乏這種工具,所以當數據庫層出現瓶頸時,就得在硬件上花費高額的費用。開源數據庫集群中間件——C-JDBC解決了上述問題。它通過JDBC接口引進了一個虛擬數據庫,只要基于擁有JDBC驅動的數據庫上面的應用程序,程序無須任何改動就能運行。C-JDBC具有靈活的體系結構,支持大型復雜的數據庫集群體系結構,為數據庫集群提供的高性能、強容錯能力、易用的平臺。
關鍵詞:Java數據庫連接;集群;中間件;數據庫
中圖分類號:TP319文獻標志碼:A
文章編號:1001-3695(2007)05-0094-03
在科學計算中,由普通機器組成的集群已經在很大程度上代替了大型機。這是因為集群有著出眾的性價比,這已經在Web服務器和應用服務器上的應用很好地體現出來了。在數據服務環境中,雖然集群也提供了高性能和強容錯能力,但是這方面的工具就少得多,并且主要是面向大企業的解決方案。商務解決方案如Oracle Real Application Clusters,已經開始從事應用共享存儲系統;IBM的DB2 Integrated Cluster環境中應用了網絡共享存儲;而在開源陣營的數據庫集群方面,MySQL復制技術應用主從機制來實現。這些技術一個明顯的缺點就是為了實現集群的特性,必須擴展數據庫引擎,所以應用程序要用一些額外的API,并且這些不同技術的不同實現,很難相互協作。
C-JDBC是一個開源的、建立在普通硬件上的數據庫集群中間件,它隱藏了集群的復雜性,為應用程序提供一個單一的數據庫視圖。客戶端程序不用修改,就可透明地訪問數據庫集群;只要RDBMS提供了JDBC驅動,C-JDBC就可以工作;分布式裝載、錯誤容忍、錯誤恢復全部由C-JDBC來處理;其具有可塑的體系結構,能支持分布式大型異質的數據庫集群,對不同程度的性能、錯誤容忍度和高效性進行協調。
本文從體系結構、容錯能力、所支持的集群結構、性能對比這幾個方面對C-JDBC進行了研究。
1C-JDBC體系結構
1.1功能總覽
C-JDBC是基于JDBC的數據庫集群Java中間件,它能使一系列不同質的數據庫轉換成一個統一的虛擬數據庫(Virtual Database)。在集群中數據同步時,數據拷貝的方式有完全拷貝、部分拷貝,復制的程度和定位都是以表為基本單位。但是,目前在詳細查詢中,表必須存在于一個后臺數據中,不能讓一個表拆分成兩個部分存儲到兩個后臺數據庫中。
數據操作時,依據Read-one Write-all的原則,由C-JDBC統一向各個后臺數據庫分配操作;C-JDBC有多種平衡裝載策略,并且用戶可以重載這些策略;利用查詢結果Cache機制,提高性能;可對多種容錯機制進行選擇。C-JDBC還提供了其他服務,如監控和日志等功能,管理平臺通過JMX來實現監控。而對于那些大型高性能的系統,還可以實現C-JDBC嵌套集群。
1.2體系結構
圖1是C-JDBC的總體結構圖。它實現了數據庫規范中所規定的JDBC驅動并且提供了與JDBC相同的接口,客戶端通過C-JDBC和C-JDBC控制器(Controller)進行交互。C-JDBC 控制器是一個Java組件,是介于C-JDBC驅動與數據庫后臺之間的代理。控制器為C-JDBC驅動和應用程序提供一個虛擬數據庫。一個控制器可以包含多個虛擬數據庫,每個虛擬數據庫擁有一個請求管理器(Request Manager)用來調度請求和實現裝載平衡策略。而數據庫后臺則是通過它們本身的JDBC驅動來實現訪問的。即使本身的驅動沒有實現連接池的功能,C-JDBC也可以通過提供一個連接管理器來實現連接池的功能。
這里將深入研究C-JDBC體系結構的關鍵組件,即C-JDBC驅動和請求管理器,而其他組件如授權管理、鏈接管理、配置支持等不作討論。
1.3C-JDBC驅動
C-JDBC驅動混合了類型3和類型4的JDBC驅動,它實現了JDBC 2.0規范和JDBC 3.0規范中一些擴展的功能。在驅動端執行的功能都已經內置到C-JDBC驅動中了。比如,當一條SQL語句在一個后臺執行時,所返回的結果被序列化成C-JDBC驅動的結果集。當被序列化的結果集被送到C-JDBC驅動反序列化處理后,客戶端才能瀏覽。
所有與數據庫相關的操作都被轉發到C-JDBC控制器處,由控制器轉發到數據庫原生驅動器來處理。C-JDBC驅動器對于不同結構的數據庫集群的錯誤恢復都是透明的。
1.4請求管理
請求管理包含了C-JDBC控制器的核心功能。它由調度組件、裝載平衡組件以及兩個可選組件(即恢復日志組件和結果緩存組件)所組成。
1.4.1調度器
每當C-JDBC驅動發出一個請求,請求在虛擬數據庫的配合之下,通過請求管理器決定執行操作。例如,新建事務、提交或者是取消操作;發送讀操作到一個后臺;更新所有受影響的后臺;對一部分或是對全部的后臺數據庫進行部分拷貝或完全拷貝;對于含有rand()或now()的SQL查詢語句進行計算,而保證各后臺數據庫數據一致性。只有當請求管理器收到所有后臺數據庫對操作發回正確的回應時,才會向客戶端發出一條響應。
當執行更新操作時,如果某一后臺出錯或者取消操作時,對于集群來說,這一操作就是無效的。應當注意的是,C-JDBC不是用的兩階段鎖協議,而是它提供了一個能在虛擬數據庫中自動恢復錯誤的工具。
1.4.2查詢結果緩存機制
查詢結果緩存機制可以用來存放查詢結果,以此來輔助每一次查詢。查詢結果緩存機制減少了查詢響應的時間。緩存機制具有靈活的機制來確保數據一致性。換句話說,C-JDBC在查詢緩存中執行了更新操作后,將對緩存實體打上無效的標志。靈活性體現在緩存的一致性的原則由用戶來定義。為了滿足不同性能要求,可以定義查詢操作在某一限定的時間內可用緩存中的數據,即使它是陳舊的數據;還可以定義緩存實體在什么條件下被標志成無效。這些條件可以是當數據庫變動、表變動和列變動三種不同的粒度。
1.4.3裝載平衡器
當緩存中沒有所需要裝載的數據時,或者緩存中的數據無效時,請求就轉發到裝載平衡器處。
C-JDBC控制器根據設定的復制方式來提供不同的裝載平衡。完全復制是一種易于處理的方法。雖然各個后臺數據庫都能夠處理查詢,但是當數據庫更新時,就必須對各個后臺就行操作,當后臺數據庫增多時就會遭遇到性能上的瓶頸。所以這種方式并不是最好的方式。為了解決這個問題,C-JDBC提供了基于用戶自定義的數據庫表復制的部分復制機制。裝載平衡通過操作請求的解析,并依據由后臺數據庫同步而來的數據結構(Schema)來達到部分復制的功能。C-JDBC控制器動態收集后臺數據庫的數據結構。當后臺可用時,C-JDBC控制器就會調用JDBC中的方法,通過數據庫生產商提供的驅動程序讀取數據庫元數據。當SQL語句中執行了Create、Drop等語句正確地反映在各個后臺時,數據庫結構信息就會動態更新。
C-JDBC控制器依據動態裝載算法,選擇后臺數據庫來執行操作語句。目前C-JDBC上所實現的動態裝載算法有:循環選擇和權重循環。
2容錯性
C-JDBC為了提高容錯能力,對客戶端屏蔽容錯功能,在C-JDBC控制器中提供了檢查點(Checkpoint)和恢復日志兩種工具。當后臺數據庫發生錯誤時,或者某一后臺數據庫執行備份后,可以結合檢查點和恢復日志自動使后臺數據庫重新達到正確的狀態。
2.1檢查點
檢查點就是虛擬數據庫在執行時的某一時刻。檢查點可由管理人員設置也可由系統依據時間規則自動設置。
在后臺數據庫執行備份時,C-JDBC會要求這個后臺停止運行,所以這段期間就不能對該后臺進行更新操作。但是其他后臺仍然要服務于客戶端。由于在同一個虛擬數據庫中的不同后臺需要保持一致性,在備份一個后臺時,該后臺要求鎖住所有的表,進入只讀的模式,掛起該后臺所有的更新操作。但這種情況對于進行一次備份需要幾個小時的大型數據庫來說是不可行的。C-JDBC引進檢查點的概念,就是在執行備份或者在特定設定的時間點時,在恢復日志中插入一個所謂檢查點的標志;然后,所有對該后臺數據庫操作就會被記錄下來。當該后臺數據庫重新啟動時,就會從這一個檢查點開始,依次執行所有操作,從而恢復到一致的狀態。
2.2恢復日志
C-JDBC提供了恢復日志。恢復日志實體記錄了操作的起始、提交、取消以及更新的各種細節,日志實體中還包括了用戶標志符、事務標志符和SQL語句。日志可以以文件的形式存儲,當然也可以通過JDBC存儲到數據庫中。當錯誤發生時,以創建好的容錯日志傳輸給C-JDBC的虛擬數據庫,進行日志更新,從而更正錯誤。
3C-JDBC擴展方式
單一的C-JDBC控制器還是存在潛在的出錯可能性。橫向擴展C-JDBC控制器就降低了這種潛在的可能性。當然也提供了垂直擴展來建立一種多層次的后臺,以滿足擁有大量數據庫后臺的系統。
3.1C-JDBC橫向擴展
橫向擴展提高了C-JDBC控制器的容錯能力。C-JDBC應用JGroup來同步不同控制器中的虛擬數據庫。當一個虛擬數據庫被一個控制器裝載時,虛擬數據庫被賦予一個組名,分布在不同控制器中的虛擬數據庫就依據組名來交換信息。在初始階段,各個控制器之間交換各自的后臺數據庫配置信息。如果有一個控制器失敗,則后臺必須重新執行同步。而C-JDBC依靠JGroup消息來同步Write請求和劃分事務。
3.2C-JDBC垂直擴展
有時可能需要在C-JDBC控制器中嵌套使用控制器。例如,第一級的控制器部分復制了三個后臺數據庫,這三個后臺數據庫都是由其他C-JDBC控制器實現的虛擬數據庫。在第一級控制器對數據庫訪問時,第二級的C-JDBC驅動被當做原生驅動了。垂直擴展可應用于大量數據庫后臺的情況。
當然,還可以進行橫向與垂直混合的擴展。總的來說,任意結構的C-JDBC控制器樹都是可以創建的。但是這種情況需要考慮JVM對外連接數目以及性能問題。
4性能測試
基于對C-JDBC結構的了解,以下用具體的實驗數據來分析C-JDBC集群的性能。搭建了測試環境,對測得的不同實驗數據進行分析。
4.1測試實驗
測試數據為每條記錄600 Bytes,客戶端分別采用三種不同方式訪問數據庫:①ODBC直連方式訪問一臺Oracle數據庫;②ODBC線性方式訪問三臺Oracle數據庫;③ODBC-JDBC 橋接加C-JDBC方式訪問三臺Oracle數據庫。其中C-JDBC測試中所采用的控制器結構為單控制器結構,就是一個控制器下連接著三臺Oracle數據庫。
4.2測試環鏡
4.3測試結果分析
從表1中的測試數據,可以得到以下結論:
(1)使用ODBC直連方式訪問單臺數據庫的速度是最理想的。
(2)使用ODBC直連方式線性訪問三臺數據庫的速度基本上是訪問單臺數據庫的速度疊加。
(3)使用C-JDBC方式將三臺Oracle數據庫組成集群。C-JDBC控制器的多播方式將插入請求分發到三臺數據庫,速度位于前兩種方式之間。隨著插入數據量的增大,這種方式的插入速度更加理想,逐漸靠近使用ODBC直接訪問單臺數據庫的性能。
在實驗中,C-JDBC不會消耗系統太多的資源。在測試中,隨著插入數據量的增大,內存的使用率也穩定在2.7%。但實驗中也暴露了一些有待解決的問題。C-JDBC和Oracle Blob不兼容;Oracle的Blob實現采取了特別的設計;只有在獲得Cursor后才可以對Blob插入,這一點與標準JDBC的setBlob方法不兼容;再則就是多控制器的數據同步時還不穩定,有時數據會出現錯誤。
5結束語
C-JDBC是一個易擴展、高效率的數據庫集群中間件。通過使用標準的JDBC接口,使用C-JDBC而無須修改應用程序、數據庫引擎。C-JDBC混合了水平和垂直擴展,從而使數據庫可以分布在多個節點并能進行數據部分復制,很好地解決了大型數據庫復制的問題;不僅如此,C-JDBC還可以平衡這些節點之間的查詢負載,提高了查詢速度,改進了查詢性能,能很好地應用于研究和工業領域。
參考文獻:
[1]CECCHET E, MARGUERITE J,PELTIER M,et al.C-JDBC user’s guide [R].[S.l.]:French National Institute for Research in Computer Science and Control (INRIA) Emic Networks,2005:1-77.
[2]BORNHVD C, ALTINEL M, MOHAN C,et al.Adaptive database caching with DBCache [J]. Data Engineering,2004,27(2):11-18.
[3]CECCHET E. C-JDBC:a middleware framework for database clustering [J].Data Engineering,2004,27(2):19-26.
[4][EB/OL].[2006-02].http://www.objectweb.org/.
[5]LIN Yi,KEMME B,PATINO-MARTINEZ M,et al. Middleware based data replication providing snapshot isolation[EB/OL].[2005-06].http://acm.lib.tsinghua.edu.cn.
[6]SIVASUBRAMANIAN S,ALONSO G,PIERRE G,et al.GlobeDB: autonomic data replication for Web applications[EB/OL].[2005-03].http://acm.lib.tsinghua.edu.cn.
注:“本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文”