2010-11-22 10 views
2

Ich bin neu in NHibernate und habe Schwierigkeiten bei der Einrichtung für meine aktuelle Website. Diese Website wird unter mehreren Webservern mit einem Datenbankserver ausgeführt, was einige Nebenläufigkeitsprobleme verursacht. Die Website wird schätzungsweise 50.000 Benutzer oder so registriert haben, und jeder Benutzer wird eine Profilseite haben. Auf dieser Seite können andere Nutzer ähnlich wie Facebook einen anderen Nutzer "mögen". Das ist, wo das Nebenläufigkeitsproblem in tritt.NHibernate - Zähler mit Nebenläufigkeit und Second-Level-Caching

Ich dachte über die Verwendung von Second-Level-Cache, wahrscheinlich mit dem MemChached-Provider, da ich mehrere Webserver haben. Was ist der beste Weg, um 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 ein Like von einem Benutzer zu einem anderen darstellt. Um die Anzahl der Likes anzuzeigen, würde ich einfach die Anzahl der Likes für einen Benutzer fragen, die als einfache SELECT COUNT(*) FROM USER_LIKES WHERE ID = x oder etwas in die Datenbank übersetzt werden würde. Ich nehme jedoch an, dass dies mit einer großen Leistungseinbuße verbunden wäre, da jedes Mal, wenn ein Benutzer eine Profilseite besucht und wie bei einem anderen Benutzer die Anzahl der Likes neu berechnet werden muss, der Cache der zweiten Ebene oder nicht.
  2. Verwenden Sie eine zusätzliche NumberOfLikes Spalte in der Benutzertabelle und erhöhen/verringern Sie diesen Wert, wenn ein Benutzer einen anderen Benutzer mag oder nicht mag. Dies gibt mir jedoch Nebenläufigkeitsprobleme. Unter Verwendung einer einfachen for-Schleife habe ich es getestet, indem ich einen Benutzer 1000-mal auf zwei Servern mochte und das Ergebnis in der db war ungefähr 1100 mag insgesamt. Das ist ein Unterschied von 900. Ob ein realistischer Test oder nicht, das ist natürlich keine Option. Nun, ich schaute optimistisch und pessimistisch sperren als Lösung (ist es?), Aber meine aktuelle Repository-Muster ist im Moment nicht geeignet, um dies zu verwenden, fürchte ich, also bevor ich das beheben, würde ich gerne zu wissen, ob dies der richtige Weg ist.
  3. Wie 2, aber mit benutzerdefinierten HQL und schreibe die Update-Anweisung selbst, etwas in Richtung UPDATE User SET NumberOfLikes = NumberOfLikes + 1 WHERE id = x. Das wird mir keine Gleichzeitigkeitsprobleme in der Datenbank geben, richtig? Ich bin jedoch nicht sicher, ob ich aufgrund der Zwischenspeicherung auf der zweiten Ebene einen Datamismatch auf meinen mehreren Servern haben werde.

Also ... ich brauche wirklich einen Rat hier. Gibt es eine andere Option? Das fühlt sich wie eine gewöhnliche Situation an und sicherlich muss NHibernate dies auf elegante Weise unterstützen. Ich bin neu bei NHIbernate, also ist eine klare, detaillierte Antwort sowohl notwendig als auch geschätzt :-) Danke!

Antwort

1

Ich vermute, Sie werden dieses Problem an mehreren Standorten sehen. Sie könnten dieses spezielle Problem mit 3. lösen, aber das lässt andere Speicherorte zurück, an denen Parallelitätsprobleme auftreten.

Was ich empfehlen würde, pessimistisches Sperren zu implementieren. Der übliche Weg, dies zu tun, besteht darin, nur eine Transaktion auf die gesamte HTTP-Anfrage anzuwenden. Mit dem BeginRequest in Ihrem Global.asax starten Sie eine Sitzung und eine Transaktion. Dann, in der EndRequest committen Sie es. Mit dem Ereignis Error gehen Sie den alternativen Pfad zum Durchführen eines Rollbacks und zum Verwerfen der Sitzung.

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

+0

Danke. Ich stellte eine andere Frage: http://stackoverflow.com/questions/4253998/nhibernate-pessimistic-locking-not-working, die gelöst werden muss, bevor ich weiß, ob dies der richtige Weg ist. – Razzie

+0

@Razzie - Eine Antwort hinzugefügt. –

0

Ich würde mit gehen. Ich glaube, dass dies in dieser Art von Anwendung nicht so kritisch ist, wenn einige Seiten für eine Weile einen etwas veralteten Wert aufweisen.

IIRC, HQL-Updates tun nicht den Entity-Cache-Eintrag ungültig machen, so dass Sie es möglicherweise manuell tun müssen.