Kiedy i jak używać hibernacji pamięci podręcznej drugiego poziomu?

90

Mam problem ze zrozumieniem, kiedy hibernacja osiąga pamięć podręczną drugiego poziomu, a kiedy unieważnia pamięć podręczną.

Oto, co obecnie rozumiem:

  • Pamięć podręczna drugiego poziomu przechowuje jednostki między sesjami, zakres to SessionFactory
  • Musisz powiedzieć, które jednostki mają być buforowane, żadna jednostka nie zostanie domyślnie zapisana w pamięci podręcznej
  • Pamięć podręczna zapytań przechowuje wyniki zapytań w pamięci podręcznej.

To, czego nie rozumiem, to

  • Kiedy hibernacja uderza w tę pamięć podręczną?
  • Powiedzmy, że skonfigurowałem pamięć podręczną drugiego poziomu, ale nie buforowanie zapytań. Chcę buforować moich klientów, jest ich 50000. W jaki sposób mogę odzyskać klientów z pamięci podręcznej?
  • Zakładam, że mogę je uzyskać przez identyfikator z pamięci podręcznej. Byłoby to łatwe, ale nie warte buforowania. Ale co, jeśli chcę przeprowadzić obliczenia dla wszystkich moich klientów. Powiedzmy, że chcę wyświetlić listę klientów, w jaki sposób mogę uzyskać do nich dostęp?
  • Jak mogę zdobyć wszystkich moich klientów, jeśli buforowanie zapytań jest wyłączone?
  • Co by się stało, gdyby ktoś zaktualizował jednego z klientów?
    • Czy ten klient zostałby unieważniony w pamięci podręcznej, czy wszyscy klienci zostaliby unieważnieni?

A może myślę, że buforowanie jest całkowicie złe? Jakie byłyby bardziej odpowiednie zastosowania pamięci podręcznej drugiego poziomu w takim przypadku? Dokumentacja hibernacji nie jest wcale jasna, jak w rzeczywistości działa pamięć podręczna. Są tylko instrukcje, jak to skonfigurować.

Aktualizacja: Więc zrozumiałem, że pamięć podręczna drugiego poziomu (bez pamięci podręcznej zapytań) byłaby dobra do ładowania danych według identyfikatorów. Na przykład mam obiekt użytkownika, dla którego chcę sprawdzić uprawnienia w każdym żądaniu w aplikacji internetowej. Czy byłby to dobry przypadek ograniczenia dostępu do bazy danych poprzez buforowanie użytkownika w pamięci podręcznej drugiego poziomu? Jakbym przechowywał identyfikator użytkownika w sesji lub gdziekolwiek, a kiedy muszę sprawdzić uprawnienia, załadowałbym użytkownika według jego identyfikatora i sprawdziłbym uprawnienia.

palto
źródło

Odpowiedzi:

101

Przede wszystkim porozmawiajmy o pamięci podręcznej na poziomie procesu (lub pamięci podręcznej drugiego poziomu, jak to nazywają w Hibernate). Aby to zadziałało, powinieneś

  1. skonfigurować dostawcę pamięci podręcznej
  2. powiedz hibernuj, które jednostki mają być buforowane (bezpośrednio w pliku hbm.xml, jeśli używasz tego rodzaju mapowania).

Informujesz dostawcę pamięci podręcznej, ile obiektów ma przechowywać i kiedy / dlaczego powinny zostać unieważnione. Powiedzmy, że masz encje Book i Author, za każdym razem, gdy otrzymujesz je z DB, tylko te, które nie są w pamięci podręcznej, zostaną wybrane z faktycznie DB. Zwiększa to znacznie wydajność. Przydaje się, gdy:

  • Piszesz do bazy danych tylko przez Hibernate (ponieważ potrzebuje sposobu, aby wiedzieć, kiedy zmienić lub unieważnić jednostki w pamięci podręcznej)
  • Często czytasz przedmioty
  • Masz pojedynczy węzeł i nie masz replikacji. W przeciwnym razie będziesz musiał zreplikować samą pamięć podręczną (użyj rozproszonych pamięci podręcznych, takich jak JGroups), co zwiększa złożoność i nie skaluje się tak dobrze, jak aplikacje typu share-none.

Kiedy więc działa pamięć podręczna?

  • Gdy Ty session.get()lub session.load()obiekt, który został wcześniej wybrany i znajduje się w pamięci podręcznej. Pamięć podręczna to magazyn, w którym ID jest kluczem, a właściwości są wartościami. Więc tylko wtedy, gdy istnieje możliwość wyszukiwania według identyfikatora, możesz wyeliminować uderzanie w DB.
  • Gdy twoje skojarzenia są leniwe (lub niecierpliwie ładowane za pomocą selekcji zamiast sprzężeń)

Ale to nie działa, gdy:

  • Jeśli nie wybierzesz według identyfikatora. Ponownie - pamięć podręczna drugiego poziomu przechowuje mapę identyfikatorów podmiotów do innych właściwości (w rzeczywistości nie przechowuje obiektów, ale same dane), więc jeśli twoje wyszukiwanie wygląda tak:, from Authors where name = :nameto nie trafisz do pamięci podręcznej.
  • Kiedy używasz HQL (nawet jeśli używasz where id = ?).
  • Jeśli w mapowaniu ustawisz fetch="join", oznacza to, że do załadowania asocjacji wszędzie będą używane sprzężenia zamiast oddzielnych instrukcji select. Pamięć podręczna na poziomie procesu działa na obiektach potomnych tylko wtedy, gdy fetch="select"jest używana.
  • Nawet jeśli masz, fetch="select"ale wtedy w HQL używasz łączenia do wybierania asocjacji - te sprzężenia zostaną wydane od razu i nadpiszą wszystko, co określono w hbm.xml lub adnotacjach.

Teraz o pamięci podręcznej zapytań. Należy zauważyć, że nie jest to oddzielna pamięć podręczna, jest to dodatek do pamięci podręcznej na poziomie procesu. Załóżmy, że masz jednostkę Country. Jest statyczny, więc wiesz, że za każdym razem, gdy powiesz, będzie ten sam zestaw wyników from Country. Jest to idealny kandydat do pamięci podręcznej zapytań, będzie przechowywać listę identyfikatorów w sobie, a gdy następnym razem wybierzesz wszystkie kraje, zwróci tę listę do pamięci podręcznej na poziomie procesu, a ta z kolei zwróci obiekty dla każdego identyfikatora ponieważ te obiekty są już przechowywane w pamięci podręcznej drugiego poziomu. Pamięć podręczna zapytań jest unieważniana za każdym razem, gdy zmienia się cokolwiek związanego z jednostką. Powiedzmy, że skonfigurowano Cię from Authorsdo umieszczenia w pamięci podręcznej zapytań. Nie będzie to skuteczne, ponieważ Autor często się zmienia

Stanislav Bashkyrtsev
źródło
Czy zapytanie „od autora a dołączenie do pobierania a.books” wymaga pamięci podręcznej zapytań, aby pobrać autorów z pamięci podręcznej?
palto
1
Nie, pamięć podręczna zapytań jest przeznaczona tylko dla danych statycznych i przechowuje tylko identyfikatory. Autorzy zostaną pobrani z pamięci podręcznej drugiego poziomu.
Stanislav Bashkyrtsev
@ctapobep: nieprawda, co mówisz! „Od autora a pobierz dołącz do a.books” działa dobrze, jeśli księgi terenowe podmiotu Autor są opatrzone adnotacją (pobierz EAGER)… myślę, że jest już za późno
Bilal BBB
Taka świetna odpowiedź! Będę to zawsze pamiętał! : d
Mohammadreza Khatami,
czy po włączeniu „pamięci podręcznej zapytań” pobiera dane z pamięci podręcznej, jeśli wybierzesz inną właściwość niż id?
Arun Raaj
42
  • pamięć podręczna drugiego poziomu to magazyn klucz-wartość. Działa tylko wtedy, gdy otrzymujesz swoje podmioty za pomocą identyfikatora
  • pamięć podręczna drugiego poziomu jest unieważniana / aktualizowana na jednostkę, gdy jednostka jest aktualizowana / usuwana przez hibernację. Nie traci ważności, jeśli baza danych jest aktualizowana w inny sposób.
  • do zapytań (np. lista klientów) użyj pamięci podręcznej zapytań.

W rzeczywistości przydatne jest posiadanie rozproszonej pamięci podręcznej klucza i wartości - to właśnie jest memcached i obsługuje Facebooka, Twittera i wiele innych. Ale jeśli nie masz wyszukiwań według identyfikatora, nie będzie to zbyt przydatne.

Bozho
źródło
12

Spóźniłem się na imprezę ale chciałem systematycznie odpowiadać na te pytania, które zadaje wielu programistów.

Odpowiadam na twoje pytanie jedno po drugim.

P: Kiedy hibernacja trafia do tej pamięci podręcznej?

A. Pamięć podręczna pierwszego poziomu jest powiązana z obiektem Session . Second Level Cache jest związany z obiektu Session Factory . Jeśli obiekt nie zostanie znaleziony na pierwszym, sprawdzany jest drugi poziom.

P. Powiedzmy, że skonfigurowałem buforowanie drugiego poziomu, ale nie buforowanie zapytań. Chcę buforować moich klientów, jest ich 50000. W jaki sposób mogę odzyskać klientów z pamięci podręcznej?

A. Otrzymałeś odpowiedź w swojej aktualizacji. Również pamięć podręczna zapytań przechowuje tylko listę identyfikatorów obiektu, a te obiekty, w których ich identyfikatory są przechowywane w tej samej pamięci podręcznej drugiego poziomu. Jeśli więc włączysz pamięć podręczną zapytań, użyjesz tego samego zasobu. Schludnie, prawda?

P: Zakładam, że mogę je uzyskać przez identyfikator z pamięci podręcznej. Byłoby to łatwe, ale nie warte buforowania. Ale co, jeśli chcę przeprowadzić obliczenia dla wszystkich moich klientów. Powiedzmy, że chcę wyświetlić listę klientów, w jaki sposób mogę uzyskać do nich dostęp?

A. Odpowiedział powyżej.

P. Jak mogę uzyskać wszystkich moich klientów, jeśli buforowanie zapytań jest wyłączone?

A. Odpowiedział powyżej.

P. Co by się stało, gdyby ktoś zaktualizował jednego z klientów? Czy ten klient zostałby unieważniony w pamięci podręcznej, czy wszyscy klienci zostaliby unieważnieni?

O. Hibernate nie ma pojęcia, ale możesz użyć innych IMDG / rozproszonych pamięci podręcznych innych firm do zaimplementowania jako hibernacji pamięci podręcznej drugiego poziomu i unieważnić je. np. TayzGrid jest jednym z takich produktów i myślę, że jest ich więcej.

Basit Anwer
źródło
0

Pamięć podręczna drugiego poziomu Hibernacji jest trochę trudna do zrozumienia i wdrożenia. Oto, co możemy powiedzieć na podstawie Twoich pytań:

Kiedy Hibernacja trafia do tej pamięci podręcznej?

Jak sugerujesz, zapytanie o pamięć podręczną Hibernate L2 (jeśli jest włączone; nie jest domyślnie włączone) jest sprawdzane tylko po pamięci podręcznej L1. Jest to pamięć podręczna klucz-wartość, której dane są przechowywane w wielu sesjach.

Powiedzmy, że skonfigurowałem pamięć podręczną drugiego poziomu, ale nie buforowanie zapytań. Chcę buforować moich klientów, jest ich 50000. W jaki sposób mogę odzyskać klientów z pamięci podręcznej?

Buforowanie zapytań byłoby najlepsze w tym przypadku użycia, ponieważ dane klienta są statyczne i pobierane z relacyjnej bazy danych.

Co by się stało, gdyby ktoś zaktualizował jednego z klientów? Czy ten klient zostałby unieważniony w pamięci podręcznej, czy wszyscy klienci zostaliby unieważnieni?

To zależy od konkretnej strategii pamięci podręcznej Hibernacji, której używasz. Hibernate faktycznie ma cztery różne strategie pamięci podręcznej:

TYLKO ODCZYT : Obiekty nie zmieniają się raz w pamięci podręcznej.

NONSTRICT_READ_WRITE : Obiekty zmieniają się (ostatecznie) po zaktualizowaniu odpowiedniego wpisu w bazie danych; gwarantuje to ostateczną spójność.

READ_WRITE : Obiekty zmieniają się (natychmiast) po zaktualizowaniu odpowiedniego wpisu w bazie danych; gwarantuje to mocną spójność dzięki zastosowaniu „miękkich” zamków.

TRANSAKCYJNE : obiekty zmieniają się za pomocą rozproszonych transakcji XA, zapewniając integralność danych; gwarantuje to całkowity sukces lub cofnięcie wszystkich zmian. Jednak we wszystkich czterech przypadkach zaktualizowanie pojedynczego wpisu bazy danych nie unieważniłoby całej listy klientów w pamięci podręcznej. Hibernate jest trochę mądrzejszy :)

Aby dowiedzieć się więcej o tym, jak działa buforowanie L2 w Hibernate, możesz zapoznać się z artykułem „Co to jest pamięć podręczna Hibernate L2” lub szczegółowym artykułem Buforowanie w Hibernate with Redis

Nikita Koksharov
źródło