web-dev-qa-db-fra.com

Quand et comment utiliser le cache de deuxième niveau en veille prolongée?

J'ai du mal à comprendre quand l'hibernation atteint le cache de deuxième niveau et quand cela invalide 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 de requêtes stocke les résultats des requêtes dans le cache.

Ce que je ne comprends pas, c'est

  • Quand l'hibernation 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 mes clients en cache, 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 id du cache. Ce serait facile mais ne mériterait pas non plus d'être mis en cache. Mais que se passe-t-il si je veux faire un calcul avec tous mes clients. Supposons 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 fausse? Quelles seraient les utilisations les plus appropriées du cache de deuxième niveau dans ce cas? La documentation d'hibernation n'est pas du tout claire sur le fonctionnement réel du cache. Il n'y a que des instructions pour le configurer.

Mise à jour: J'ai donc compris que le cache de second niveau (sans cache de requête) serait bon pour charger les données par identifiants. Par exemple, j'ai un objet utilisateur que je souhaite vérifier pour chaque autorisation dans une application Web. Serait-ce un bon cas pour réduire l'accès à la base de données en mettant en cache l'utilisateur dans le cache de deuxième niveau? Comme si je stockais l'ID utilisateur dans la session ou n'importe où et quand je dois vérifier les autorisations, je chargerais l'utilisateur par son ID et vérifierais les autorisations.

83
palto

Tout d'abord, parlons du cache au niveau du processus (ou du cache de deuxième niveau comme ils l'appellent dans Hibernate). Pour que cela fonctionne, vous devez

  1. configurer le fournisseur de cache
  2. indiquer à hibernate quelles entités mettre en cache (directement dans le fichier hbm.xml si vous utilisez ce type de mappage).

Vous dites au fournisseur de cache combien d'objets 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 obtenez de la base de données, seules celles qui ne sont pas dans le cache seront sélectionnées dans la base de données. Cela augmente considérablement les performances. C'est utile quand:

  • Vous écrivez dans la base de données uniquement via Hibernate (car il a besoin d'un moyen de savoir quand changer ou invalider des entités dans le cache)
  • Vous lisez souvent des objets
  • Vous avez un seul nœud et vous n'avez pas de réplication. Sinon, vous devrez répliquer le cache lui-même (utilisez des caches distribués comme JGroups), ce qui ajoute plus de complexité et ne s'adapte pas aussi bien que les applications de partage rien.

Alors, quand le cache fonctionne-t-il?

  • Lorsque vous session.get() ou session.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, seulement lorsqu'il y a une possibilité de rechercher par ID, vous pouvez éliminer la frappe de la base de données.
  • Lorsque vos associations sont chargées paresseusement (ou empressées de sélections au lieu de jointures)

Mais cela ne fonctionne pas lorsque:

  • Si vous ne sélectionnez pas par ID. Encore une fois - le cache de deuxième niveau stocke une carte des identifiants des entités vers d'autres propriétés (il ne stocke pas réellement les objets, mais les données elles-mêmes), donc si votre recherche ressemble à ceci: from Authors where name = :name, alors vous n'atteignez pas le cache.
  • Lorsque vous utilisez HQL (même si vous utilisez where id = ?).
  • Si dans votre mappage, vous définissez fetch="join", cela signifie que pour charger les associations, les jointures seront utilisées partout au lieu d'instructions select distinctes. Le cache au niveau du processus ne fonctionne sur les objets enfants que si fetch="select" est utilisé.
  • Même si vous avez fetch="select" mais dans HQL, vous utilisez des jointures pour sélectionner des associations - ces jointures seront émises immédiatement et elles écraseront tout ce que vous avez spécifié dans hbm.xml ou des annotations.

Maintenant, à propos du cache de requête. Vous devez noter que ce n'est pas un cache séparé, c'est un ajout au cache au niveau du processus. Disons que vous avez une entité Pays. Il est statique, vous savez donc qu'à chaque fois, le même jeu de résultats sera obtenu lorsque vous direz from Country. C'est un candidat parfait pour le cache de requêtes, il stockera une liste de ID en lui-même et la prochaine fois que vous sélectionnerez tous les pays, il renverra cette liste dans le cache au niveau du processus et ce dernier, à son tour , renverra des objets pour chaque ID car ces objets sont déjà stockés dans le cache de deuxième niveau. Le cache de requêtes est invalidé chaque fois que quelque chose lié aux modifications de l'entité. Disons que vous avez configuré from Authors à placer dans un cache de requête. Il ne sera pas efficace car l'auteur change souvent. Vous devez donc utiliser Query Cache uniquement pour des données plus ou moins statiques.

93
  • le cache de deuxième niveau est un magasin de valeurs-clés. Cela ne fonctionne que si vous obtenez vos entités par identifiant
  • le cache de deuxième niveau est invalidé/mis à jour par entité lorsqu'une entité est mise à jour/supprimée via la mise en veille prolongée. Il n'est pas invalidé si la base de données est mise à jour d'une manière différente.
  • pour les requêtes (par exemple la liste des clients), utilisez le cache de requêtes.

En réalité, il est utile d'avoir un cache distribué de valeurs-clés - 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.

38
Bozho

Tard dans la soirée mais a voulu répondre systématiquement à ces questions que se posent de nombreux développeurs.

Prendre votre question une par une ici est ma réponse.

Q. Quand la mise en veille prolongée arrive-t-elle dans ce cache?

A. Le cache de premier niveau est associé à l'objet de 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é.

Supposons que j'ai configuré le cache de deuxième niveau mais pas la mise en cache des requêtes. Je veux mettre mes clients en cache, il y en a 50000. De quelles manières puis-je récupérer les clients du cache?

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 les objets avec leurs ID sont stockés dans le cache de deuxième niveau même. Donc, si vous activez le cache de requêtes, vous utiliserez la même ressource. C'est bien ça?

Q. Je suppose que je peux les obtenir par identifiant à partir du cache. Ce serait facile mais ne mériterait pas non plus d'être mis en cache. Mais que se passe-t-il si je veux faire un calcul avec tous mes clients. Supposons que je souhaite afficher une liste des clients, comment puis-je y accéder?

A. Répondu ci-dessus.

Q. Comment puis-je obtenir tous mes clients si la mise en cache des requêtes est désactivée?

A. Répondu ci-dessus.

Q. 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?

A. Hibernate n'a aucune idée mais vous pouvez utiliser d'autres caches IMDG/distribués tiers à implémenter comme hibernate second level cache et les invalider. par exemple. TayzGrid est un de ces produits et il y en a plus je suppose.

11
Basit Anwer