2012-07-16 89 views
1

我有一个包含300万条记录的数据库表。一个java线程从表中读取10,000条记录并处理它。处理后,它跳到下一个10000,依此类推。为了加速,我有25个线程完成相同的任务(读取+处理),然后我有4个物理服务器运行相同的Java程序。所以有效地,我有100个线程做同样的工作(阅读+处理)。在多个进程间平均分配数据库记录

我使用的策略是有一个SQL过程,抓取下一个10,000条记录并将它们标记为由特定线程处理。但是,我注意到线程似乎在等待一段时间,试图调用该过程并获得响应。还有什么其他的策略可以用来加速这个数据选择过程。

我的数据库服务器是MySQL和编程语言是Java

回答

3

处理这种情况的惯用方式是设计模式。而在Java领域实现它的惯用方式是使用

本质上,您需要一个主服务器读取记录并将其推送到JMS队列。然后你会有任意数量的消费者从队列中读取并相互竞争。您要如何详细实现这一点取决于您:是否要发送带有整个记录或只有ID的消息?一条消息或每条消息记录中的所有10000条记录?

另一种方法是,检出。但学习曲线有点陡峭。

+0

我用这种方法可以看到的唯一问题是“写入”队列会被卡住。瓶颈处于驱动器的读/写周期,我不认为他能做任何事情。 – 2012-07-16 16:55:08

+0

@Tomasz:使用jms方法,如果消费者由于某些原因而死亡,那么我将拥有一组不会处理的消息,除非我提供某种额外的检查机制。用我目前的程序方法,我能够绕过这种情况。如果一台服务器出现故障,其余的服务器将继续工作并承担额外的负载。 – prashant 2012-07-16 18:23:52

+0

@prashant:如果您将消费者配置为事务性消息,如果消费者无法处理某些消息(通过死亡,抛出异常,无论如何),消息代理会将该消息放回队列中,另一位消费者会将其选中。 – 2012-07-16 18:28:06

2

听起来像Hadoop的工作给我。

2

我会怀疑你主要是数据库IO绑定这个方案。如果您试图提高系统的性能,那么我建议您将数据分区到多个数据库服务器上(如果可以的话)。 MySQL has some partitioning modes,我没有经验。如果你自己进行分区,它会给数据库模式增加很多复杂性,你必须使用散列机制添加某种路由层,以某种方式在多个分区间划分你的记录。但我怀疑你会得到显着的速度提升,你的线程不会等待几乎。

如果你不能分区你的数据,那么移动你的数据库到SSD memory drive将是一个巨大的胜利,我怀疑 - 任何提高这些分区的IO率。由于固有的性能问题,请远离RAID5。如果你需要一个可靠的文件系统,那么镜像或RAID10会有更好的性能,RAID50也是一个大分区的选项。

最后,您可能会发现如果您的数据库IO总线发生颠簸,那么您的应用程序执行效果会更好。这取决于很多因素,包括并发查询,数据库布局等。您可以尝试拨出每客户端线程数来查看是否会产生不同。但效果可能很小。

+1

是的 - 如果没有SSD,现在就得到一个。仅对大文件数据库性能产生巨大影响。对于那些生成大量小文件的应用程序(如编译器/链接器),差异是巨大的。 – 2012-07-16 18:26:10

+0

我会先去SSD。但是在大型企业中,很难说服基础架构和DBA团队改变存储技术。 – prashant 2012-07-16 18:26:33