高级问题!怎样多线程操作队列?

ranranshengqi 2015-06-16 10:42:04
比如,有一个数据表(可以理解为队列不?)中有5000条未完成数据,每条数据需要进行复杂的计算、处理、写入文本文件后才能标记为完成。
现在是单台机器按先进先出的原则逐条处理。领导觉得太慢了,想加几台机器同时处理【数据表是同一个】。

我现在想法是,假如有两台机器,每台机器每五分钟读取一些待处理数据,然后处理。A机器处理ID为单号的,B机器处理ID为双号的。
大家觉得可行吗?MS sql不能select 单双数ID吧。。。

我知道这是一个很笨的方法 ,期待高手们能有更好的方法


...全文
318 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
你可以看看一个服务器在公网,然后许多客户端在(各自的)局域网内,如何保持双向长连接操作。 我在之前贴过一个简单的 tcp 长连接的底层代码的例子。http://bbs.csdn.net/topics/390987992
  • 打赏
  • 举报
回复
引用 5 楼 ranranshengqi 的回复:
关键的问题在于,数据在公网,而工作的几台机器在内网。这样就没有办法通知它们起来工作,除了让它们定时来轮询
如果不在同一个局域网,那么就使用长连接,服务器给客户端推送消息啊。
  • 打赏
  • 举报
回复
实际上,所谓分布式计算,非常简单。上面的很简单模型已经有了完整的框架雏形,只不过实现方法不同而已。 1. 首先需要有一个client负责将任务倒入到系统中,然后通知一个master机器处理这一批次的任务。 2. 然后master通知所有的worker机器这个批次中的每一个任务。 3. worker采取“抢任务”的方式,这样即使是你在任务处理前1分钟才临时增加10台服务器或者减少5台服务器,系统也自动根据各个服务器的负载情况而自动地调配。因为反应比较慢的烂机器,就没有人家好机器“抢”的多。只不过大型的分布式系统通常用master机的内存状态来协调,而不是像上面那样用数据库记录来协调,只是存储上的区别。 4. workder处理完毕之后,根据任务代码编写的业务逻辑,把结果推送到某个地方。例如你的worker可以每当推送结果给某个固定存储地址后,就像client一样去让master机器启动一个reduce任务来合并任务(可以给出积攒了多少内容之后才真正开始合并)。甚至启动一个notify push任务去向前端设备发送一个“请来读取结果”的通知。 分布式处理,是任何一个软件服务公司都最基本的应该掌握的编程知识。不习惯于做这个,跟10几年的走街串巷卖进销存软件的小公司也就差不多了,也就慢慢跟不上最近这几年的时代的步伐了。
ranranshengqi 2015-06-17
  • 打赏
  • 举报
回复
谢谢楼上的高手,受教了!
ranranshengqi 2015-06-17
  • 打赏
  • 举报
回复
关键的问题在于,数据在公网,而工作的几台机器在内网。这样就没有办法通知它们起来工作,除了让它们定时来轮询
ranranshengqi 2015-06-17
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
首先,假设要处理5000个并发任务,可以使用这样的写法。例如我们准备一个“测试条件”集合,随便用顺序号来表示
var condition = Enumerable.Range(0, 5000).ToList();
假设每当接受一个输入编号,进行一项计算,这样模拟
static Random rnd = new Random();

private static bool solve(int x)
{
    return rnd.Next(2) + x == 0;
}
那么要并发执行这5000千个solve方法(输入的x各不相同),则应该这样写
var result = (from x in condition.AsParallel() select solve(x)).ToList();
这就是并发执行这些任务。 对于你的程序来说,如果在一台机器上并发处理这5000条记录,那么就可以用 condition 来一次读取出来5000条数据,用solve 来处理记录(单个记录对应的实体对象代替这里的x变量),最后得到每条记录处理的结果集合,返回统计。 对于plinq 来说,它使用了.net的系统线程池,因此可以根据你的机器的使用情况来自动优化并发数量。所以不用担心、也不用手动规定什么并发数据量。当然如果你想限制最多用30个并发线程,也可以手动规定,例如
var result = (from x in condition.AsParallel().WithDegreeOfParallelism(30) select solve(x)).ToList();
但是通常不必这样多此一举。
大神可能没有明白 简单的说,我现在有一个队列表,其中是有很多条任务,任务队列不断的增加,程序定期访问这个表,得到未处理的任务进行处理,然后处理完成做标记。 如果现在有两台服务器,我可以一台处理单数ID,另一台处理偶数ID的任务。 我希望能有更好的方法
  • 打赏
  • 举报
回复
对于你分布式处理问题,由于比较简单,我们用基本的分布式原则(而且不考虑内外网之分)来设计,不用纠结什么高大上的什么开源框架(.net中也没有类似PLinq那样的现成的框架)。那么可以这样设计: 你可以为你的数据库表加上一个“状态”字段,至少有三种状态值: 1. 未处理。 2. 正在处理。 3. 处理完毕。 然后假设你有n台机器(千万比要想当然地以为固定为5台机器或者2台机器,不然反而造成资源浪费),每台机器都访问这个数据库来“抢夺”一个处于“未处理”状态的记录、并且在同一个事务中把它变为“正在处理”状态。这个操作肯定很快,连查询带改变状态(在同一个事务中)然后读取记录,这三项功能也就几毫秒就做完了。然后就对记录进行你的费时的处理,然后把处理结果送到统一规定的位置,然后处理下一条数据。 这跟你的“A、B”机的说法类似,区别是,这里不假设只能有2台机器。并且注意数据库操作尽可能限制在4、5毫秒之内。 而且也不是什么“每隔5分钟处理一批数据”。应该是收到请求既启动。例如其发布的网页只要被人访问一下,例如 http://192.268.1.203:81/proc1/default.ashx 就触发其启动。 这样,当年任何地方知道有数据产生的时候,改变这里的ip来通知各个机器(机器的ip地址可以配置好)开始启动操作就行了。 根据机器的处理速度的快慢、以及数据本身的不同,可能A机器处理了2100条记录,B机器处理了1850条记录,C机器处理了1050条记录,这都是可能的。 不要想当然地以为需要固定指定“几台机器,每台机器分别处理哪些条记录”。看似简单但是死板的设计会产生很差的性能。
  • 打赏
  • 举报
回复
首先,假设要处理5000个并发任务,可以使用这样的写法。例如我们准备一个“测试条件”集合,随便用顺序号来表示
var condition = Enumerable.Range(0, 5000).ToList();
假设每当接受一个输入编号,进行一项计算,这样模拟
static Random rnd = new Random();

private static bool solve(int x)
{
    return rnd.Next(2) + x == 0;
}
那么要并发执行这5000千个solve方法(输入的x各不相同),则应该这样写
var result = (from x in condition.AsParallel() select solve(x)).ToList();
这就是并发执行这些任务。 对于你的程序来说,如果在一台机器上并发处理这5000条记录,那么就可以用 condition 来一次读取出来5000条数据,用solve 来处理记录(单个记录对应的实体对象代替这里的x变量),最后得到每条记录处理的结果集合,返回统计。 对于plinq 来说,它使用了.net的系统线程池,因此可以根据你的机器的使用情况来自动优化并发数量。所以不用担心、也不用手动规定什么并发数据量。当然如果你想限制最多用30个并发线程,也可以手动规定,例如
var result = (from x in condition.AsParallel().WithDegreeOfParallelism(30) select solve(x)).ToList();
但是通常不必这样多此一举。
tcmakebest 2015-06-17
  • 打赏
  • 举报
回复
多台机器同时处理数据,防冲突就是加一个状态,谁加了这个状态就由谁处理
全栈极简 2015-06-16
  • 打赏
  • 举报
回复
所谓的多线程就是开启多个线程同时执行某个单项任务,最终完成某个事情的过程。但是并不是开启的线程数越多越好,到达一个临界点之后,效率反而会降低。 你首先要做的就是将你的任务进行分解(比如你有5000条数据,开启5个线程,线程1处理1-1000条数据,线程2处理1001-2000条数据,以此类推),然后让线程单独执行各自的操作,最后共同完成这项任务。

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧