Ich versuche, einen einfachen Service zu implementieren (C#, SQL Server, Entity Framework), die vorher (zum Beispiel geschehen, Zahlungen von Kunden mit mehreren Check verarbeiten würden, ein einziges Produkt kann mehr als 10 mal am Tag nicht gekauft werden, etc.)Wie Sie den richtige Gleichzeitigkeit/Verriegelungsmechanismus mit Entity Framework wählen
die vereinfachte Version des Codes ist die folgende:
public void ExecutePayment(int productId, PaymentInfo paymentInfo)
{
using (var dbContext = new MyDbContext())
{
var stats = dbContext.PaymentStatistics.Single(s => s.ProductId== productId);
var limits = dbContext.Limits.Single(l => l.ProductId == productId);
int newPaymentCount = stats.DailyPaymentCount + 1;
if (newPaymentCount > limits.MaxDailyPaymentCount)
{
throw new InvalidOperationException("Exceeded payment count limit");
}
// other limits here...
var paymentResult = ProcessPayment(paymentInfo); <-- long operation, takes 2-3 seconds
if (paymentResult.Success)
{
stats.DailyPaymentCount = newPaymentCount;
}
dbContext.SaveChanges();
}
}
Was mich betrifft mögliche Parallelitätsprobleme sind. Ich muss sicherstellen, dass keine 2 Threads/Prozesse gleichzeitig stats.PaymentCount
prüfen/aktualisieren, sonst sind die Statistiken nicht mehr synchron.
Ich dachte über das gesamte Verfahren in eine Distributed Lock (zB this implementation verwenden) Umwickeln wie folgt aus:
string lockKey = $"processing-payment-for-product-{productId}";
var myLock = new SqlDistributedLock(lockKey);
using (myLock.Acquire())
{
ExecutePayment(productId, paymentInfo);
}
Aber die Beschäftigung mit diesem Ansatz ist, dass ProcessPayment sehr langsam (2-3 Sekunden) Dies bedeutet, dass alle gleichzeitigen Zahlungsanforderungen für dasselbe Produkt 2-3 Sekunden warten müssen, bevor die Limitprüfungen überhaupt beginnen können.
Kann mir jemand eine gute Sperr Lösung für diesen Fall vorschlagen?
Haben Sie auch Zahlungen in Datenbank speichern? Ich meine ein Zahlungsobjekt, das eine ausstehende/fehlgeschlagene/abgeschlossene Zahlung darstellt. – Evk
@Evk, ja, ist SQL Server derzeit der einzige Speichermechanismus für alle Arten von Anwendungsdaten –