2010-12-17 16 views
6

Używam dekoratora EhCache SelfPopulatingCache i mam problem, gdy pamięć podręczna próbuje załadować nowy wpis, ale nie istnieje (tzn. Nie istnieje w bazie danych). Tak więc pamięć podręczna wstawi do pamięci podręcznej wartość null, aby odblokować wszelkie inne pobrania klucza, ale wtedy następny wątek wykona to samo wywołanie bazy danych, ponieważ otrzyma wartość "null" z pamięci podręcznej. co oznacza, że ​​uważa, że ​​wpis musi zostać załadowany - nawet jeśli w rzeczywistości jest pusty, ponieważ dane nigdzie nie istnieją. Czuję, że robię coś nie tak.Ehcache - przy użyciu SelfPopulatingCache, gdy dane nie są obecne

(pseudo kod)

Value v = cache.get(key); // multiple threads will block here 
if (v == null) 
    cache.put(key, getValueFromDB()); // this might put a null value 

Moje obecne rozwiązanie jest nie stawiać null, ale umieścić zastępczy Object i sprawdzić to.

Value v = cache.get(key); 
if (v == null) 
    cache.put(key, getValueFromDB()); 
else if (v == NOENTRYOBJECT) 
    return null; 
else 
    return v; 

Myśli?

+0

Nie wiem, jak twój pseudo-kod odnosi się do 'SelfPopulatingCache'. Jak się używasz? – skaffman

+0

cache = SelfPopulatingCache (lub BlockingCache) ... myśl, że było całkiem jasne – Gandalf

Odpowiedz

3

Robimy coś podobnego. W naszym przypadku wpisujemy Boolean.FALSE do pamięci podręcznej, jeśli żądany klucz nie odpowiada poprawnemu elementowi. Zasadniczo informuje kod wywołujący, że klucz, o który prosił, nie pasuje do żadnych danych. Musisz wykonać jedno wywołanie do bazy danych przy pierwszym żądaniu dla tego klucza, aby odkryć, że nie odpowiada on poprawnym danym, ale kolejne wywołania są oszczędzane przez wyszukiwanie db. Oczywiście, jeśli dane są zawsze wprowadzane do bazy danych dla tego klucza, należy koniecznie unieważnić ten wpis pamięci podręcznej (w przeciwnym razie nastąpi zwrócenie wartości Boolean.FALSE, nawet jeśli dostępne są rzeczywiste dane).

Nie jestem pewien, czy moja odpowiedź bardzo pomaga (nie jest to podejście alternatywne), ale przynajmniej potwierdza, że ​​nie jesteś sam w swoim podejściu.

BTW, nie sądzę, że jest to unikalne dla SelfPopulatingCache EHCache.

1

Typowy wzór nie jest ponownie sprawdzić bazę danych, jeśli istnieje elementu KEY w pamięci podręcznej w ogóle, zamiast WARTOŚCI.

Wzór jest opisany w dokumentach ehcache tutaj: Caching Empty Values.

Zazwyczaj, ale nie zawsze, get zwraca Element, więc get(id) nie będzie null jeśli put(id, value) kiedykolwiek wcześniej nazywana, nawet jeśli wartość jest null.

Pamiętaj, że zależy to od implementacji pamięci podręcznej. Dokumentacja ehcache wydaje się sugerować, że powinna zawsze działać, ale BlockingCache (i jej potomkowie) does NOT allow putting null values into the cache. Podstawowy obiekt ehcache Cache pozwala na przechowywanie wartości pustych w pamięci podręcznej (podobnie jak wiele przykładów i niestandardowych implementacji).

W sumie myślę, że rozwiązanie, które już masz (obiekt wartości zastępczej), działa również i powinno osiągnąć ten sam wynik, co klasa i dokumentacja bazy ehcache Cache.

+0

Właściwie to nie jest prawda - jeśli spojrzysz na kod BlockingCache i metodę put (..) - jeśli wartość == null usuwa klucz z Pamięć podręczna. Tak więc put (id, null) skutecznie nie umieszcza niczego w pamięci podręcznej, następny id dla id zwróci wartość null - not a Element. – Gandalf

+0

Hmmm. Nie spojrzałem na kod, więc byłoby to ostateczne źródło. Ale wtedy wydawałoby się to całkowicie sprzeczne z dokumentacją Ehcache. Nie jestem pewien, jak inaczej, przykład "Caching Empty Values" działałby, gdyby nie można było buforować wartości pustej (wyraźnie mówi, aby to zrobić). Przyjrzę się bliżej kodowi, gdy dostanę szansę, ale myślę, że * pamiętam, że robiłem to w przeszłości i działało dobrze (nie jestem pewien, umysłu, niewyraźne wspomnienie, ja też napiszę prosty test, aby potwierdzić /zaprzeczać). –

+0

Widzę, co to jest. Moja implementacja pamięci podręcznej nie korzysta z żadnego wbudowanego impulsu Ehcache lub oczywiście SelfPopulatingCache. Moja metoda put używa wartości boolean ustawionej w implementacji pamięci podręcznej o nazwie: putNullInCache. Domyślnie jest to prawda, więc pozwala na zapisanie wartości NULL. Zależy więc od impedancji pamięci podręcznej i masz całkowitą rację co do SelfPopulatingCache. Zaktualizuję moją "odpowiedź" tylko na przyszłe odniesienia dla każdego, gdy dostanę szansę - ale tak naprawdę jest źle;). W sumie myślę, że to, co robisz, ma taki sam efekt netto. –

0

Myślę, że trzeba zajrzeć do CacheElementFactory. Zaimplementowałam to na wiosnę dla projektu, nad którym pracowałem, aby zażądać informacji o ładowaniu do pamięci podręcznej, jeśli brakowało pamięci podręcznej, podjęto próbę załadowania go z bazy danych. Nie pamiętam konkretnie, co zrobiłem w tej sprawie i myślę, że to niestety spowoduje, że do bazy danych zostanie wysłane zapytanie o każde podanie, które zażądało brakującego klucza.

Powiązane problemy