2011-05-25 43 views
1

這是情況。如何在有多個線程時減少文件寫入次數?

在我被分配到mantain的Java Web App中,我被要求改進QA期間壓力測試的一般響應時間。這個網絡應用程序不使用數據庫,因爲它應該是輕而易舉的。 (並且我不能改變這個決定)

要持久化配置,我發現每次你對它做出改變時,一個包含config對象列表的通用對象被序列化爲一個文件。

使用Jmeter我發現在給定的測試用例中,有2個請求佔用大部分時間。這兩個請求都添加或更改了一些配置對象。由於必須對文件進行訪問,因此許多用戶在更改配置時,文件必須在幾秒鐘內完成多次寫入,並且請求正在等待寫入文件的發生。

我認爲所有這些序列化根本就沒有必要,因爲我們一次又一次地重寫大部分對象,每個請求中的更改都是針對一個對象,但是整個文件都是作爲一個整體寫入的時間。

那麼,有沒有辦法減少真正的文件寫入的數量,但仍然保證所有的更改最終序列化?

任何建議表示讚賞

+0

爲什麼您將配置存儲爲序列化對象? – Kaj 2011-05-25 17:02:14

+0

這不是我的選擇,設計者認爲它會很好很簡單,不幸的是,他沒有看到結果,我負責「爲QA球員做足夠快」......任何方式我都可以'在不久的將來會改變這種情況,因爲設計已經被批准並且功能測試已經結束。改變其根源以使用[db4o](http://db4o.com/)或JavaDB將使我們回到根據政治的發展階段......並且至少延遲3周。我討厭現在爲這樣一個糟糕的設計負責。 – rsinuhe 2011-05-25 18:01:26

回答

2

一種選擇是做改變內存中,並保持在後臺一個線程,在給定的時間間隔運行,並刷新更改磁盤。請記住,在發生崩潰的情況下,您將丟失未刷新的數據。

可以使用ScheduledExecutorService來安排後臺線程。

IMO,最好使用DB。你不能使用像Java DBH2HSQLDB的嵌入式數據庫嗎?這些數據庫支持併發訪問,並且還可以保證數據在崩潰時的一致性。

+0

謝謝!如預期的那樣,將寫入更改爲每隔幾秒而不是多次寫入一秒鐘就已經對這些請求的響應時間產生了奇蹟,他們不再等待序列化完成。 – rsinuhe 2011-05-25 21:58:22

+0

很高興知道。我希望你能夠儘快地改變這種設計,這對於像這樣的系統來說是非常糟糕的。 – iruediger 2011-05-26 00:10:12

0

如果您絕對不能使用數據庫,顯而易見的解決方案是將您的單個文件分解爲多個文件,每個配置對象一個文件。它可以加速序列化和輸出過程,並減少鎖爭用(更改不同配置對象的請求可能會同時寫入其文件,儘管它可能會成爲IO限制)。

+0

我試圖在各種文件中分割寫入,並且它減少了響應時間,不幸的是,正如您指出的那樣,在峯值負載期間,它也變成了io綁定並且響應延遲很多。 (但不像它是單個文件那麼多)。 – rsinuhe 2011-05-25 21:57:48

0

一種方法是做Lucene所做的事情,根本不覆蓋舊文件,而是寫一個只包含「更新」的新文件。這依賴於你的更新是關聯的,但無論如何通常都是這樣。

這個想法是,如果你的舊文件包含「8」,並且你有3個更新,你爲新文件寫入「3」,新狀態爲「11」,接下來你寫下「-2」有「9」。您可以定期彙總舊版和更新。您所寫的任何物理文件都不會更新,但一旦不再使用,可能會被刪除。

爲了讓這個想法更具針對性,考慮一下上面的數字是否是某種記錄。 「3」可以翻譯爲「添加三條新記錄」和「-2」到「刪除這兩條記錄」。

Lucene是一個項目的例子,它非常成功地使用了這種添加劑更新策略。