http://www.csai.cn 作者:Jayanthi 來源:賽迪網
在開發分布式應用程式時,可用性與效能是主要考慮事項。但是用資料存放區解決這些問題可能會給異構資料存放區之間的資料同步帶來一些問題。在本文中,Jayanthi Suryanarayana 和 Neil Tunnicliffe 將提供一種解決方案:用 JDBC 和 SyncML 標準來實現通用的資料庫資料複製。
在設計分布式應用程式時,必須考慮可用性與效能。一般的解決方案是在客戶機系統上包含資料存放區。通常,由於資源有限,客戶機需要一個輕量級資料存放區。這種方法為異構資料存放區之間的資料同步帶來了挑戰。這個問題的一種解決方案是採用基於 java 的方法,用 JDBC 和 SyncML 標準進行異構資料庫複寫。
複製概述
複製是在兩個環境之間複製全部或部分資料庫的過程。為了保持一致,對來源資料庫所做的更改要傳播到複製的資料庫中。複製可以是單向的,也可以是雙向的。雙向複製可能更困難一些,因為對任何資料庫所做的更改都可能產生不一致的資料。當這些更改在兩個資料庫之間傳播時,需要有一個策略來調解這些差異,以便維護一致性。
ID 處理
作為複製的基本需求,我們需要惟一地標識將要複製的每個資料單元。對於雙向複製,還需要一個能夠標識資料庫之間對應資料單元的映射方案。根據複製的需求,可以採用各種各樣的方案。對於單向複製,主要資料庫可以要求為資料單元產生 ID。對於雙向複製,必鬚根據應用程式的 ID 產生方案定義映射方案。ID 產生方案與映射方案可以是每個資料庫使用的 ID 編號的相互排斥範圍,在這個範圍內,ID 編號是正好匹配的。更複雜的樣本中可能包括 ID 產生服務或者特定於資料庫的方案,在這種情況下,必須在資料庫之間維護 ID 的映射。
變化檢測
複製過程中的下一步是找出哪些資料單元已經更改。在關聯式資料庫中,可以用附加欄位來記錄資料單元的狀態和狀態變化的時間戳記。或者,也可以使用觸發器使部分變化檢測過程自動化。附加到表上的插入/更新/刪除觸發器可以檢測到對資料單元所做的更改,並在變更記錄檔表中記錄這些更改。這樣就可以用變更記錄表(change log table)確定在任何指定時間上對資料單元所做的更改。
複製
複製的目標是產生公用資料集的多個一致的副本。為了實現這個目標,必須交換每個資料庫中檢測到的更改,並使它們一致。在這裡,您面臨著一個設計上的挑戰。您可以作出如下選擇:
表示將交換的那些更改的資料格式。
傳輸機制,例如 HTTP、FTP、JMS 等,取決於應用程式的需求。
參與實體之間的交換協議。
資料單元之間的衝突檢測和解決機制。
SyncML 定義了一個同步協議,使用 XML 訊息來添加、刪除和修改資料單元。它也允許交換安全資訊,這樣節點就可以執行身分識別驗證。
Sync4J 是 SyncML 的開源 java 實現,它能夠支援多種傳輸機制。Sync4J 也根據應用程式的需求,給出了衝突檢測架構和解決方案策略。
樣本實現
本文將介紹一個簡單的資料複製樣本。這個樣本將示範兩個異構資料庫之間的雙向客戶資料記錄複製,每個資料庫都包含一個結構類似的客戶表。使用惟一的客戶 ID 來標識被複製的每條記錄。我們在表中添加了兩列,以記錄每條記錄的狀態和最後狀態變化時間戳記。對於這個樣本,狀態與時間戳記這兩列必須通過應用程式或手工進行填充。正如前面說過的,觸發器是一種在變更記錄表中自動填滿更改資料的適當解決方案。但是,在這個例子中使用的資料庫目前擁有的觸發器能力還很有限,因此我們選擇不用觸發器來實現這項任務。而且,這個執行個體不包括雙向複製的衝突解決方案策略。所以衝突會導致複製過程失敗。
我們要配置在 Tomcat servlet 容器中運行 Sync4J 伺服器的伺服器端環境,還要用 Derby 作為來源資料庫。此外,還要配置用戶端環境,用 HSQLDB 作為目標資料庫,在上面運行 Sync4J 客戶程式。(在這個例子中,假設已經安裝了 J2SE SDK 和 Ant。)
伺服器端安裝
要運行應用程式範例,需要在伺服器端安裝三個開源組件:Tomcat、Sync4J 伺服器和資料庫引擎。安裝 Tomcat、Sync4J 和 Derby 按以下步驟安裝三個主要的伺服器組件(請參閱 參考資料,以獲得下載連結)下載並展開 Tomcat 5.0.29。本文中用 TOMCAT 表示 Tomcat 的安裝目錄。將環境變數 J2EE_HOME 設為 TOMCAT。下載並展開 Sync4J Server 4.0.2。本文中用 SYNC4J 表示 Sync4J 伺服器的安裝目錄。下載並安裝 Derby。本文中用 DERBY 表示 Derby 的安裝目錄。
配置應用程式範例
接下來,需要配置範例程式碼。請單擊本文頂部或底部的 Code 表徵圖來下載j-sync4j.zip。將該檔案解壓到包含本樣本使用的用戶端代碼、伺服器代碼和 SQL 指令碼的目錄中。本文中用 TESTSYNC 表示這個目錄。
設定 JDBC 驅動程式類路徑
設定 JDBC 驅動程式的類路徑:將 db2jcc.jar 和 db2jcc_license_c.jar 分別從 DERBY\lib 複製到 TOMCAT\common\lib 和 SYNC4J\lib 中。用於 Sync4J 伺服器的 Derby 安裝指令碼,接下來,將目錄 TESTSYNC\derby 移動到 SYNC4J\default\sql。提供的指令碼與 Sync4J 伺服器下載一起提供的其他資料庫指令碼類似,但是要針對 Derby 對它們稍作修改。構建樣本 Sync4J 伺服器模組,要構建樣本 Sync4J 伺服器模組,請按以下步驟進行:
將 TESTSYNC\module\build.bat 中的 SYNCSERVER_DIR 設定為指向 SYNC4J。
運行 TESTSYNC\module\build.bat。
配置 Sync4J 伺服器
要配置 Sync4J,請按以下步驟進行:
在 Derby 中建立叫做 sync4jdb 的資料庫。步驟 3 的代碼中描述了 JDBC 設定,這些設定假設 DERBY 中有一個叫做 sync4jdb 的資料庫,使用者名稱為 sync4j,口令為 sync4j。
用 Derby 附帶的 IJ 工具建立並設定這個資料庫(有關 Derby 工具的資訊,請參閱 參考資料)。
設定 the properties in SYNC4J\install.properties 中的屬性,如下所示(用 JDBC 設定中的實際路徑代替 DERBY):
| dbms=derby jdbc.classpath=DERBY/lib/db2jcc.jar;DERBY/lib/db2jcc_license_c.jar; jdbc.driver=com.ibm.db2.jcc.DB2Driver jdbc.url=jdbc:derby:net://localhost:1527/"DERBY/sync4jdb" jdbc.user=sync4j jdbc.password=sync4j modules-to-install=foundation-1.0,pdi-1.1,testsync-1.0 |
設定 Derby 資料庫
執行 DERBY\frameworks\NetworkServer\bin\startNetworkServer.bat,將 Derby 作為網路伺服器來啟動。有關將 Derby 作為網路伺服器啟動的更多資訊,請參閱 Derby 的手冊。用 IJ 工具執行 TESTSYNC\create_table_server.sql,在 Derby 資料庫中建立表 customer1。為 Tomcat 安裝 Sync4J 伺服器和樣本模組要為 Tomcat 伺服器安裝 Sync4J 伺服器並設定 Sync4J 資料庫,需要完成以下步驟:
從 SYNC4J 中運行以下命令:SYNC4J\bin\install.cmd tomcat。當給出命令提示時,按 Y 來重新構建 testsync-1.0 模組的資料庫。從 SYNC4J 中運行 SYNC4J\bin\sync4j-tomcat.cmd,然後啟動 Tomcat 伺服器。請注意伺服器端設定;現在可以安裝客戶機了。
用戶端安裝
需要在用戶端安裝資料庫引擎 HSQLDB。然後安裝並配置範例程式碼。設定客戶機應用程式和資料庫要設定客戶機應用程式資料庫,請按下以步驟進行:
下載並解壓 HSQL 資料庫。本文中用 HSQLDB 作為 HSQL 資料庫的安裝目錄。將 HSQL 作為網路伺服器啟動,它帶有一個叫做 test 的資料庫。運行 TESTSYNC\create_table_client.sql 在 HSQL 資料庫中建立類似的表(customer2)。將 HSQL JDBC 驅動程式 HSQLDB\lib\hsqldb.jar 複製到 TESTSYNC\client\lib。在 TESTSYNC\client\config\spds\sources\testsync.properties 中設定客戶機的 JDBC 屬性,如下所示:
| jdbcDriver=org.hsqldb.jdbcDriver urlConnection=jdbc:hsqldb:hsql://localhost/test |
正確地設定使用者名稱稱和口令。然後,運行 TESTSYNC\client\build.bat 來構建用戶端應用程式。運行客戶機應用程式向 Derby 資料庫中的 customer1 表中插入記錄。例如:
| insert into customer1 (userid, password, cl_op_type, clo_op_time) values ('user1', 'pass1', 'N', CURRENT_TIMESTAMP); |
向 HSQL 資料庫中的 customer2 表中插入記錄(請確保 userid 的值與 customer1 中記錄的值不同)。例如:
| insert into customer2 (userid, password, cl_op_type, clo_op_time) values ('user2', 'pass2', 'N', CURTIME()); |
運行 TESTSYNC\client\output\testsync.bat。customer1 表現在應當包含剛才插入 customer2 表中的記錄,而 customer2 表應當包含來自 customer1 表的記錄。
結束語
在本文中,我們討論了在設計通用資料庫複寫解決方案時涉及的一些重要概念和問題。在設計複雜的分布式應用程式時,資源佔用少的嵌入式 Java 資料庫的可用為您提供了一個很好的選擇,同時它還允許使用異構資料庫。對於複製過程和相關問題有很好理解,有助於我們改進這類系統的設計。我們鼓勵您擴充這個樣本,以便用衝突解決方案策略來處理雙向複製,並使用記錄更改資料的自動記錄。