2013-07-23 66 views
3

Heyho,番石榴緩存:取消驅逐特定的緩存值

當前使用番石榴來緩存用戶。所以我的問題是,如果緩存對象具有特定的屬性值,是否可以用番石榴來重新排除條目的驅逐。例如,如果user.isOnline()返回true,即使用戶沒有被訪問特定時間(.expireAfterAccess(KEEP_LOADED,TimeUnit.SECONDS)),用戶也不會被驅逐。

編輯:

我發現這個在CacheBuilder.weighter的javadoc的(...):

當條目的權重爲零,它不會被認爲對於尺寸(儘管它仍然可能被其他方式驅逐)。

但我不想以任何方式驅逐我的用戶,如果他在線。

基本上我緩存我的用戶是這樣的:

 this.cache = CacheBuilder.newBuilder() 
      .maximumSize(MAX_CACHED_USERS) 
      .expireAfterAccess(KEEP_LOADED, TimeUnit.SECONDS) 
      .build(new UserLoader(core)); 

編輯:

好吧,我可以用加權器來限制我的緩存的大小。對於每個在線的用戶,我都可以返回0,對於其他任何用戶1.這會導致緩存保持在線用戶。但如果使用maximumSize和expireAfterAccess會很好。但是,CacheBuilder.weighter(...)不會阻止expireAfterAccess(...)設置以驅逐舊用戶。

編輯:

也許有可能取消驅逐以某種方式,但我不知道如何:/

相關:Is it safe to reinsert the entry from Guava RemovalListener?

最大

+0

你能展示你如何使用番石榴來緩存用戶,所以我們有更多的上下文? – tuckermi

+0

在您的CacheLoader實現上編寫一個重載方法,該實現返回user.isOnline()的給定「舊」實例爲true。 – Ray

+0

@Ray soo reload()在高速緩存的對象被驅逐時調用? – maxammann

回答

0

您鏈接的問題直接描述如何處理此模式。

我會使用一個地圖和一個緩存。將地圖用於仍在進行中的作業,也許可以使用緩存的RemovalListener從地圖中刪除條目?

簡而言之,如果有數據您不想被驅逐,它不屬於驅逐數據結構。

對於您的用例,您需要維護已登錄用戶的地圖和最近登錄的用戶的緩存。在用戶登錄時,它們存儲在標準地圖中。當他們註銷時,他們的對象被移動到緩存中,最終將驅逐它們。

您可以(也應該)在包含地圖和緩存的對象中隱藏此行爲。這可能看起來像這樣:

public class UserStore { 
    private final ConcurrentHashMap<Key, User> loggedIn; 
    private final LoadingCache<Key, User> recentlyAccessed; 

    ... 

    public User getUser(Key userKey) { 
    User user = loggedIn.get(userKey); 
    if (user != null) { 
     return user; 
    } 
    return recentlyAccessed.getUnchecked(userKey); // or .get() if necessary 
    } 
}