Sperren in ASP.NET ordnungsgemäß

7

Ich habe eine ASP.NET-Site mit einer ziemlich langsamen Suchfunktion, und ich möchte die Leistung verbessern, indem ich die Ergebnisse eine Stunde lang dem Cache hinzufüge und dabei die Abfrage als Cache-Schlüssel verwende:

%Vor%

Nehmen wir an, Besucher A macht eine Suche. Der Cache ist leer, die Sperre ist gesetzt und das Ergebnis wird von der Datenbank angefordert. Jetzt kommt Besucher B mit einer anderen Suche: Wird Besucher B nicht warten müssen, bis die Suche von Besucher A abgeschlossen ist? Was ich wirklich wollte, war, dass B die Datenbank sofort aufruft, weil die Ergebnisse unterschiedlich sein werden und die Datenbank mehrere Anfragen bearbeiten kann - ich möchte einfach keine unnötigen unnötigen Abfragen wiederholen.

Was wäre der richtige Ansatz für dieses Szenario?

    
Jakob Gade 07.04.2011, 09:16
quelle

3 Antworten

25

Wenn Sie nicht absolut sicher sind, dass es wichtig ist, keine redundanten Abfragen zu haben, würde ich die Sperrung vermeiden. Der ASP.NET-Cache ist inhärent threadsicher, daher besteht der einzige Nachteil des folgenden Codes darin, dass Sie möglicherweise kurzzeitig einige redundante Abfragen sehen, die miteinander konkurrieren, wenn der zugehörige Cache-Eintrag abläuft:

%Vor%

Wenn Sie entscheiden, dass Sie wirklich alle redundanten Abfragen vermeiden müssen, können Sie eine Reihe von feineren Sperren verwenden, eine Sperre pro Abfrage:

%Vor%     
LukeH 07.04.2011, 12:12
quelle
8

Dein Code hat eine potentielle Race Condition:

%Vor%

Im Allgemeinen würde ich das Sperren nicht verwenden und würde dies folgendermaßen tun, um die Wettlaufsituation zu vermeiden:

%Vor%

Im obigen Fall könnten mehrere Threads versuchen, Daten zu laden, wenn sie ungefähr gleichzeitig einen Cache-Fehltreffer entdecken. In der Praxis ist dies wahrscheinlich selten und in den meisten Fällen unwichtig, da die Daten, die sie laden, gleichwertig sind.

Wenn Sie jedoch eine Sperre verwenden möchten, um dies zu verhindern, können Sie dies folgendermaßen tun:

%Vor%     
Joe 07.04.2011 10:38
quelle
0

Ihr Code ist korrekt . Sie verwenden auch double-if-sandwitching-lock , was Wettlaufbedingungen verhindert was eine häufige Falle ist, wenn sie nicht benutzt wird. Dadurch wird kein Zugriff auf vorhandene Objekte im Cache gesperrt.

Das einzige Problem ist, wenn viele Clients gleichzeitig in den Cache eingefügt werden und sie sich hinter der Sperre einreihen, aber was ich tun würde, ist results = GetResultsFromSlowDb(query); außerhalb der Sperre zu setzen:

%Vor%

Wenn das langsam ist, ist Ihr Problem anderswo.

    
Aliostad 07.04.2011 09:26
quelle

Tags und Links