¿Cuándo y cómo usar la caché de segundo nivel de hibernación?

90

Tengo problemas para entender cuándo la hibernación llega al caché de segundo nivel y cuándo invalida el caché.

Esto es lo que entiendo actualmente:

  • El caché de segundo nivel almacena entidades entre sesiones, el alcance es SessionFactory
  • Tienes que decir qué entidades almacenar en caché, ninguna entidad se almacenará en caché de forma predeterminada
  • La caché de consultas almacena los resultados de las consultas en la caché.

Lo que no entiendo es

  • ¿Cuándo llega la hibernación a este caché?
  • Digamos que he configurado la caché de segundo nivel pero no la caché de consultas. Quiero almacenar en caché a mis clientes, hay 50000 de ellos. ¿De qué manera puedo recuperar los clientes del caché?
  • Supongo que puedo obtenerlos por identificación desde el caché. Eso sería fácil pero tampoco digno de almacenar en caché. Pero, ¿y si quiero hacer algún cálculo con todos mis clientes? Digamos que quiero mostrar una lista de los clientes, ¿cómo puedo acceder a ellos?
  • ¿Cómo obtendría todos mis clientes si el almacenamiento en caché de consultas está deshabilitado?
  • ¿Qué pasaría si alguien actualizara a uno de los clientes?
    • ¿Ese cliente quedaría invalidado en la caché o todos los clientes quedarían invalidados?

¿O estoy pensando que el almacenamiento en caché está totalmente mal? ¿Cuáles serían los usos más apropiados de la caché de segundo nivel en ese caso? La documentación de hibernación no es del todo claro cómo funciona el caché en realidad. Solo hay instrucciones sobre cómo configurarlo.

Actualización: he llegado a comprender que la caché de segundo nivel (sin la caché de consultas) sería buena para cargar datos por id. Por ejemplo, tengo un objeto de usuario que quiero verificar los permisos en cada solicitud en una aplicación web. ¿Sería este un buen caso para reducir el acceso a la base de datos almacenando en caché al usuario en el caché de segundo nivel? Al igual que almacenaría la identificación del usuario en la sesión o en cualquier lugar y cuando necesite verificar los permisos, cargaría el usuario por su identificación y verificaría los permisos.

palto
fuente

Respuestas:

100

En primer lugar, hablemos del caché de nivel de proceso (o caché de segundo nivel como lo llaman en Hibernate). Para que funcione, debes

  1. configurar proveedor de caché
  2. dígale a hibernate qué entidades almacenar en caché (directamente en el archivo hbm.xml si usa este tipo de mapeo).

Le indica al proveedor de caché cuántos objetos debe almacenar y cuándo / por qué deben invalidarse. Entonces, digamos que tiene una entidad de Libro y una de Autor, cada vez que las obtenga de la base de datos, solo las que no estén en la caché se seleccionarán de la base de datos. Esto aumenta el rendimiento de manera significativa. Es útil cuando:

  • Escribe en la base de datos solo a través de Hibernate (porque necesita una forma de saber cuándo cambiar o invalidar entidades en el caché)
  • Lees objetos a menudo
  • Tiene un solo nodo y no tiene replicación. De lo contrario, deberá replicar el caché en sí (use cachés distribuidos como JGroups), lo que agrega más complejidad y no escala tan bien como las aplicaciones que no comparten nada.

Entonces, ¿cuándo funciona el caché?

  • Cuando usted session.get()o session.load()el objeto que fue seleccionado previamente y reside en caché. La caché es un almacenamiento donde ID es la clave y las propiedades son los valores. Entonces, solo cuando existe la posibilidad de buscar por ID, puede eliminar el acceso a la base de datos.
  • Cuando sus asociaciones se cargan de forma diferida (o se cargan ansiosamente con selecciones en lugar de uniones)

Pero no funciona cuando:

  • Si no selecciona por ID. Nuevamente, la caché de segundo nivel almacena un mapa de los ID de las entidades a otras propiedades (en realidad no almacena objetos, sino los datos en sí), por lo que si su búsqueda se ve así:, from Authors where name = :nameentonces no ingresa a la caché.
  • Cuando usa HQL (incluso si lo usa where id = ?).
  • Si en su mapeo lo estableció fetch="join", esto significa que para cargar asociaciones, las uniones se usarán en todas partes en lugar de las declaraciones de selección separadas. La caché de nivel de proceso funciona en objetos secundarios solo si fetch="select"se usa.
  • Incluso si lo tiene, fetch="select"pero luego en HQL usa combinaciones para seleccionar asociaciones, esas combinaciones se emitirán de inmediato y sobrescribirán lo que haya especificado en hbm.xml o anotaciones.

Ahora, sobre la caché de consultas. Debe tener en cuenta que no es una caché separada, es una adición a la caché de nivel de proceso. Digamos que tiene una entidad País. Es estático, por lo que sabe que siempre habrá el mismo conjunto de resultados cuando diga from Country. Este es un candidato perfecto para el caché de consultas, almacenará una lista de ID en sí mismo y la próxima vez que seleccione todos los países, devolverá esta lista al caché de nivel de proceso y este último, a su vez, devolverá objetos para cada ID. ya que estos objetos ya están almacenados en la caché de segundo nivel. La caché de consultas se invalida cada vez que cambia algo relacionado con la entidad. Entonces, digamos que lo configuró from Authorspara ser colocado en un caché de consultas. No será efectivo ya que el autor cambia con frecuencia.

Stanislav Bashkyrtsev
fuente
¿La consulta "from Author a fetch join a.books" requiere Query cache para obtener autores de la cache?
palto
1
No, la caché de consultas es solo para datos estáticos y solo almacena ID. Los autores se tomarán de la caché de segundo nivel.
Stanislav Bashkyrtsev
@ctapobep: ¡no es cierto lo que dices! "from Author a fetch join a.books" funciona bien si los libros de campo de la entidad Author están anotados (buscar EAGER) ... creo que es demasiado tarde
Bilal BBB
¡Qué gran respuesta! ¡Lo recordaré todo el tiempo! : d
Mohammadreza Khatami
después de habilitar el 'caché de consultas', ¿obtiene los datos del caché si selecciona una propiedad diferente a la identificación?
Arun Raaj
41
  • la caché de segundo nivel es un almacén de valores clave. Solo funciona si obtiene sus entidades por id
  • la caché de segundo nivel se invalida / actualiza por entidad cuando una entidad se actualiza / elimina mediante hibernación. No se invalida si la base de datos se actualiza de otra manera.
  • para consultas (por ejemplo, lista de clientes) utilice la caché de consultas.

En realidad, es útil tener un caché distribuido de valor clave; eso es lo que es Memcached, y funciona con Facebook, Twitter y muchos más. Pero si no tiene búsquedas por id, entonces no será muy útil.

Bozho
fuente
12

Llegó tarde a la fiesta, pero quería responder sistemáticamente a estas preguntas que hacen muchos desarrolladores.

Tomando su pregunta una por una aquí está mi respuesta.

P. ¿Cuándo llega la hibernación a esta caché?

R. La caché de primer nivel está asociada con el objeto de sesión . La caché de segundo nivel está asociada con el objeto Session Factory . Si el objeto no se encuentra en el primero, se verifica el segundo nivel.

P. Digamos que he configurado la caché de segundo nivel pero no la caché de consultas. Quiero almacenar en caché a mis clientes, hay 50000 de ellos. ¿De qué manera puedo recuperar los clientes del caché?

R. Obtuviste esa respuesta en tu actualización. Además, el caché de consultas almacena solo la lista de ID del objeto y esos Objetos con sus ID se almacenan en el mismo caché de segundo nivel. Entonces, si habilita la caché de consultas, utilizará el mismo recurso. Genial, ¿verdad?

P. Supongo que puedo obtenerlos por id desde el caché. Eso sería fácil pero tampoco digno de almacenar en caché. Pero, ¿y si quiero hacer algún cálculo con todos mis clientes? Digamos que quiero mostrar una lista de los clientes, ¿cómo puedo acceder a ellos?

A. Respondido arriba.

P. ¿Cómo obtendría todos mis clientes si el almacenamiento en caché de consultas está deshabilitado?

A. Respondido arriba.

P. ¿Qué pasaría si alguien actualizara a uno de los clientes? ¿Ese cliente quedaría invalidado en la caché o todos los clientes quedarían invalidados?

R. Hibernate no tiene idea, pero podría usar otras memorias caché IMDG / distribuidas de terceros para implementarlas como caché de segundo nivel de hibernación y invalidarlas. Por ejemplo, TayzGrid es uno de esos productos y supongo que hay más.

Basit Anwer
fuente
0

El caché de segundo nivel de Hibernate es un poco complicado de entender e implementar. Esto es lo que podemos decir en función de sus preguntas:

¿Cuándo llega Hibernate a este caché?

Como sugiere, la caché Hibernate L2 (si está habilitada; no está activada de forma predeterminada) se consulta solo después de la caché L1. Se trata de una caché de clave-valor cuyos datos se conservan en varias sesiones.

Digamos que he configurado la caché de segundo nivel pero no la caché de consultas. Quiero almacenar en caché a mis clientes, hay 50000 de ellos. ¿De qué manera puedo recuperar los clientes del caché?

El almacenamiento en caché de consultas sería lo mejor para este caso de uso, ya que los datos del cliente son estáticos y se recuperan de una base de datos relacional.

¿Qué pasaría si alguien actualizara a uno de los clientes? ¿Ese cliente quedaría invalidado en la caché o todos los clientes quedarían invalidados?

Depende de la estrategia de caché de Hibernate específica que esté utilizando. Hibernate en realidad tiene cuatro estrategias de caché diferentes:

READ_ONLY : Los objetos no cambian una vez dentro del caché.

NONSTRICT_READ_WRITE : Los objetos cambian (eventualmente) después de que se actualiza la entrada correspondiente de la base de datos; esto garantiza una eventual consistencia.

READ_WRITE : Los objetos cambian (inmediatamente) después de que se actualice la entrada correspondiente de la base de datos; esto garantiza una fuerte consistencia mediante el uso de cerraduras "blandas".

TRANSACCIONAL : Los objetos cambian mediante transacciones XA distribuidas, lo que garantiza la integridad de los datos; esto garantiza el éxito total o revertir todos los cambios. Sin embargo, en los cuatro casos, la actualización de una sola entrada de la base de datos no invalidaría la lista completa de clientes en la caché. Hibernate es un poco más inteligente que eso :)

Para obtener más información sobre cómo funciona el almacenamiento en caché L2 en Hibernate, puede consultar el artículo “¿Qué es el caché L2 de Hibernate?” O el artículo detallado Almacenamiento en caché en Hibernate con Redis.

Nikita Koksharov
fuente