Abbiamo un'API Web MVC chiamata per scrivere transazioni per un importo specifico, in cui l'importo viene addebitato o accreditato sul saldo di un utente. Questo registra il saldo pre-transazione (PreAmount), l'importo e il saldo post-transazione (PostAmount). Abbiamo notato da una semplice query che utilizzava le funzioni LAG
e LEAD
di SQL Server che vi erano istanze di transazioni aggiunte dall'API che venivano inserite troppo velocemente (parzialmente a causa della mancanza di risorse per l'acquisto di un buon hardware per il server e IIS e SQL in esecuzione nella stessa casella). Abbiamo un meccanismo per impedire l'inserimento della transazione se esiste, ma sembra che la chiamata al metodo venga chiamata molto rapidamente, il che comporta che il record venga aggiunto più volte a causa di una condizione di competizione.
Il modo in cui tenterò di risolvere questo problema è utilizzando Dictionary<long, object>
. Il presupposto è che vogliamo che le transazioni per un cliente vengano immesse in sequenza in qualsiasi momento, ma non voglio bloccare richieste concorrenti per più clienti . Il dizionario dovrebbe contenere un numero ID cliente e il valore sarebbe un oggetto che posso bloccare. Quando una transazione sta per essere immessa, controllerò per vedere se c'è un numero ID cliente, e in caso contrario, inseriscilo lì):
private static Dictionary<long, object> customerLocker = new Dictionary<long, object>();
private static object dictLocker = new object();
Quindi, quando viene richiesta una richiesta di verifica di un saldo, o per inserire una transazione, vorrei quindi bloccare quell'oggetto ed eseguire il lavoro necessario:
lock (dictLocker)
{
if (!customerLocker.ContainsKey(customerID))
customerLocker.Add(customerID, new object());
}
lock (customerLocker[customerID])
{
// ... do the work needed for this customer
}
Questa è una buona soluzione al problema che sto avendo? Il blocco degli elementi all'interno di un dizionario causerà problemi? Ci proverò, ma mentre lo sto mettendo insieme, mi piacerebbe vedere l'input degli altri su questo scenario.