2010-08-18 34 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利用率,但會以輸出隊列的暫時增長爲代價。如果不是這樣,吞吐量將受限於寫入數據庫的速度,無論您擁有多少線程,然後只需一個讀取進程寫入線程即可脫身。