2012-04-10 35 views
1

我想在我的應用程序中有幾個Cache對象,我希望他們分享最大的權重。因此,給定總重量X,我希望所有緩存中緩存項的權重總和不超過X.我不知道預先需要多少緩存,也不需要緩存'公平' - 如果一個人被大量使用而另一個人不是,那麼他應該能夠佔據全球最大份額的最大份額。我不想錯過緩存,因爲它被認爲是完整的,而其他緩存大部分是未使用的,並且該空間可以被高度使用的緩存分配。這些將使我無法回到磁盤獲取數據,所以低失誤率非常重要。創建全局(JVM)緩存最大權重的簡單方法?

我想過有一個使用靜態變量保持總緩存權重的Weigher實現。然後稱重器會返回物體的重量,如果重量小於總剩餘空間,我會按原樣返回重量。如果它超過了剩餘的總重量,我可以返回Long.MAX_VALUE,這樣該項目不會被緩存。每個緩存都有很高的最大權重,可能是Long.MAX_VALUE-1,所以只要我們可以計算/分配權重,就可以插入一個元素。

問題是,我沒有看到任何方式來知道緩存對象的總重量。我可以減少驅逐偵聽器的總重量,但是當有東西插入到緩存中時,我看不到要通知的方式,緩存統計數據也不會在其數據中反映這一點。

是否有任何解決方法可以實現此功能?我有一個處理全局權重的自定義緩存實現,但缺少Guava緩存提供的許多功能,所以我想盡可能避免重新實現。雖然我不介意嘗試將它連接到番石榴高速緩存,如果你能指出我的大方向。

+0

您建議的Weigher不起作用,因爲具有MAX_VALUE權重的項目會刷新整個緩存。 (是的,我們可以優化它,但這並不簡單,並不清楚它是否值得。) – fry 2012-04-11 12:10:20

+0

最接近的是Jive的[heap-bounded cache](https://github.com/Omega1/voldemort/blob/master /src/java/voldemort/store/memory/ConcurrentLinkedHashMap.java)。這是ConcurrentLinkedHashMap早期版本的一個分支,但是在它的官方版本(現在在Guava中)實現算法之前。它爲他們工作,作爲soft-ref(高GC懲罰)的替代方案,但通常不足以成爲Guava緩存庫的一部分。 – 2012-04-12 05:39:44

+0

本,謝謝你的指針,我會檢查一下。 @fry,一旦我深入瞭解代碼,我就會意識到MAX_VALUE。對ConstrainedCache有沒有任何想法 - 將它與約束已有的約束結合起來。這可以讓我在約束中定義全局權重,並且可能對我來說至少是一個好的解決方案。 – Michael 2012-04-12 12:10:12

回答

2

番石榴緩存根本沒有相互作用 - 沒有「全局」交互 - 但softValues()是製作「內存敏感」緩存的傳統方式,因爲軟引用由GC收集(通常在全球最近最少使用的訂單),但只有當內存緊張時。

我甚至不相信番石榴在內部高速緩存跟蹤他們的總重量 - 他們跟蹤每個部分的總重量,我相信,但跟蹤總重量需要太多的鎖定。

+0

我知道他們並不全球互動,但我希望他們=) softValues感覺不合適,因爲我希望能夠從GC緩存中刪除項目,而GC不必處理它, d希望儘可能降低GC壓力。 我在代碼中注意到這些細分市場保留了它們的總重量,我會採用一個近似的而不是線程安全的總重量視圖。我最終在這裏和那裏會有一些額外的負載,但是我想這些將會被我所有時間節省下來的時間彌補,並避免再次進入磁盤。 – Michael 2012-04-10 16:03:17

+0

我不認爲你將能夠用Guava緩存來做到這一點,但如果我是你,我會首先嚐試softValues實現,做一些基準測試,然後才能看到是否需要移動到另一個緩存實現。 – 2012-04-10 16:08:18

+1

我正在看LocalCache代碼,看起來Weigher.weight被調用來獲取該條目的權重,然後插入到recordWrite中。它看起來不像插入被拒絕,如果權重會超過緩存的限制,而是插入,然後最舊的條目將被刪除,直到權重低於最大值,所以是的,使用Long.MAX_VALUE作爲信號沒有插入不起作用 – Michael 2012-04-10 16:10:45

2

我看到只有一個解決方案:你可以將這些組合到一個緩存中,並使用某種組合鍵嗎?

+0

我的想法確切。 – fry 2012-04-11 12:11:58

+0

這是一個有趣的建議。鍵總是長整型,並且這些值是相同的包裝對象,只是根據其中包含的東西進行參數化。這會使Weigher實現有點棘手,instanceof不會直接工作,因爲每個值都是同一類型的實例,所以我必須檢查泛型參數;儘管我可以看到將一個getType()方法添加到包裝器中,該方法將返回它參數化的類。我想我會花一些時間來看看這個。感謝您的建議。 – Michael 2012-04-11 13:07:37