论坛首页 Java企业应用论坛

java如何做到实时-----两种方案

浏览 20131 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-11-11  
两种方法
1:临时表然后一个守护进程不停扫表,然后进行任务分发处理
2:所有对关系改变的数据操作前加一个中间层,就是在数据操作的时候写消息然后用jms异步进行处理。用jms来保存和分发任务可以用开源的activemq

现在你看到的很多webgame都是用着两种办法来做建筑升级之类的操作的和你的类似
0 请登录后投票
   发表时间:2009-11-11  
yuanyi_wang 写道
可以在触发器里插入一个message到AQ(Oracle内置的queue服务,在oracle中有个package可以直接操作),再用JMS接受这个消息。


为什么潜意识里认定是oracle?我们所要做到的是与数据库无太大的关系。不管是oracle还是mysql 或者sqlserver都能ok
0 请登录后投票
   发表时间:2009-11-11  
SQL2000+存储过程+触发器+DLL调用的方法来实现数据实时转换
在GPS/GIS系统中经常会遇到坐标系问题,一般GPS模块输出的位置数据是参考84坐标的,而在系统应用的时候,特别在政府应用系统中的GIS电子地图常常采用地方坐标系。为了能够正确地在电子地图上显示移动终端的位置,需要将位置数据从84坐标转换到地方坐标。在实时环境下,如何自动完成转换,这里采用了SQL2000+存储过程+触发器+DLL调用的方法来实现。
1)背景
环境:windows2000+sp4
数据库:SQL2000
动态库制作:VB
结构:C/S
2)工作思路
采用TCP/IP将移动终端的位置数据传递到服务器,存入数据库的实时数据表a中;
在该实时数据表a上创建触发器(FOR INSERT),每当实时数据表a中记录插入的时候,触发器被激活,执行存储过程datatrans,该存储过程自动初始化COM实例,调用DLL中的转换方法,实现位置数据的坐标转换,将转换后的数据插入新的实时数据表b。
3)主要函数
SQL Server中的7个用于COM操作的扩展存储过程。
当需要操作一个COM对象时,首先通过调用sp_OACreate建立一个COM对象的实例,然后通过一系列的sp_OAGetProperty、sp_OASetProperty和sp_OAMethod调用完成需要完成的任务,在完成对COM对象的操作后,还需要调用sp_OADestroy释放该对象。每个调用返回一个整数类型的HRESULT,如果调用成功则该值为0。7个存储过程分别是:sp_OACreate 建立自动操作对象的一个实例
sp_OADestroy 释放一个对象的实例
sp_OAGetErrorInfo 从其他过程返回的HRESULT中获得错误描述信息
sp_OAGetProperty  把一个对象的属性存储在结果集或局部变量中
sp_OASetProperty  改变一个对象属性的值
sp_OAMethod 执行对象的方法,向方法传递参数,并得到返回值
sp_OAStop 关闭SQL Server的自动操作环境  
4)代码
a)VB实现的DLL
打开VB6.0的IDE,按照ActivX DLL模版新建工程gpsSQLCOM,
CLASS的名称GPSFunction,工程名称gpsSQLCOM
实现转换
Public Function GetGpsDataSH(process_tmpGpsData As String) As String
‘输入process_tmpGpsData为84坐标数据
‘输出GetGpsDataSH=为地方坐标数据
END Fnction
编译输出DLL
b) 存储过程datatrans的实现
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[gps_datatrans]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[gps_datatrans]
GO

CREATE PROCEDURE gps_datatrans
@gpsvid varchar(25),
@gpsdata varchar(50)
AS
--定义用到的变量
declare @obj int,@re int
declare @VehileIDstring varchar(30)
declare @Mobilerestring varchar(30)
declare @Gpsadatastring varchar(30)
declare @sqlTable varchar(30)
declare @insertstring nvarchar(1000)

SET NOCOUNT ON
set @sqlTable='b'

--创建调用实例
exec @err=sp_OACreate 'gpsSQLCOM.GPSFunction', @obj out
if @err<>0 goto lberr --如果创建失败,则进行错误处理

--调用DLL中的位置转换函数
exec @err=sp_OAMethod @obj,'GetGpsDataSH',@Gpsadatastring out,@gpsdata
if @err<>0 goto lberr --如果调用错误,则进行错误处理
print '返回的结果是:' + @Gpsadatastring

--将结果存入数据表b,采用sp_executesql可以动态产成sql语句
set @insertstring=' INSERT INTO @sqlTabl (VEHICLEID,Time , DATA)
       VALUES( @VehileIDstring,@Datetimestring,@Gpsadatastring )'
exec sp_executesql @insertstring,N'@VehileIDstring varchar(30),
@Gpsadatastring varchar(50) ,
@sqlTabl ',
                @gpsvid,,@Gpsadatastring, @sqlTabl
--完成后释放实例
exec sp_OADestroy @obj
return

lberr:
--错误处理
c)触发器实现
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[gps_insert]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
drop trigger [dbo].[gps_insert]
GO

CREATE TRIGGER gps_Insert
ON [a]
FOR INSERT
AS
BEGIN

declare @gpsvid varchar(50)
declare @gpsdate varchar(50)

SET NOCOUNT ON
--获得新插入数据
select @gpsmobile =[feild1],
       @gpsvid=[ feild2],
       @gpsdata=[ feild3]

FROM a AS P INNER JOIN Inserted AS I
ON P. feild1 = I. feild1
--执行转换存储过程
exec gps_datatrans @gpsvid, @gpsdata

END
5)小节
采用这样的方式,以数据库为中心,转换灵活,只要制作不同的转换函数,就可以灵活实现多种坐标各式的转换,而通过触发器激活,不必使用专门的进程不停的来轮讯来发现新纪录,系统负担低。而且利于不同的前置系统接入也非常容易。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/black_ben/archive/2006/02/16/593854.aspx
0 请登录后投票
   发表时间:2009-11-11  
“数据库新增了数据就要及时通知应用层做一系列的处理”
功能需求不能于技术实现方案。显然你把需求当成技术实现了。
1 请登录后投票
   发表时间:2009-11-11  
sunnymoon 写道
“数据库新增了数据就要及时通知应用层做一系列的处理”
功能需求不能于技术实现方案。显然你把需求当成技术实现了。


需求不用代码,用什么实现? 没明白意思!
0 请登录后投票
   发表时间:2009-11-11  

 

rovanz 写道
....
只要统一数据库操作的入口不就做到了,你爱杂折腾咋折腾,而且这种方式对数据库没有任何额外的操作

    这种方法最好,但需要架构设计师有很丰富的经验,在设计时就考虑到。否则项目成型再改,改动量巨大。

 

lovemylover 写道
从数据源入手,使用代理模式封装数据源,在其中解析sql命令,如果是涉及指定表的变更操作(如insert、delete、update)等,调用相关应用程序。

    这种方法有一个小问题,就是如果高级语言这边调用成功了,而db处理失败了,那也会“调用相关应用程序”,其他就和上面的一样了。

 

     lz说的直接用触发器,这个又有点性能问题。

 

     我建议的做法,搞个中间表,插入时统一插入这个中间表,定时(或按其他规则也行)从中间表插数据到原表。

 

     这样做的好处有二:

         1、只要扫描中间表就知道有没有insert数据,而如果设置转储时间间隔(就是移数据到原表的间隔)较小的话,中间表肯定比原表小很多,性能影响小。

         2、这样搞虽说也要改代码,但比较好改。可以想象,如果直接把原表当中间表来用,然后建个新表放原表的数据,这样java端什么代码都不用改。或者把原表的表名全部替换成中间表的表名,其他工作对java(或其他语言)端是透明的。而转储工作可以写个简单的过程由db来做,程序员根本不用考虑这些问题。

 

0 请登录后投票
   发表时间:2009-11-11  
ubotutwin 写道

 

rovanz 写道
....
只要统一数据库操作的入口不就做到了,你爱杂折腾咋折腾,而且这种方式对数据库没有任何额外的操作

    这种方法最好,但需要架构设计师有很丰富的经验,在设计时就考虑到。否则项目成型再改,改动量巨大。

 

lovemylover 写道
从数据源入手,使用代理模式封装数据源,在其中解析sql命令,如果是涉及指定表的变更操作(如insert、delete、update)等,调用相关应用程序。

    这种方法有一个小问题,就是如果高级语言这边调用成功了,而db处理失败了,那也会“调用相关应用程序”,其他就和上面的一样了。

 

     lz说的直接用触发器,这个又有点性能问题。

 

     我建议的做法,搞个中间表,插入时统一插入这个中间表,定时(或按其他规则也行)从中间表插数据到原表。

 

     这样做的好处有二:

         1、只要扫描中间表就知道有没有insert数据,而如果设置转储时间间隔(就是移数据到原表的间隔)较小的话,中间表肯定比原表小很多,性能影响小。

         2、这样搞虽说也要改代码,但比较好改。可以想象,如果直接把原表当中间表来用,然后建个新表放原表的数据,这样java端什么代码都不用改。或者把原表的表名全部替换成中间表的表名,其他工作对java(或其他语言)端是透明的。而转储工作可以写个简单的过程由db来做,程序员根本不用考虑这些问题。

 


其实触发器有弊端的,有时候触发器 不触发 不知道你们是否遇到过 你说的两点好处 ,我也是这么跟老大说的 ,老大说这个数据库都是弄好的,不能动,这个也不是我来做,只是他要我想办法,我就说出我的观点,你的这种方法不就是我的第二种方法吗?扫描中间临时表
0 请登录后投票
   发表时间:2009-11-11  
数据库新增加数据总是有程序往里面塞的吧
塞数据的程序在添加数据后,就通知一个监听程序,让监听程序去数据库中去取
(可以传一个新添数据的最小Id给监听程序,让它从这个id之后取最新数据)
0 请登录后投票
   发表时间:2009-11-11  
jjxlcsw 写道
可能是直接通过数据库的工具更新数据的。 根本就不走jdbc

这个就用线程扫描了(可以使用中间表或试图提取数据),
感觉触发器比这个要低效点
0 请登录后投票
   发表时间:2009-11-11  
实时,我觉得有点偷换概念,这个一般用在生产领域

其实这里要做的就是数据同步,那么楼上已经有很多解决方案了
用jms是一个比较好的方案,可以解决集群、或单机宕机问题
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics