2 Stimmen

NHibernate - Zähler mit Nebenläufigkeit und Cache der zweiten Ebene

Ich bin neu bei NHibernate und habe Schwierigkeiten, es für meine aktuelle Website einzurichten. Diese Website wird auf mehreren Webservern mit einem Datenbankserver ausgeführt, was zu einigen Problemen mit der Nebenläufigkeit führt. Die Website wird schätzungsweise etwa 50.000 registrierte Benutzer haben, und jeder Benutzer wird eine Profilseite haben. Auf dieser Seite können andere Benutzer einen anderen Benutzer 'liken', ähnlich wie bei Facebook. Hier tritt das Problem der Nebenläufigkeit auf.

Ich dachte daran, den Second-Level-Cache zu verwenden, wahrscheinlich mit dem MemChached-Provider, da ich mehrere Webserver habe. Was ist der beste Weg, eine solche 'Like'-Funktion mit NHibernate zu implementieren? Ich dachte an drei Optionen:

  1. Verwenden Sie eine einfache Count()-Abfrage. Es wird eine Tabelle 'User_Likes' geben, in der jede Zeile einen Like von einem Benutzer zu einem anderen repräsentiert. Um die Anzahl der Likes anzuzeigen, würde ich einfach die Anzahl der Likes für einen Benutzer abfragen, was in der Datenbank als einfaches SELECT COUNT(*) FROM USER_LIKES WHERE ID = x oder so etwas übersetzt würde. Allerdings denke ich, dass dies mit einer großen Leistungseinbuße verbunden wäre, da jedes Mal, wenn ein Benutzer eine Profilseite besucht und einen anderen Benutzer mag, die Anzahl der Likes neu berechnet werden müsste, zweiter Cache-Level hin oder her.
  2. Verwenden Sie eine zusätzliche AnzahlDerLikes-Spalte in der Benutzertabelle und inkrementieren/dekrementieren Sie diesen Wert, wenn ein Benutzer einen anderen Benutzer mag oder nicht mag. Allerdings habe ich dabei Probleme mit der Nebenläufigkeit. Mit einer einfachen for-Schleife habe ich es getestet, indem ich einen Benutzer auf zwei Servern jeweils 1000 Mal gemocht habe, und das Ergebnis in der Datenbank waren insgesamt etwa 1100 Likes. Das ist ein Unterschied von 900. Ob ein realistischer Test oder nicht, dies ist natürlich keine Option. Jetzt habe ich mir optimistisches und pessimistisches Sperren als Lösung angesehen (ist es das?), aber mein aktuelles Repository-Muster ist im Moment leider nicht geeignet, dies zu verwenden, also bevor ich das behebe, würde ich gerne wissen, ob das der richtige Weg ist.
  3. Wie 2, aber mit benutzerdefiniertem HQL und dem Schreiben des Update-Statements selbst, etwas in der Art von UPDATE Benutzer SET AnzahlDerLikes = AnzahlDerLikes + 1 WHERE id = x. Das sollte mir keine Nebenläufigkeitsprobleme in der Datenbank bereiten, oder? Allerdings bin ich mir nicht sicher, ob ich Dateninkonsistenzen auf meinen mehreren Servern aufgrund des Second-Level-Cachings haben werde.

Also... Ich brauche wirklich einen Rat hier. Gibt es eine andere Option? Das fühlt sich nach einer häufigen Situation an und NHibernate muss das doch bestimmt auf elegante Weise unterstützen. Ich bin neu bei NHibernate, daher ist eine klare, ausführliche Antwort sowohl notwendig als auch geschätzt :-) Danke!

1voto

Pieter van Ginkel Punkte 28696

Ich vermute, dass Sie dieses Problem an weiteren Stellen sehen werden. Sie könnten dieses spezifische Problem mit 3. lösen, aber das lässt andere Stellen zurück, an denen Sie auf Gleichzeitigkeitsprobleme stoßen werden.

Was ich empfehlen würde, ist die Implementierung von pessimistischem Sperren. Der übliche Weg, dies zu tun, besteht darin, einfach eine Transaktion auf die gesamte HTTP-Anforderung anzuwenden. Mit dem BeginRequest in Ihrem Global.asax beginnen Sie eine Sitzung und Transaktion. Dann, im EndRequest committen Sie es. Mit dem Error-Ereignis gehen Sie den alternativen Weg, eine Rollback durchzuführen und die Sitzung zu verwerfen.

Dies ist eine ziemlich akzeptierte Art, NHibernate anzuwenden. Siehe zum Beispiel http://dotnetslackers.com/articles/aspnet/Configuring-NHibernate-with-ASP-NET.aspx.

0voto

Diego Mijelshon Punkte 52110

Ich würde mich für 3 entscheiden. Ich glaube, dass es in dieser Art von Anwendung nicht so kritisch ist, wenn einige Seiten für eine Weile einen leicht veralteten Wert anzeigen.

Soweit ich mich erinnere, führen HQL-Updates nicht zur Ungültigmachung des Cacheneintrags der Entität, daher müssen Sie dies möglicherweise manuell tun.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X