1

我有一個應用程序在UDP端口上監聽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條消息並將其存儲在列表中

堆大小不斷增大,並在一段時間後導致內存執行。

我試圖找到解決方案來改善我的應用程序的性能。

感謝

回答

3

對於任何數據庫來說,每隔5秒存儲10,000條記錄相當多。

你需要考慮其他的選擇

  • 使用不同的數據存儲e.g NoSQL數據存儲庫,或平面文件。
  • 確保您的磁盤具有良好的寫入性能,例如使用寫入緩存。
  • 使用具有多個磁盤或SSD驅動器的磁盤子系統。
+0

問一個數據庫管理員調整/重新配置數據庫,或在SAN上(或在多個節點上)使用散列隨機文件(最終使用雙路徑) sks配置) –

2

建議

一個。你真的需要一個同步列表嗎?難道你不能擁有一組列表嗎?讓我們假設在這些列表之間劃分工作,比方說通過在數據的關鍵字上運行hashCode?

b。你可以使用從列表中讀取信息的線程池(順便說一下,我會在這裏使用一個隊列),這樣,當一個線程由於大批量插入而「卡住」時,其他線程仍然可以讀取「作業「從隊列中執行它們?

c。您的數據庫是否與應用程序共同託管在同一臺機器上?這可以提高性能

d。你能發佈你的插入查詢嗎?也許有人可以爲您提供一種優化方法?

2

使用數據庫連接池,以便您不必等待任何一個線程上的提交。只需抓住下一個可用連接並進行平行插入。

+0

我理解你的解決方案,但恐怕數據庫的負載將會太高(正如Peter所說的那樣)。 –

+0

那麼這是一個架構問題。將數據庫分佈在更多磁盤上,以便通過更多控制器通道進行更多的並行寫入磁盤。 - 對不起,彼得,沒有看到上面的答案,所有的好建議 – Mike

+0

最後一點建議,數據庫通常會讓你感到驚訝。雖然這是一個合理的假設,但直到嘗試之後纔會真正知道。性能是關於不斷解決下一個瓶頸。你的問題是如何避免提交的延遲,平行寫入就是答案。配置數據庫來處理它是一個不同的問題。 – Mike

1

我在SQLServer表上每秒獲得5.000次插入,但是這需要相當多的優化。沒有使用下面的所有提示,有些可能對您有用。

  • 檢查是否有可能在 http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html
  • MySQL的插入速度文件的提示進行並行插入過程
  • 總消息。而不是存儲所有消息在某個時間範圍內插入一行,包含特定類型的時間範圍內收到的消息的信息。
  • 將表更改爲除主鍵外沒有索引或外鍵
  • 切換到寫入文本文件(和導入過程中一個loaddata批量文件的夜晚插入,如果你真的想在數據庫中)
  • 使用一個單獨的數據庫實例只服務於你的表
  • ...