2010-11-22 3 views
2

Je suis nouveau à NHibernate et j'ai de la difficulté à le configurer pour mon site actuel. Ce site fonctionnera sur plusieurs serveurs Web avec un serveur de base de données, ce qui me laisse face à certains problèmes de concurrence. Le site aura environ 50.000 utilisateurs enregistrés, et chaque utilisateur aura une page de profil. Sur cette page, d'autres utilisateurs peuvent "aimer" un autre utilisateur, un peu comme Facebook. C'est dans ce cas que le problème de concurrence est apparu.NHibernate - compteurs avec accès simultané et mise en mémoire cache de second niveau

Je pensais à utiliser un cache de second niveau, très probablement en utilisant le fournisseur MemChached car j'aurais plusieurs serveurs Web. Quelle est la meilleure façon de mettre en œuvre une telle fonction «J'aime» en utilisant NHibernate? Je pensais à trois options:

  1. Utilisez une requête simple Count(). Il y aura une table 'User_Likes' où chaque rangée représentera un semblable d'un utilisateur à l'autre. Pour afficher le nombre le nombre de j'aime, je demanderais simplement le nombre de J'aime pour un utilisateur, qui serait traduit à la base de données comme un simple SELECT COUNT(*) FROM USER_LIKES WHERE ID = x ou quelque chose. Cependant, je suppose que cela serait accompagné d'une pénalité de performance, car chaque fois qu'un utilisateur visite une page de profil et comme un autre utilisateur, le nombre de likes doit être recalculé, le cache de second niveau ou pas.
  2. Utilisez une colonne NumberOfLikes supplémentaire dans le tableau Utilisateur et augmentez/décrémentez cette valeur lorsqu'un utilisateur aime ou n'aime pas un autre utilisateur. Cela me donne cependant des problèmes de concurrence. En utilisant une simple boucle for, je l'ai testé en aimant un utilisateur 1000 fois sur deux serveurs et le résultat dans la base de données était d'environ 1100 j'aime total. C'est une différence de 900. Que ce soit un test réaliste ou non, ce n'est bien sûr pas une option. Maintenant, j'ai regardé verrouillage optimiste et pessimiste comme une solution (est-ce?) Mais mon modèle de dépôt actuel est, pour le moment, pas adapté pour utiliser ce que j'ai peur, alors avant de résoudre ce problème, je voudrais savoir si c'est la bonne façon d'y aller.
  3. Comme 2, mais en utilisant HQL personnalisé et écrire l'instruction de mise à jour moi-même, quelque chose le long des lignes de UPDATE User SET NumberOfLikes = NumberOfLikes + 1 WHERE id = x. Cela ne me donnera pas des problèmes de concurrence dans la base de données non? Cependant, je ne suis pas sûr si je vais avoir un datamismatch sur mes multiples serveurs en raison de la mise en cache de second niveau.

Alors ... J'ai vraiment besoin de conseils ici. Y a-t-il une autre option? Cela ressemble à une situation commune et certainement NHibernate doit soutenir cela d'une manière élégante. Je suis nouveau à NHIbernate donc une réponse claire et détaillée est à la fois nécessaire et appréciée :-) Merci!

Répondre

1

Je suspecte que vous verrez ce problème dans plus d'endroits. Vous pouvez résoudre ce problème spécifique avec 3., mais cela laisse d'autres emplacements où vous allez rencontrer des problèmes de concurrence.

Ce que je conseillerais est d'implémenter le verrouillage pessimiste. La manière habituelle de le faire consiste simplement à appliquer une transaction à l'ensemble de la requête HTTP. Avec le BeginRequest dans votre Global.asax, vous lancez une session et une transaction. Ensuite, dans le EndRequest, vous le validez. Avec l'événement Error, vous accédez au chemin alternatif d'annulation et de suppression de la session.

C'est une manière tout à fait acceptée d'appliquer NHibernate. Voir par exemple http://dotnetslackers.com/articles/aspnet/Configuring-NHibernate-with-ASP-NET.aspx.

+0

Merci. J'ai posé une autre question: http://stackoverflow.com/questions/4253998/nhibernate-pessimistic-locking-not-working qui doit être résolu avant que je sache si c'est la voie à suivre. – Razzie

+0

@Razzie - Ajout d'une réponse. –

0

J'irais avec . Je crois que dans ce genre d'application ce n'est pas si important si certaines pages montrent une valeur légèrement dépassée pendant un moment.

Les mises à jour IIRC, HQL ne pas invalider l'entrée de l'antémémoire d'entité, donc vous devrez peut-être le faire manuellement.

Questions connexes