日期:2014-05-18  浏览次数:20446 次

使用数据库来进行图像分布式运算中的问题
当前有个应用,需要数据库作同步,我想了很久,有些问题需要请各位高人指点一下。
  在图像运算中,有些需要接近实时运算,例如,每秒钟需要运算20次以上。但是算法又太复杂,于是我计划使用LAN上的N台机机进行分布式运算,其中的N可能是随时变化的,现在大致计划30台左右。而且每台客户机的速度也可能不一样。数据库平台没有定,SQL或ORACLE 均可,算法使用 C++.net 或者C# 来实现。 
  我是这么构想的。算法是存储在EXE文件中,客户机执行这个EXE。
服务器上的表A:内容为需要运算的图片,定段为:
  int id //主键
  string FileName //源图片的定位
  int RunState //运算状态
  string CFileName //结果图片的输出位置
  服务器上对应每个需要运算的图像生成1张表,暂名为B。其字段为:
  int ID, //主键
  int PictID, //表A的对应ID
  int LineNO, //行号
  int Channel, //通道号,如果返回的结果不是灰度图,才需要这个字段
  int RunState, //当前运算情况
  string Count, //返回的结果

  客户机根据表A的内容,确定当前需要运算的源图,查找对应的表B,查看有哪些行还没有被运算,然后运算这个行。因为可能要跨行获取运算所需的参数,因此要先载入整个源图(如果已经下载当然就不用重新下了),然后将源图和需运算的行号输入到算法,算法计算出这一行的结果,将它转换成 char[],然后输出到表B/Count。
  当然了,里面的数据和文件同步算法很简单,就此略过。图像与字符串的相互转换已经完成,这个也不复杂。
  在数据库效率方面有两个限制:
  1.数据库的写入阶段需要锁定,否则会造成查询用户的返回错误。
  2.太多的连接或者频繁的打开关闭都会影响数据库的性能
  因为 1 和 2 的限制,使我不能采用频繁打开和关闭连接的方法,同时又不能打开连接,直到完成运算并写入数据才关闭。为此,我想了另外的一个方法,就是将结果字符串不写入数据表格中,将它以文本文件的方式传入文件服务器,然后连接到表B,将运算状态写入即可。
  请问这样做的话,效率是否会高一些?还会出现什么问题?
  事实上几乎所有的图像算法都是遂行遍历的,因此这个构架可以大范围推广,并且可以在WAN上运行。最后我打算用 JAVA 把算法和数据库操作都写成跨等平台的,MAC,UNIX都能够运行。

------解决方案--------------------
在数据库效率方面有两个限制: 
1.数据库的写入阶段需要锁定,否则会造成查询用户的返回错误。 
2.太多的连接或者频繁的打开关闭都会影响数据库的性能 
这个是并发问题,应该用事务隔离呀,没必要老断开老连接吧
------解决方案--------------------
可能出现的问题
运算端死掉, 解决办法-》某客户端一担开始进行某数据库中,来源数据行进行处理,对当行数据做处理中标记,统计记录当前数据库时间,,当其他客户端需要进行新的数据行运算时,查询当前正在运行的数据行,的开始运行时间,发现当前行处理时间过长(看你实际业务中算做异常的时间范围),则取代带他,自己去运算,同时覆写开始运算时间(当然也可以你做一个服务器端软件来做时时监控的方式实现)

------解决方案--------------------
1-2张图片肯定可能比单机慢
何况还是1秒处理20多张图片?
,,,因为你这个处理办法,,存在机器性能差异,,读取数据库时间,,,等
怎么能和一切内存搞定,,,何况现在电脑CPU又NB,,,做好多线程就搞定了
但是只要没有其他技术上的问题,,,,在处理大批量的图片时
绝对性能会优异很多,。。
所以建议一次性,,,从数据库度取N张图片(这个需要你自己多测试看怎样的情况是最优的)
别一张一张搞

------解决方案--------------------
1.并发问题,应该用事务隔离呀,没必要老断开老连接
2.注意死锁,多测试看看数据。
3.。。。,还在探索
------解决方案--------------------
你可以考慮參考那種群集服務器實現方式,,,
网络负载平衡群集(简称NLB)
實現這種負載分配的問題

你圖片量大,,,牽涉個數據傳輸問題,,自然速度快不了,,,
要不處理完畢后圖片別回傳,,,就存在本地,,,只對數據庫中數據行,,做完成標記
所有行被標記完畢后,,再通過服務器端程式,,,去一一copy每個運算節點的文件
整合,並檢測是否有漏掉的,,,
------解决方案--------------------
那就只有一个批次一个批次处理完毕后上传
在服务器端,,做一个队列,,
一个客户端完成一个批次的图片处理,则在这个队列上加入,,,并传回客户端的完整的完成图片的绝对路径文件夹名,已经完成的图片张数
由服务器端主动去客户端拷贝已处理完的整个图片包,,,拷贝完毕后验证图片张数是否与客户提交的数量一致。。。
考虑到客户端挂掉情况,,可以在服务器加入重试次数,,,

建议在数据库做客户端分发图片批次的时候,,,再做一个总表,,已一个编号到一个编号为一行,,,把整行作为一个用户一次读取来标实,就不需要一次update大量标识行了, ,,
------解决方案--------------------
其实你这个程式数据库上的问题不大,,。
计算部分又在客户端,只要你一次拷贝足够量的图片到客户端,不太可能发生客户端频繁去访问服务器端的情况
主要是copy过来copy过去的时候,需要在服务器端做好输出队列,接收对列,避免大量的copy并发

当然如果条件允许,,,直接一次性让服务器用udp协议,像飞鸽传书一样(反正网络上又有源代码,借鉴过来用三),一次把处理源丢出去,基本就没有out数据的时候的问题,而接受的时候,只要服务器段有个数据表,来存储copy请求队列,基本就完全解决的并发问题了,,
但这必须要求客户端硬盘和服务器端硬盘一样大了, ,,,

还是得看你实际情况,和数据量大小问题
------解决方案--------------------
嘛。。。反正你数据源放哪哪就是瓶井
毕竟图片拷贝,,,及站网络,,又站硬盘读写,,,,
在我看来,,,应该多个数据源,,,来减轻这个问题,,,
把图片,,,多少编号到多少编号放在哪,,,
路径放在数据库里,,,然后让客户端分别读,,这样才是最好的办法,,,


------解决方案--------------------
不我的意思是,,,服务器一个完整的,,,数据源
分别切成4-7分,,分别放在4-7个比较好的电脑中(各自只放属于他的那一份,不重复),,,
然后让客户端根据数据库的中的绝对路径,,,去对应 小数据源中获取数据,,,