1

我有一个在端口上侦听 UDP 数据报的应用程序。我使用 UDP 入站通道适配器侦听此端口。我的 UDP 通道适配器配置为使用 ThreadPoolTask​​Executor 来调度传入的 UDP 数据报。在 UDP 通道适配器之后,我使用直接通道。我的频道只有一个订阅者,即服务激活者。

该服务将传入消息添加到存储在内存中的同步列表中。然后,我有一个线程每 5 秒检索一次列表的内容,并对 MySQL 数据库进行批量更新。

我的问题:

  1. 第一批消息到达。我的 ThreadPoolExecutor 的线程从 UDP 通道适配器获取传入消息并将它们添加到同步列表中。假设已经收到并插入了 10000 条消息。
  2. 后台线程检索 10000 条消息并进行批量更新 (JdbcTemplate.update(String[])。
  3. 此时,后台线程等待来自数据库的响应。但是,现在,由于数据库执行 10000 INSERT 需要时间,因此已收到 20000 条消息并出现在列表中。
  4. 后台线程接收来自数据库的响应。然后,它检索 20000 条消息并进行批量更新 (JdbcTemplate.update(String[])。
  5. 数据库执行 INSERT 需要更多时间,在此期间,已收到 35000 条消息并将其存储在列表中。

堆大小不断增长,并在一定时间后导致内存执行。

我正在尝试寻找解决方案来提高我的应用程序的性能。

谢谢

4

4 回答 4

3

每 5 秒存储 10,000 条记录对于任何数据库来说都是相当多的。

您需要考虑其他选择

  • 使用不同的数据存储,例如 NoSQL 数据存储或平面文件。
  • 确保您的磁盘具有良好的写入性能,例如使用写入缓存。
  • 使用具有多个磁盘或 SSD 驱动器的磁盘子系统。
于 2012-06-19T13:32:49.537 回答
2

使用数据库连接池,这样您就不必等待任何一个线程上的提交。只需抓住下一个可用连接并进行并行插入。

于 2012-06-19T14:13:10.987 回答
2

建议

一个。你真的需要一个同步列表吗?你不能有一组列表,让我们说在这些列表之间划分工作,比如说通过在数据的键上运行 hashCode ?

湾。您可以使用从列表中读取信息的线程池(顺便说一下,我会在这里使用队列),这样,当一个线程由于大量的批量插入而“卡住”时,其他线程仍然可以读取“作业“从队列中执行?

C。您的数据库是否与应用程序共同托管在同一台机器上?这可以提高性能

d。你能发布你的插入查询吗?也许有人可以为您提供优化它的方法?

于 2012-06-19T13:18:31.773 回答
1

I get 5.000 inserts per second sustained on a SQLServer table, but that required quite a few optimizations. Did not use all of the tips below, some might be of use to you.

  • Check the MySQL Insert Speed documentation tips in http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html
  • Parallelize the insert process
  • Aggregate messages if possible. Instead of storing all messages insert a row with information about received messages in a timeframe, of a certain type etc.
  • Change the table to have no Indexes or Foreign keys except for the primary key
  • Switch to writing to a textfile (and import that during the night in a loaddata bulk file insert if you really want it in the database)
  • Use a seperate database instance to serve only your table
  • ...
于 2012-06-19T16:06:45.657 回答