Quando e come utilizzare l'ibernazione della cache di secondo livello?


90

Ho problemi a capire quando l'ibernazione colpisce la cache di secondo livello e quando invalida la cache.

Questo è ciò che attualmente capisco:

  • La cache di secondo livello memorizza le entità tra le sessioni, l'ambito è SessionFactory
  • Devi dire quali entità memorizzare nella cache, nessuna entità verrà memorizzata nella cache per impostazione predefinita
  • La cache delle query memorizza i risultati delle query nella cache.

Quello che non capisco è

  • Quando l'ibernazione raggiunge questa cache?
  • Diciamo che ho impostato la cache di secondo livello ma non la cache delle query. Voglio memorizzare nella cache i miei clienti, ce ne sono 50000. In che modo posso recuperare i clienti dalla cache?
  • Presumo di poterli ottenere tramite ID dalla cache. Sarebbe facile ma anche non degno di essere memorizzato nella cache. Ma cosa succede se voglio fare qualche calcolo con tutti i miei clienti. Diciamo che voglio mostrare un elenco dei clienti, quindi come potrei accedervi?
  • Come potrei ottenere tutti i miei clienti se la cache delle query è disabilitata?
  • Cosa succederebbe se qualcuno aggiornasse uno dei clienti?
    • Quel cliente verrebbe invalidato nella cache o tutti i clienti verrebbero invalidati?

O sto pensando che il caching sia totalmente sbagliato? Quali sarebbero gli usi più appropriati della cache di secondo livello in quel caso? La documentazione di ibernazione non è affatto chiara come funziona la cache nella realtà. Ci sono solo le istruzioni su come configurarlo.

Aggiornamento: quindi sono arrivato a capire che la cache di secondo livello (senza cache di query) sarebbe utile per caricare i dati dagli ID. Ad esempio, ho un oggetto utente di cui desidero verificare le autorizzazioni in ogni richiesta in un'applicazione web. Sarebbe un buon caso per ridurre l'accesso al database memorizzando nella cache l'utente nella cache di secondo livello? Come se memorizzassi l'ID utente nella sessione o ovunque e quando ho bisogno di controllare i permessi, caricherò l'utente dal suo ID e controllerei i permessi.


Risposte:


100

Prima di tutto, parliamo della cache a livello di processo (o cache di 2 ° livello come la chiamano in Hibernate). Per farlo funzionare, dovresti

  1. configurare il provider della cache
  2. dì a hibernate quali entità memorizzare nella cache (direttamente nel file hbm.xml se usi questo tipo di mappatura).

Dite al provider della cache quanti oggetti deve memorizzare e quando / perché dovrebbero essere invalidati. Quindi supponiamo che tu abbia un libro e un'entità autore, ogni volta che le ottieni dal DB, solo quelle che non sono nella cache verranno selezionate dal DB effettivo. Ciò aumenta notevolmente le prestazioni. È utile quando:

  • Scrivi nel database solo tramite Hibernate (perché ha bisogno di un modo per sapere quando modificare o invalidare le entità nella cache)
  • Leggi spesso gli oggetti
  • Hai un singolo nodo e non hai la replica. Altrimenti dovrai replicare la cache stessa (usa cache distribuite come JGroups) che aggiunge più complessità e non scala bene come le app senza condivisione.

Quindi quando funziona la cache?

  • Quando tu session.get()o session.load()l'oggetto che è stato precedentemente selezionato e risiede nella cache. La cache è un archivio in cui l'ID è la chiave e le proprietà sono i valori. Quindi solo quando c'è la possibilità di cercare per ID si potrebbe eliminare di colpire il DB.
  • Quando le tue associazioni sono caricate in modo pigro (o caricate con entusiasmo con selezioni invece di join)

Ma non funziona quando:

  • Se non selezioni per ID. Ancora una volta: la cache di 2 ° livello memorizza una mappa degli ID delle entità su altre proprietà (in realtà non memorizza gli oggetti, ma i dati stessi), quindi se la tua ricerca è simile a questa:from Authors where name = :name :, non premi la cache.
  • Quando usi HQL (anche se usi where id = ? ).
  • Se nella mappatura si imposta fetch="join", ciò significa che per caricare le associazioni verranno utilizzati i join ovunque invece di istruzioni select separate. La cache a livello di processo funziona sugli oggetti figli solo sefetch="select" viene utilizzata.
  • Anche se hai fetch="select"ma poi in HQL usi i join per selezionare le associazioni: quei join verranno emessi immediatamente e sovrascriveranno ciò che hai specificato in hbm.xml o annotazioni.

Ora, a proposito di Query Cache. Si noti che non è una cache separata, è un'aggiunta alla cache a livello di processo. Supponiamo che tu abbia un'entità Paese. È statico, quindi sai che ogni volta ci sarà lo stesso set di risultati quando dici from Country. Questo è un candidato perfetto per la cache delle query, memorizzerà un elenco di ID in sé e quando selezioni tutti i paesi la prossima volta, restituirà questo elenco alla cache a livello di processo e quest'ultima, a sua volta, restituirà oggetti per ogni ID poiché questi oggetti sono già memorizzati nella cache di 2 ° livello. La cache delle query viene invalidata ogni volta che viene modificato qualcosa relativo all'entità. Supponiamo quindi che tu sia configurato from Authorsper essere inserito in una cache delle query. Non sarà efficace poiché l'autore cambia spesso.


La query "da Author a fetch join a.books" richiede che la Query cache recuperi gli autori dalla cache?
palto

1
No, la cache delle query è solo per i dati statici e memorizza solo gli ID. Gli autori verranno presi dalla cache di 2 ° livello.
Stanislav Bashkyrtsev

@ctapobep: non è vero quello che dici! "from Author a fetch join a.books" funziona bene se i libri di campo dell'entità Author sono annotati (fetch EAGER) ... è troppo tardi penso
Bilal BBB

Un'ottima risposta! Lo ricorderò tutto il tempo! : d
Mohammadreza Khatami

dopo aver abilitato la "cache delle query", recupera i dati dalla cache se si seleziona una proprietà diversa da id?
Arun Raaj

41
  • la cache di 2 ° livello è un archivio di valori-chiave. Funziona solo se ottieni le tue entità tramite ID
  • la cache di 2 ° livello viene invalidata / aggiornata per entità quando un'entità viene aggiornata / eliminata tramite ibernazione. Non viene invalidato se il database viene aggiornato in modo diverso.
  • per le query (ad es. elenco di clienti) utilizzare la cache delle query.

In realtà è utile avere una cache distribuita di valori-chiave - questo è ciò che è memcached, e alimenta Facebook, Twitter e molti altri. Ma se non hai ricerche per ID, non sarà molto utile.


12

In ritardo alla festa, ma volevo rispondere sistematicamente a queste domande che molti sviluppatori chiedono.

Prendendo la tua domanda una per una, ecco la mia risposta.

D. Quando l'ibernazione raggiunge questa cache?

R. La cache di primo livello è associata all'oggetto Session . La cache di secondo livello è associata all'oggetto Session Factory . Se l'oggetto non viene trovato nel primo, viene controllato il secondo livello.

D. Diciamo che ho impostato la cache di secondo livello ma non la cache delle query. Voglio memorizzare nella cache i miei clienti, ce ne sono 50000. In che modo posso recuperare i clienti dalla cache?

A. Hai ricevuto una risposta nel tuo aggiornamento. Inoltre, la cache delle query memorizza solo l'elenco degli ID dell'oggetto e quegli Oggetti rispetto ai loro ID sono memorizzati nella stessa cache di secondo livello. Quindi, se abiliti la cache delle query, utilizzerai la stessa risorsa. Perfetto, vero?

D. Presumo di poterli ottenere tramite ID dalla cache. Sarebbe facile ma anche non degno di essere memorizzato nella cache. Ma cosa succede se voglio fare qualche calcolo con tutti i miei clienti. Diciamo che voglio mostrare un elenco dei clienti, quindi come potrei accedervi?

A. Risposte sopra.

D. Come potrei ottenere tutti i miei clienti se la cache delle query è disabilitata?

A. Risposte sopra.

D. Cosa succederebbe se qualcuno aggiornasse uno dei clienti? Quel cliente verrebbe invalidato nella cache o tutti i clienti verrebbero invalidati?

R. Hibernate non ne ha idea, ma potresti usare altri IMDG / cache distribuite di terze parti da implementare come cache di secondo livello ibernata e farle invalidare. ad esempio TayzGrid è uno di questi prodotti e credo ce ne siano altri.


0

La cache di secondo livello di Hibernate è un po 'complicata da capire e implementare. Ecco cosa possiamo dire in base alle tue domande:

Quando Hibernate raggiunge questa cache?

Come suggerisci, la cache L2 di Hibernate (se abilitata; non è attivata di default) viene interrogata solo dopo la cache L1. Si tratta di una cache valore-chiave i cui dati vengono conservati in più sessioni.

Diciamo che ho impostato la cache di secondo livello ma non la cache delle query. Voglio memorizzare nella cache i miei clienti, ce ne sono 50000. In che modo posso recuperare i clienti dalla cache?

La memorizzazione nella cache delle query sarebbe la migliore per questo caso d'uso, poiché i dati del cliente sono statici e recuperati da un database relazionale.

Cosa succederebbe se qualcuno aggiornasse uno dei clienti? Quel cliente verrebbe invalidato nella cache o tutti i clienti verrebbero invalidati?

Dipende dalla specifica strategia di cache di Hibernate che stai utilizzando. Hibernate ha in realtà quattro diverse strategie di cache:

READ_ONLY : gli oggetti non cambiano una volta all'interno della cache.

NONSTRICT_READ_WRITE : gli oggetti cambiano (eventualmente) dopo che la voce del database corrispondente è stata aggiornata; questo garantisce un'eventuale coerenza.

READ_WRITE : gli oggetti cambiano (immediatamente) dopo l'aggiornamento della voce di database corrispondente; questo garantisce una forte consistenza utilizzando serrature "morbide".

TRANSACTIONAL : gli oggetti cambiano utilizzando transazioni XA distribuite, garantendo l'integrità dei dati; questo garantisce il successo totale o il rollback di tutte le modifiche. In tutti e quattro questi casi, tuttavia, l'aggiornamento di una singola voce del database non invaliderebbe l'intero elenco di clienti nella cache. Hibernate è un po 'più intelligente di così :)

Per saperne di più su come funziona la memorizzazione nella cache L2 in Hibernate, puoi consultare l'articolo "Che cos'è la cache L2 di Hibernate" o l'articolo approfondito Memorizzazione nella cache in Hibernate con Redis

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.