J'ai du mal à comprendre quand la mise en veille prolongée atteint le cache de deuxième niveau et quand cela invalide-t-il le cache.
Voici ce que je comprends actuellement:
- Le cache de deuxième niveau stocke les entités entre les sessions, la portée est la SessionFactory
- Vous devez dire quelles entités mettre en cache, aucune entité ne sera mise en cache par défaut
- Le cache des requêtes stocke les résultats des requêtes dans le cache.
Ce que je ne comprends pas, c'est
- Quand la mise en veille prolongée atteint-elle ce cache?
- Disons que j'ai configuré le cache de deuxième niveau mais pas la mise en cache des requêtes. Je veux mettre en cache mes clients, il y en a 50000. De quelles manières puis-je récupérer les clients du cache?
- Je suppose que je peux les obtenir par identifiant à partir du cache. Ce serait facile mais pas digne de la mise en cache. Mais que faire si je veux faire des calculs avec tous mes clients. Disons que je souhaite afficher une liste des clients, comment puis-je y accéder?
- Comment puis-je obtenir tous mes clients si la mise en cache des requêtes est désactivée?
- Que se passerait-il si quelqu'un mettait à jour l'un des clients?
- Ce client serait-il invalidé dans le cache ou tous les clients seraient-ils invalidés?
Ou est-ce que je pense que la mise en cache est totalement erronée? Quelles seraient les utilisations les plus appropriées du cache de deuxième niveau dans ce cas? La documentation de mise en veille prolongée n'est pas du tout claire sur le fonctionnement du cache dans la réalité. Il n'y a que des instructions sur la façon de le configurer.
Mise à jour: J'ai donc compris que le cache de deuxième niveau (sans cache de requête) serait bon pour charger des données par identifiant. Par exemple, j'ai un objet utilisateur pour lequel je souhaite vérifier les autorisations dans chaque demande d'une application Web. Serait-ce un bon cas pour réduire l'accès à la base de données en mettant l'utilisateur en cache dans le cache de deuxième niveau? Comme si je stockais l'identifiant de l'utilisateur dans la session ou n'importe où et quand je devais vérifier les autorisations, je chargerais l'utilisateur par son identifiant et vérifierais les autorisations.
Réponses:
Tout d'abord, parlons du cache de niveau processus (ou cache de 2e niveau comme ils l'appellent dans Hibernate). Pour que cela fonctionne, vous devez
Vous indiquez au fournisseur de cache le nombre d'objets qu'il doit stocker et quand / pourquoi ils doivent être invalidés. Supposons donc que vous ayez un livre et une entité auteur, chaque fois que vous les récupérez de la base de données, seuls ceux qui ne sont pas dans le cache seront sélectionnés à partir de la base de données. Cela augmente considérablement les performances. C'est utile quand:
Alors, quand le cache fonctionne-t-il?
session.get()
ousession.load()
l'objet qui a été précédemment sélectionné et réside dans le cache. Le cache est un stockage où ID est la clé et les propriétés sont les valeurs. Donc, ce n'est que lorsqu'il y a une possibilité de recherche par ID que vous pouvez éviter de toucher la base de données.Mais cela ne fonctionne pas quand:
from Authors where name = :name
alors vous n'atteignez pas le cache.where id = ?
).fetch="join"
, cela signifie que pour charger des associations, les jointures seront utilisées partout au lieu d'instructions de sélection séparées. Le cache de niveau de processus ne fonctionne sur les objets enfants que s'ilfetch="select"
est utilisé.fetch="select"
mais dans HQL, vous utilisez des jointures pour sélectionner des associations - ces jointures seront émises immédiatement et elles remplaceront tout ce que vous avez spécifié dans hbm.xml ou les annotations.Maintenant, à propos du cache de requêtes. Vous devez noter qu'il ne s'agit pas d'un cache séparé, mais d'un ajout au cache de niveau processus. Disons que vous avez une entité Pays. C'est statique, vous savez donc qu'à chaque fois, il y aura le même jeu de résultats lorsque vous dites
from Country
. C'est un candidat parfait pour le cache de requêtes, il stockera une liste d' identifiants en lui-même et la prochaine fois que vous sélectionnerez tous les pays, il renverra cette liste dans le cache de niveau processus et ce dernier, à son tour, renverra des objets pour chaque identifiant car ces objets sont déjà stockés dans le cache de 2e niveau. Le cache des requêtes est invalidé chaque fois que tout élément lié à l'entité change. Supposons que vous soyez configuréfrom Authors
pour être placé dans un cache de requêtes. Cela ne sera pas efficace car l'auteur change souvent.la source
En réalité, il est utile d'avoir un cache distribué clé-valeur - c'est ce qu'est Memcached, et il alimente Facebook, Twitter et bien d'autres. Mais si vous n'avez pas de recherche par identifiant, cela ne sera pas très utile.
la source
En retard à la fête mais a voulu systématiquement répondre à ces questions que se posent de nombreux développeurs.
Voici ma réponse en prenant votre question une par une.
A. Le cache de premier niveau est associé à l' objet Session . Le cache de deuxième niveau est associé à l' objet Session Factory . Si l'objet n'est pas trouvé dans le premier, le deuxième niveau est vérifié.
R. Vous avez obtenu cette réponse dans votre mise à jour. De plus, le cache de requêtes stocke uniquement la liste des ID de l'objet et ces objets avec leurs ID sont stockés dans le même cache de deuxième niveau. Donc, si vous activez le cache de requêtes, vous utiliserez la même ressource. Neat non?
A. Répondu ci-dessus.
A. Répondu ci-dessus.
R. Hibernate n'a aucune idée, mais vous pouvez utiliser d'autres caches IMDG / distribués tiers pour être implémentés en tant que cache de deuxième niveau d'hibernation et les invalider. par exemple, TayzGrid est l'un de ces produits et il y en a plus, je suppose.
la source
Le cache de deuxième niveau Hibernate est un peu difficile à comprendre et à implémenter. Voici ce que nous pouvons dire en fonction de vos questions:
Comme vous le suggérez, le cache Hibernate L2 (s'il est activé; il n'est pas activé par défaut) est interrogé uniquement après le cache L1. Il s'agit d'un cache clé-valeur dont les données sont conservées sur plusieurs sessions.
La mise en cache des requêtes serait la meilleure pour ce cas d'utilisation, car les données client sont statiques et extraites d'une base de données relationnelle.
Cela dépend de la stratégie de cache Hibernate spécifique que vous utilisez. Hibernate a en fait quatre stratégies de cache différentes:
READ_ONLY : les objets ne changent pas une fois dans le cache.
NONSTRICT_READ_WRITE : les objets changent (éventuellement) après la mise à jour de l'entrée de base de données correspondante; cela garantit une cohérence éventuelle.
READ_WRITE : les objets changent (immédiatement) après la mise à jour de l'entrée de base de données correspondante; cela garantit une forte cohérence grâce à l'utilisation de verrous «souples».
TRANSACTIONNEL : les objets changent à l'aide de transactions XA distribuées, garantissant l'intégrité des données; cela garantit un succès total ou l'annulation de tous les changements. Dans ces quatre cas, cependant, la mise à jour d'une seule entrée de base de données n'invaliderait pas la liste complète des clients dans le cache. Hibernate est un peu plus intelligent que ça :)
Pour en savoir plus sur le fonctionnement de la mise en cache L2 dans Hibernate, vous pouvez consulter l'article «Qu'est-ce que le cache Hibernate L2» ou l'article détaillé Caching in Hibernate with Redis
la source