Quando e como usar o cache de segundo nível de hibernação?


90

Tenho dificuldade em entender quando o Hibernate atinge o cache de segundo nível e quando invalida o cache.

Isso é o que eu entendo atualmente:

  • O cache de segundo nível armazena entidades entre sessões, o escopo é a SessionFactory
  • Você tem que dizer quais entidades armazenar em cache, nenhuma entidade será armazenada em cache por padrão
  • O cache de consulta armazena resultados de consultas no cache.

O que não entendo é

  • Quando a hibernação atinge esse cache?
  • Digamos que eu configurei o cache de segundo nível, mas não o cache de consulta. Eu quero armazenar meus clientes em cache, há 50000 deles. De que forma posso recuperar os clientes do cache?
  • Presumo que posso obtê-los por id no cache. Isso seria fácil, mas também não vale a pena armazenar em cache. Mas e se eu quiser fazer alguns cálculos com todos os meus clientes. Digamos que eu queira mostrar uma lista dos clientes, então como posso acessá-los?
  • Como obteria todos os meus clientes se o cache de consultas estivesse desabilitado?
  • O que aconteceria se alguém atualizasse um dos clientes?
    • Esse cliente seria invalidado no cache ou todos os clientes seriam invalidados?

Ou estou pensando que o cache é totalmente errado? Quais seriam os usos mais apropriados do cache de segundo nível nesse caso? A documentação do hibernate não deixa claro como o cache funciona na realidade. Existem apenas instruções sobre como configurá-lo.

Update: Então, eu entendi que o cache de segundo nível (sem cache de consulta) seria bom para carregar dados por id's. Por exemplo, tenho um objeto de usuário que desejo verificar se há permissões em cada solicitação em um aplicativo da web. Seria um bom caso para reduzir o acesso ao banco de dados, armazenando o usuário no cache de segundo nível? Como se eu armazenasse a id do usuário na sessão ou onde quer que eu precisasse verificar as permissões, carregaria o usuário por sua id e verificaria as permissões.


Respostas:


100

Em primeiro lugar, vamos falar sobre cache de nível de processo (ou cache de segundo nível, como o chamam no Hibernate). Para fazer funcionar, você deve

  1. configurar provedor de cache
  2. diga ao hibernate quais entidades armazenar em cache (direito no arquivo hbm.xml se você usar esse tipo de mapeamento).

Você diz ao provedor de cache quantos objetos ele deve armazenar e quando / por que eles devem ser invalidados. Então, digamos que você tenha entidades Book e Author, cada vez que você as obtém do DB, apenas aquelas que não estão no cache serão selecionadas do DB. Isso aumenta o desempenho significativamente. É útil quando:

  • Você grava no banco de dados apenas via Hibernate (porque ele precisa de uma maneira de saber quando alterar ou invalidar entidades no cache)
  • Você lê objetos com frequência
  • Você tem um único nó e não tem replicação. Caso contrário, você precisará replicar o próprio cache (use caches distribuídos como JGroups), o que adiciona mais complexidade e não é tão bom quanto os aplicativos compartilham nada.

Então, quando o cache funciona?

  • Quando você session.get()ou session.load()o objeto que foi selecionado anteriormente e reside no cache. Cache é um armazenamento em que ID é a chave e as propriedades são os valores. Portanto, somente quando houver a possibilidade de pesquisar por ID você poderá eliminar o acerto no DB.
  • Quando suas associações são carregadas lentamente (ou carregadas rapidamente com seleções em vez de junções)

Mas não funciona quando:

  • Se você não selecionar por ID. Novamente - o cache de segundo nível armazena um mapa de IDs de entidades para outras propriedades (ele não armazena objetos, mas os próprios dados), então se sua pesquisa for assim:, from Authors where name = :nameentão você não acessa o cache.
  • Quando você usa HQL (mesmo se você usar where id = ?).
  • Se em seu mapeamento você definir fetch="join", isso significa que, para carregar associações, as junções serão usadas em todos os lugares em vez de instruções select separadas. O cache de nível de processo funciona em objetos filhos apenas se fetch="select"for usado.
  • Mesmo se você tiver, fetch="select"mas em HQL, você usa junções para selecionar associações - essas junções serão emitidas imediatamente e sobrescreverão tudo o que você especificou em hbm.xml ou anotações.

Agora, sobre Query Cache. Você deve notar que não é um cache separado, é uma adição ao cache de nível de processo. Digamos que você tenha uma entidade País. É estático, então você sabe que sempre haverá o mesmo conjunto de resultados quando você disser from Country. Este é um candidato perfeito para cache de consulta, ele armazenará uma lista de IDs em si mesmo e quando você selecionar todos os países da próxima vez, ele retornará essa lista para o cache de nível de processo e este, por sua vez, retornará objetos para cada ID pois esses objetos já estão armazenados no cache de segundo nível. O cache de consulta é invalidado cada vez que algo relacionado à entidade muda. Digamos que você tenha configurado from Authorspara ser colocado em um Cache de Consulta. Não será eficaz porque o autor muda frequentemente.


A consulta "do autor, um fetch join a.books" exige o cache de consulta para buscar autores do cache?
palto de

1
Não, o cache de consulta é apenas para dados estáticos e armazena apenas IDs. Os autores serão retirados do cache de segundo nível.
Stanislav Bashkyrtsev de

@ctapobep: não é verdade o que você diz! "from Author, a fetch join a.books" funciona bem se os livros de campo da entidade Author estiverem anotados (fetch EAGER) ... acho que é tarde demais
Bilal BBB

Que resposta ótima! Vou me lembrar disso o tempo todo! : d
Mohammadreza Khatami

após habilitar o 'cache de consulta', ele busca os dados do cache se você selecionar por outra propriedade que não seja id?
Arun Raaj

41
  • o cache de segundo nível é um armazenamento de valor-chave. Só funciona se você pegar suas entidades por id
  • o cache de segundo nível é invalidado / atualizado por entidade quando uma entidade é atualizada / excluída via hibernação. Não é invalidado se o banco de dados for atualizado de uma maneira diferente.
  • para consultas (por exemplo, lista de clientes), use o cache de consultas.

Na realidade, é útil ter um cache distribuído de valor-chave - isso é o memcached, e ele alimenta o Facebook, Twitter e muitos mais. Mas se você não tiver pesquisas por id, não será muito útil.


12

Atrasado para a festa, mas queria responder sistematicamente a essas perguntas que muitos desenvolvedores fazem.

Tomando sua pergunta uma por uma aqui está minha resposta.

Q. Quando a hibernação atinge este cache?

A. O cache de primeiro nível está associado ao objeto de sessão . O segundo nível de cache está associado ao objeto Session Factory . Se o objeto não for encontrado no primeiro, o segundo nível será verificado.

P. Digamos que eu configurei o cache de segundo nível, mas não o cache de consulta. Eu quero armazenar meus clientes em cache, há 50000 deles. De que forma posso recuperar os clientes do cache?

A. Você teve essa resposta em sua atualização. Além disso, o cache de consulta armazena apenas a lista de IDs do objeto e os objetos escritos em seus IDs são armazenados no mesmo cache de segundo nível. Portanto, se você habilitar o cache de consulta, utilizará o mesmo recurso. Legal, certo?

P. Presumo que posso obtê-los por id no cache. Isso seria fácil, mas também não vale a pena armazenar em cache. Mas e se eu quiser fazer alguns cálculos com todos os meus clientes. Digamos que eu queira mostrar uma lista dos clientes, então como posso acessá-los?

A. Respondido acima.

P. Como posso obter todos os meus clientes se o cache de consulta estiver desabilitado?

A. Respondido acima.

P. O que aconteceria se alguém atualizasse um dos clientes? Esse cliente seria invalidado no cache ou todos os clientes seriam invalidados?

R. O Hibernate não tem ideia, mas você pode usar outros caches de IMDG / distribuídos de terceiros para serem implementados como cache de segundo nível de hibernação e invalidá-los. por exemplo, TayzGrid é um desses produtos e acho que há mais.


0

O cache de segundo nível do Hibernate é um pouco complicado de entender e implementar. Aqui está o que podemos dizer com base em suas perguntas:

Quando o Hibernate atinge este cache?

Como você sugere, o cache L2 do Hibernate (se habilitado; não é ativado por padrão) é consultado somente após o cache L1. Este é um cache de valor-chave cujos dados são preservados em várias sessões.

Digamos que eu configurei o cache de segundo nível, mas não o cache de consulta. Eu quero armazenar meus clientes em cache, há 50000 deles. De que forma posso recuperar os clientes do cache?

O cache de consulta seria o melhor para este caso de uso, uma vez que os dados do cliente são estáticos e recuperados de um banco de dados relacional.

O que aconteceria se alguém atualizasse um dos clientes? Esse cliente seria invalidado no cache ou todos os clientes seriam invalidados?

Depende da estratégia específica de cache do Hibernate que você está usando. O Hibernate, na verdade, tem quatro estratégias de cache diferentes:

SOMENTE LEITURA : Objetos não mudam uma vez dentro do cache.

NONSTRICT_READ_WRITE : Objetos mudam (eventualmente) após a entrada do banco de dados correspondente ser atualizada; isso garante consistência eventual.

LER ESCREVER : Objetos mudam (imediatamente) após a entrada do banco de dados correspondente ser atualizada; isso garante consistência forte usando bloqueios "suaves".

TRANSACIONAL : Objetos mudam usando transações XA distribuídas, garantindo a integridade dos dados; isso garante sucesso total ou reversão de todas as alterações. Em todos esses quatro casos, no entanto, atualizar uma única entrada do banco de dados não invalidaria toda a lista de clientes no cache. O Hibernate é um pouco mais inteligente do que isso :)

Para aprender mais sobre como o cache L2 funciona no Hibernate, você pode verificar o artigo “O que é o cache L2 do Hibernate,” ou o artigo detalhado Cache no Hibernate com Redis

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.