鄒永平 毛 蔚
(1.江蘇無錫交通高等職業技術學校組織人事處 江蘇 無錫 214151;2.江蘇無錫交通高等職業技術學校繼續教育部 江蘇 無錫 214151)

圖1 系統結構圖
為了提高現有的在線計費產品在國際市場的優勢,決定通過自主研發一套高度獨立的、快速的、安全的、易用的內存數據庫,來代替TimesTen[1],同時能夠無縫的與現有系統進行對接,并將CustCache、RuleCache進行替換,簡化現有系統的復雜度,降低系統的耦合度。通過這套系統,可以在各個計費版本中進行推廣,為在線計費系統提供一套完整的、可控的解決方案。這個專為計費系統而生的內存數據庫就是Quick Memory DataBase,本文簡稱QMDB或者MiniDB。
本文主要是針對計費領域中的數據處理,考慮了計費數據的特點和技術難度,摒棄TimesTen的一些特性,增加幾點功能:支持多平臺運行,QMDB也必須能在AIX、HP、Solaries、Linux和Windows平臺上面運行。這是設計的第一個要求,其次,針對計費系統的高可靠性和實時性,QMDB必須能夠應對系統發生故障的例外情況,就是主備機同步的。第三,由于計費系統的處理數據都存于Oracle數據庫中,所以,QMDB也必須要支持數據與Oracle系統的同步[2-3]。
圖1說明:
a)系統結構圖中右邊的虛線部分表示與其他主機進行數據傳輸。
b)接口進程G通過消息方式與其他進程交互,不僅限于數據接收進程F,還可以包括Oracle數據更新進程(指O-racle數據變更后,數據需要同步過來)、沖值進程、開戶進程、SID等等沒,只要這些進程滿足我們約定的格式要求就可以。
c)外部系統(指除去本機上面運行的計費相關進程),所有涉及非只讀表的修改(包括插入、更新、刪除)都必須通過接口進程G處理,對于Java進程可以直接從Oracle讀取數據,對于C++的程序,則可以通過系統接口直接訪問。
d)本次設計主要考慮主要需求,對于像遠程客戶端的設計、ODBC設計,暫時不予考慮,隨著項目的深入再追加設計。
e)程序中關于數據存儲,采用 INT8、INT16、 INT32、INT64來表示,而不是用short。
f)Int、long 等表示,方便直觀。
配置文件的配置
QMDB的配置文件是以QuickMDB_XXX.xml命名的,其中“xxx”為內存數據庫名,為大寫。具體配置項的含義以及配置參考《QuickMDB配置說明》,在這里主要突出與主備機同步模塊相關的配置項:
is-rep這個需要配置成“Y”,如果配置為“N”則不啟動主備同步進程;
rep-type這表的列的一個屬性,這個配置項需要配置成“MDB2MDB”,表示是從 active 同步到 standby。
應用程序QMDB里的數據,這個數據需要同步到備機,以保證QMDB與備機的一致。
2.2.1 流程說明
1)應用程序對QMDB變更的同時將變更動作以以下的形式寫入主備機刷新緩存隊列:

2)mdbFlushRep進程從刷新緩存隊列中取出數據并生成相應的文件,具體情況如下:初始化生成的文件名為Rep_***,其中***為進程ID,當主備機同步緩存中的記錄條數達到2000條的時候或同步時間間隔超出配置大小(配置項:log-time)或文件大小超出配置大小(配置項:file-size),則重命名Rep_PID為Rep_PID.xxxx.OK,其中xxxx為文件序列號。并重新生成Rep_***(其中***為進程ID)文件。
3)啟動mdbRep進程用于讀取文件記錄,并轉換成相應的SQL語句發送備機執行。
2.2.2 流程操作
1)從日志目錄中獲取Rep_xxxx.*.OK文件(其中xxxx表示進程ID,*表示文件編號)(.ok文件才會被同步);
2)解析Rep_xxxx.*.OK文件中的每條記錄,生成相應的SQL并形成主備交互協議報文發送到備機執行,處理完后刪除Rep_xxxx.*.OK,(考慮性能,都采用異步方式,不等待備機端響應結果)。
第一次啟動時,先要判斷對端是否已經啟動,如果對端沒有啟動,則本機直接從Oracle上載數據,上載完畢,數據庫處于正常運行狀態。
如果對端已經啟動,則首先從備機上載數據,發送“數據從備機上載”的命令。這個流程是按照單表進行的,表上面有狀態,主機收到同步的指令后,會把所有需要同步數據的表狀態設定為“待同步”,然后取一個表,將其狀態改為“正在同步”,此時這個表的變更數據需要落地,當數據同步完畢,表狀態變為“正常同步”,換句話說,所有同步的文件都須要落地。當所有的表都同步完畢,數據庫處于正常狀態。
流程說明:
1)應用程序對QuickMDB變更的同時將變更動作以一下的形式寫入主備機刷新緩存隊列:

2)mdbFlushRep進程從刷新緩存隊列中取出數據并生成相應的文件,具體情況如下:
初始化生成的文件名為Rep_***,其中***為進程ID,當主備機同步緩存中的記錄條數達到2000條的時候或同步時間間隔超出配置大小(配置項:log-time)或文件大小超出配置大小 (配置項:file-size),則重命名 Rep_PID為Rep_PID.xxxx.OK,其中xxxx為文件序列號.并重新生成Rep_***(其中***為進程ID)文件。
3)啟動mdbRep進程用于讀取文件記錄,并轉換成相應的SQL語句發送備機執行。
流程操作:
1)從日志目錄中獲取Rep_xxxx.*.OK文件(其中xxxx表示進程ID,*表示文件編號)(.ok文件才會被同步);
2)解析Rep_xxxx.*.OK文件中的每條記錄,生成相應的SQL并形成主備交互協議報文(見上面的協議說明)發送到備機執行,處理完后刪除Rep_xxxx.*.OK,(考慮性能,都采用異步方式,不等待備機端響應結果)。
1)QMDB全量上載Oracle 數據是在QMDB創建這個環節完成的,當創建好表空間,表結構等的時候就開始上載數據了。上載Oracle中哪些表的數據是根據QMDB的配置項(QuickMDB_xxx.XML)來決定的,即創建了哪些表就需要上載哪些表的數據例如:

圖2 XML內容,配置了表cust,上載的時候就會上載oracle中cust表的數據
2)為了提高上載效率和速度,QuickMDB采用了多線程上載的方法,即為每個表空間創建一個線程,每個表空間的下的表就用對應的線程加載。
3)上載步驟:
(1)根據配置項拼裝出查詢語句,插入語句等;(2)根據查詢語句得到oracle的返回結果集;
(3)根據結果集拼裝插入語句,插入到QuickMDB中。
3.1.1 驗證同步結果
啟動mdbSQL,命令如下:mdbSQL dsn名輸入如下命令:select count(*)from表名查看紀錄數是否和oracle數據庫的紀錄數相同
由于某些原因Oracle數據庫表中的紀錄優先于Quick-MDB發生變化了,這時候需要將Oracle表中的增量的紀錄同步到QuickMDB中,以保證Oracle表和QuickMDB表的數據一致性。
3.2.1 詳細描述
假設A表發生增量變化,同步流程如下:
1)Oracle中存在一個對應于A表的觸發器,當A表發生變化時,觸發器會向MDB_CHANGE_NOTIF表插入一條描述A表變化的紀錄,結構如表1。

表1 MDB_CHANGE_NOTIF表結構
2)mdb_change_notify_seq表結構如表2。

表2 mdb_change_notify_seq表結構
根據dsn_name查詢mdb_change_notify_seq表,得到Update_time,然后用 Update_time去查詢MDB_CHANGE_NOTIFf表,查出 MDB_CHANGE_NOTIF表中Update_time比mdb_change_notify_seq表中Update_time大的紀錄,即查出還沒有更新的紀錄,根據查出紀錄的Key_info和Table_name字段找出需要更新呢的整條紀錄更新到QuickMDB中。
3)oracle中存在Job,定時的掃描mdb_change_notify_seq表,找出其中最小的Update_time,然后用該Update_time去刪除MDB_CHANGE_NOTIF表中所有時間比Update_time小的紀錄,即刪除所有IP已經更新過的紀錄。
3.2.2 樣例
mdb_change_notify_seq表存在一條紀錄:
ip:10.40.45.4;dsn_name:mdbTest;update_time:2010-11-15 01:00:00
mdb_change_notify表存在一條紀錄:
charge_notify_id:1;Table_name:cust;Key_info:5;Update_time:2010-11-1502:00:00;Action_type:I
從mdb_change_notify_seq表中紀錄看出,mdbTest最后一次更新時間為2010-11-15 01:00:00,而同步表中有一條紀錄,update_time 為 2010-11-15 02:00:00,比最后更新時間還要晚,也就是這條記錄還沒更新,cust的主鍵為cust_id,通過Key_info:5, 得到如下查詢語句:select*from cust where cust_id=5,執行得到需要更新的紀錄,又根據Action_type:I,得知更新操作為插入,于是組裝Insert語句,插入到QMDB中,并更新mdb_change_notify_seq表的update_time字段為2010-11-15 02:00:00。
3.2.3 驗證同步結果
啟動mdbSQL,命令如下:mdbSQL dsn名輸入如下命令:select count(*)from表名查看紀錄數是否和oracle數據庫的紀錄數相同
引入QMDB內存數據庫系統后,對于計費系統帶來的一些明顯的優勢。首先,QMDB作為一個獨立的系統,通過類似ODBC接口的形式,被應用程序調用,采用動態連接庫的方式加載到應用系統中,QMDB的任何變動和升級,都不會影響到應用程序,所以系統可以在不影響應用的情況下升級、修正;其次,可以解決系統中存在多種數據的情況,因為目前系統中的數據存儲機制非常復雜,有Oracle數據、TimesTen數據、CustCache數據和RuleCache數據,每次變更表結構或者增加表信息,都需要變動相應的應用代碼,這給應用帶來了一定的復雜度和不穩定性,開發人員不得不抽出一定的時間進行開發、驗證,測試也要分配人員進行相關的測試驗證,這樣毫無疑問會分散開發、測試人員的精力。
通過QMDB內存數據庫,數據的存儲機制將變為內存數據庫數據和Oracle數據兩種,極大地簡化系統的復雜度,而且當應用的表結構發生變動時,不必修改相應的代碼,只要變更一下腳本就可以處理,讓開發人員有更多地精力去處理業務邏輯;第三,由于現有的內存數據庫TimesTen的價格十分昂貴,采用QMDB可以降低產品的采購成本,創造市場機會,提高企業利潤。
[1]劉云升.現代數據庫技術[M].1 版.北京:國防工業出版社,2009:238-314
[2]朱穎輝.OCS 在線計費系統解決方案[J].電信網技術,2010(1).
[3]周媛,苗耀峰.內存數據庫及其技術淺談[J].煤炭技術,2011(11).