在线计费系统中内存数据库的研究与应用
2012-08-22邹永平
邹永平 毛 蔚
(1.江苏无锡交通高等职业技术学校组织人事处 江苏 无锡 214151;2.江苏无锡交通高等职业技术学校继续教育部 江苏 无锡 214151)
0 引言
图1 系统结构图
为了提高现有的在线计费产品在国际市场的优势,决定通过自主研发一套高度独立的、快速的、安全的、易用的内存数据库,来代替TimesTen[1],同时能够无缝的与现有系统进行对接,并将CustCache、RuleCache进行替换,简化现有系统的复杂度,降低系统的耦合度。通过这套系统,可以在各个计费版本中进行推广,为在线计费系统提供一套完整的、可控的解决方案。这个专为计费系统而生的内存数据库就是Quick Memory DataBase,本文简称QMDB或者MiniDB。
本文主要是针对计费领域中的数据处理,考虑了计费数据的特点和技术难度,摒弃TimesTen的一些特性,增加几点功能:支持多平台运行,QMDB也必须能在AIX、HP、Solaries、Linux和Windows平台上面运行。这是设计的第一个要求,其次,针对计费系统的高可靠性和实时性,QMDB必须能够应对系统发生故障的例外情况,就是主备机同步的。第三,由于计费系统的处理数据都存于Oracle数据库中,所以,QMDB也必须要支持数据与Oracle系统的同步[2-3]。
1 系统结构图
图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 等表示,方便直观。
2 主备机同步模块
2.1 主备同步相关配置
配置文件的配置
QMDB的配置文件是以QuickMDB_XXX.xml命名的,其中“xxx”为内存数据库名,为大写。具体配置项的含义以及配置参考《QuickMDB配置说明》,在这里主要突出与主备机同步模块相关的配置项:
is-rep这个需要配置成“Y”,如果配置为“N”则不启动主备同步进程;
rep-type这表的列的一个属性,这个配置项需要配置成“MDB2MDB”,表示是从 active 同步到 standby。
2.2 QMDB数据同步到备机
应用程序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,(考虑性能,都采用异步方式,不等待备机端响应结果)。
2.3 启动逻辑
第一次启动时,先要判断对端是否已经启动,如果对端没有启动,则本机直接从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,(考虑性能,都采用异步方式,不等待备机端响应结果)。
3 Oracle同步模块
3.1 详细描述
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数据库的纪录数相同
3.2 Oracle增量同步到QMDB
由于某些原因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数据库的纪录数相同
4 小结
引入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).