How to prevent the Cache Stampede (Thundering Herd) problem when cache keys expire:
When a popular cache key expires, 100 concurrent requests all miss the cache simultaneously and query the database at once, overwhelming the database server.
Solution: Double-Checked Locking with SemaphoreSlim:
public async Task<string> GetCachedDataAsync(string key)
{
if (_cache.TryGetValue(key, out string val)) return val;
await _semaphore.WaitAsync();
try
{
if (_cache.TryGetValue(key, out val)) return val; // Double check!
val = await FetchFromDatabaseAsync(key);
_cache.Set(key, val, TimeSpan.FromMinutes(10));
return val;
}
finally { _semaphore.Release(); }
}