2012-07-16 71 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