锁定老帖子 主题:java如何做到实时-----两种方案
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-11
两种方法
1:临时表然后一个守护进程不停扫表,然后进行任务分发处理 2:所有对关系改变的数据操作前加一个中间层,就是在数据操作的时候写消息然后用jms异步进行处理。用jms来保存和分发任务可以用开源的activemq 现在你看到的很多webgame都是用着两种办法来做建筑升级之类的操作的和你的类似 |
|
返回顶楼 | |
发表时间:2009-11-11
yuanyi_wang 写道 可以在触发器里插入一个message到AQ(Oracle内置的queue服务,在oracle中有个package可以直接操作),再用JMS接受这个消息。
为什么潜意识里认定是oracle?我们所要做到的是与数据库无太大的关系。不管是oracle还是mysql 或者sqlserver都能ok |
|
返回顶楼 | |
发表时间: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 |
|
返回顶楼 | |
发表时间:2009-11-11
“数据库新增了数据就要及时通知应用层做一系列的处理”
功能需求不能于技术实现方案。显然你把需求当成技术实现了。 |
|
返回顶楼 | |
发表时间:2009-11-11
sunnymoon 写道 “数据库新增了数据就要及时通知应用层做一系列的处理”
功能需求不能于技术实现方案。显然你把需求当成技术实现了。 需求不用代码,用什么实现? 没明白意思! |
|
返回顶楼 | |
发表时间:2009-11-11
rovanz 写道
....
只要统一数据库操作的入口不就做到了,你爱杂折腾咋折腾,而且这种方式对数据库没有任何额外的操作 这种方法最好,但需要架构设计师有很丰富的经验,在设计时就考虑到。否则项目成型再改,改动量巨大。
lovemylover 写道
从数据源入手,使用代理模式封装数据源,在其中解析sql命令,如果是涉及指定表的变更操作(如insert、delete、update)等,调用相关应用程序。
这种方法有一个小问题,就是如果高级语言这边调用成功了,而db处理失败了,那也会“调用相关应用程序”,其他就和上面的一样了。
lz说的直接用触发器,这个又有点性能问题。
我建议的做法,搞个中间表,插入时统一插入这个中间表,定时(或按其他规则也行)从中间表插数据到原表。
这样做的好处有二: 1、只要扫描中间表就知道有没有insert数据,而如果设置转储时间间隔(就是移数据到原表的间隔)较小的话,中间表肯定比原表小很多,性能影响小。 2、这样搞虽说也要改代码,但比较好改。可以想象,如果直接把原表当中间表来用,然后建个新表放原表的数据,这样java端什么代码都不用改。或者把原表的表名全部替换成中间表的表名,其他工作对java(或其他语言)端是透明的。而转储工作可以写个简单的过程由db来做,程序员根本不用考虑这些问题。
|
|
返回顶楼 | |
发表时间:2009-11-11
ubotutwin 写道
rovanz 写道
....
只要统一数据库操作的入口不就做到了,你爱杂折腾咋折腾,而且这种方式对数据库没有任何额外的操作 这种方法最好,但需要架构设计师有很丰富的经验,在设计时就考虑到。否则项目成型再改,改动量巨大。
lovemylover 写道
从数据源入手,使用代理模式封装数据源,在其中解析sql命令,如果是涉及指定表的变更操作(如insert、delete、update)等,调用相关应用程序。
这种方法有一个小问题,就是如果高级语言这边调用成功了,而db处理失败了,那也会“调用相关应用程序”,其他就和上面的一样了。
lz说的直接用触发器,这个又有点性能问题。
我建议的做法,搞个中间表,插入时统一插入这个中间表,定时(或按其他规则也行)从中间表插数据到原表。
这样做的好处有二: 1、只要扫描中间表就知道有没有insert数据,而如果设置转储时间间隔(就是移数据到原表的间隔)较小的话,中间表肯定比原表小很多,性能影响小。 2、这样搞虽说也要改代码,但比较好改。可以想象,如果直接把原表当中间表来用,然后建个新表放原表的数据,这样java端什么代码都不用改。或者把原表的表名全部替换成中间表的表名,其他工作对java(或其他语言)端是透明的。而转储工作可以写个简单的过程由db来做,程序员根本不用考虑这些问题。
其实触发器有弊端的,有时候触发器 不触发 不知道你们是否遇到过 你说的两点好处 ,我也是这么跟老大说的 ,老大说这个数据库都是弄好的,不能动,这个也不是我来做,只是他要我想办法,我就说出我的观点,你的这种方法不就是我的第二种方法吗?扫描中间临时表 |
|
返回顶楼 | |
发表时间:2009-11-11
数据库新增加数据总是有程序往里面塞的吧
塞数据的程序在添加数据后,就通知一个监听程序,让监听程序去数据库中去取 (可以传一个新添数据的最小Id给监听程序,让它从这个id之后取最新数据) |
|
返回顶楼 | |
发表时间:2009-11-11
jjxlcsw 写道 可能是直接通过数据库的工具更新数据的。 根本就不走jdbc
这个就用线程扫描了(可以使用中间表或试图提取数据), 感觉触发器比这个要低效点 |
|
返回顶楼 | |
发表时间:2009-11-11
实时,我觉得有点偷换概念,这个一般用在生产领域
其实这里要做的就是数据同步,那么楼上已经有很多解决方案了 用jms是一个比较好的方案,可以解决集群、或单机宕机问题 |
|
返回顶楼 | |