2010-08-18 36 views
2

我们公司正在运行Java应用程序(在单个CPU Windows服务器上)从TCP/IP套接字读取数据并检查特定条件(使用正则表达式),如果找到匹配,则将数据存储在MySQL数据库。数据是巨大的,并且以800个记录/秒的速率读取,并且大约70%的记录将是匹配的记录,所以涉及很多数据库写入。该程序正在使用LinkedBlockingQueue来处理数据。生产者类只是读取记录并将其放入队列中,并且消费者类从队列中移除并执行处理。在我的场景中,单个Java线程比多线程更好吗?

所以问题是:如果我使用多个消费者线程而不是单个线程,它会有所帮助吗?在上述场景中线程是否真的有帮助(因为我使用单个CPU)?我正在寻找关于如何加速的建议(无需更改硬件)。

任何建议将非常感激。谢谢

+0

核心数量仅与具有大量cpu绑定应用程序的线程数量相关。我会说绝大多数应用程序不是。 – CurtainDog 2010-08-18 04:39:58

+1

为什么'LinkedBlockingQueue'?数据是否必须按顺序存储在数据库中? – 2010-08-18 04:42:43

+0

我认为你需要在修改应用程序之前对其进行配置。您必须计算IO(网络数据到达)和CPU的百分比利用率。将cpu的数据分批处理是另一种可能的优化。但真正的问题是你真的有性能问题? – questzen 2010-08-18 06:53:07

回答

1

单线程能跟上传入的数据吗?数据库能跟得上传出的数据吗?

换句话说,哪里是瓶颈?如果你需要使用多线程,那么在并发实用程序中查看Executor概念(在Executors助手类中有很多选择),因为这将处理所有你并不特别感兴趣的乏味细节。

我个人的直觉是瓶颈是数据库。这里索引和RAM有很多帮助,但这是一个不同的问题。

+0

同意。 '瓶颈'是重点。 – 2010-08-18 04:40:25

1

很可能多线程会有所帮助,但它很容易测试。使其成为可配置的参数。找出每秒可以做多少个1线程,2线程,4线程,8线程等。

2

简单:试试看看。

这是你在争论的任何一方争论几个问题的问题之一。但听起来你已经拥有大部分的基础设施。只需创建另一个消费者线程并查看是否有帮助。

但您需要问自己的第一个问题:

有什么更好?
你如何衡量更好?

回答这两个问题,然后尝试。

1

首先:
明智的做法是使用java 5 concurrent api

如果您的应用程序的ExecutorService这是很容易改变使用的线程数量周围创建创建应用程序。例如:您可以创建一个线程池,其中线程数由配置指定。所以,如果你想改变线程的数量,你只需要改变一些属性。

关于你的问题:
- 关于您的插座阅读:据我所知,这是不是有用的(如果可能的话)有两个线程从一个套接字读取数据。只需使用一个读取套接字的线程,但尽可能少地使该线程中的动作(例如,读取套接字 - 将数据放入队列中 - 读取套接字 - 等等)。
- 关于队列的消耗:如上所述构建这个部分是明智的,这样就很容易改变消耗线程的数量。
- 注意:你无法真正预测哪种方法更好,可能会有另一部分是瓶颈,等等。只有监视器/分析可以让您真实地了解您的情况。但是如果你的应用程序是按照上面的方式构建的,那么用不同数量的线程来测试真的很容易。

总之所以:
- 制作部分:一个线程,只有从插座读取和队列提出
- 消费部分:各地ExecutorService的建立,因此很容易适应消费线程的数量
然后使用分析确定瓶颈,并使用AB测试为您的系统定义最佳消耗线程数

0

作为一个u在我之前的问题中有更新:

我们在单个消费者线程和多个线程之间运行了一些比较测试(添加了5,10,15等)并监视了尚未处理记录的队列大小。这个差别是微乎其微的,在线程数量超过25的情况下(与运行5个线程相比),更多的... que大小变得稍大一些。这引出了我的结论:维护线程的开销超过了处理的好处。也许这可能是我们的场景所特有的,但只是提到我的观察。

当然(正如其他人指出的)瓶颈是数据库。这是通过在mySQL中使用多重插入语句而不是单个插入来处理的。如果我们没有这个开始,我们不能处理这个负载。

最终结果:我还不确定多线程如何为处理时间带来好处。也许它有其他的好处......但我只从处理时间的角度来看。如果您有任何相反的经历,请让我们听听。

再次感谢您的所有输入。

+0

哎呀..这个帖子是来自阿卜杜拉,但得到了不同的身份证。 – Abdullah 2010-08-18 23:47:33

0

在您的场景中,a)处理最小b)只有一个CPU c)数据直接进入数据库,添加更多线程不太可能会有所帮助。换句话说,前端和后端线程是I/O绑定的,在中间处理最少。这就是为什么你没有看到很大的改进。

你可以做的是尝试有三个阶段:1st是一个单线程从套接字中提取数据。第二个是处理的线程池。 3rd是一个服务于数据库输出的单线程。如果输入速率变化,这可能会产生更好的CPU利用率,但会以输出队列的暂时增长为代价。如果不是这样,吞吐量将受限于写入数据库的速度,无论您拥有多少线程,然后只需一个读取进程写入线程即可脱身。