graph TD
A[请求] --> B[浏览器缓存]
B --> C[CDN缓存]
C --> D[应用层缓存]
D --> E[分布式缓存]
E --> F[数据库]
D --> D1[本地缓存]
D --> D2[进程缓存]
E --> E1[Redis集群]
E --> E2[热点数据]
E --> E3[冷数据]
三、Redis缓存策略
3.1 Cache-Aside策略
public class CacheAsideService
{
public async Task GetAsync(string key, Func> fetchFunction, TimeSpan? expiration = null)
{
var cached = await _redisService.GetAsync(key);
if (!string.IsNullOrEmpty(cached))
{
return JsonSerializer.Deserialize(cached);
}
var data = await fetchFunction();
if (data != null)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data), expiration ?? TimeSpan.FromMinutes(30));
}
return data;
}
public async Task UpdateAsync(string key, T data)
{
await _databaseService.UpdateAsync(data);
await _redisService.RemoveAsync(key);
}
public async Task DeleteAsync(string key)
{
await _databaseService.DeleteAsync(key);
await _redisService.RemoveAsync(key);
}
}
3.2 Read-Through策略
public class ReadThroughCacheService
{
public async Task GetAsync(string key)
{
var cached = await _redisService.GetAsync(key);
if (!string.IsNullOrEmpty(cached))
{
return JsonSerializer.Deserialize(cached);
}
var data = await _databaseService.GetAsync(key);
if (data != null)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
}
return data;
}
public async Task GetWithFallbackAsync(string key, Func> fallback)
{
var cached = await _redisService.GetAsync(key);
if (!string.IsNullOrEmpty(cached))
{
return JsonSerializer.Deserialize(cached);
}
var data = await fallback();
if (data != null)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
}
return data;
}
}
3.3 Write-Through策略
public class WriteThroughCacheService
{
public async Task UpdateAsync(string key, T data)
{
await _databaseService.UpdateAsync(data);
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
}
public async Task InsertAsync(string key, T data)
{
await _databaseService.InsertAsync(data);
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
}
public async Task DeleteAsync(string key)
{
await _databaseService.DeleteAsync(key);
await _redisService.RemoveAsync(key);
}
}
3.4 Write-Behind策略
public class WriteBehindCacheService
{
private readonly Queue _writeQueue = new Queue();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
public async Task UpdateAsync(string key, T data)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
await _semaphore.WaitAsync();
try
{
_writeQueue.Enqueue(new WriteOperation
{
Key = key,
Data = data,
OperationType = OperationType.Update
});
}
finally
{
_semaphore.Release();
}
_backgroundWriter.Enqueue();
}
private async Task ProcessWriteQueueAsync()
{
while (true)
{
await _semaphore.WaitAsync();
WriteOperation operation = null;
if (_writeQueue.Count > 0)
{
operation = _writeQueue.Dequeue();
}
_semaphore.Release();
if (operation == null)
{
await Task.Delay(100);
continue;
}
try
{
switch (operation.OperationType)
{
case OperationType.Update:
await _databaseService.UpdateAsync(operation.Data);
break;
case OperationType.Insert:
await _databaseService.InsertAsync(operation.Data);
break;
case OperationType.Delete:
await _databaseService.DeleteAsync(operation.Key);
break;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process write operation");
}
}
}
}
public enum OperationType { Insert, Update, Delete }
四、缓存问题与解决方案
4.1 缓存穿透
public class CachePenetrationService
{
private readonly BloomFilter _bloomFilter;
public async Task GetWithPenetrationProtectionAsync(string key, Func> fetchFunction)
{
if (!_bloomFilter.Contains(key))
{
return default;
}
var cached = await _redisService.GetAsync(key);
if (!string.IsNullOrEmpty(cached))
{
return JsonSerializer.Deserialize(cached);
}
var data = await fetchFunction();
if (data != null)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
_bloomFilter.Add(key);
}
return data;
}
}
public class BloomFilter
{
private readonly BitArray _bitArray;
private readonly int _hashCount;
private readonly HashAlgorithm[] _hashAlgorithms;
public bool Contains(string key)
{
foreach (var hashAlgorithm in _hashAlgorithms)
{
var hash = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(key));
var index = BitConverter.ToUInt32(hash, 0) % _bitArray.Length;
if (!_bitArray[(int)index])
{
return false;
}
}
return true;
}
public void Add(string key)
{
foreach (var hashAlgorithm in _hashAlgorithms)
{
var hash = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(key));
var index = BitConverter.ToUInt32(hash, 0) % _bitArray.Length;
_bitArray[(int)index] = true;
}
}
}
4.2 缓存击穿
public class CacheBreakdownService
{
private readonly ConcurrentDictionary _locks = new ConcurrentDictionary();
public async Task GetWithBreakdownProtectionAsync(string key, Func> fetchFunction)
{
var cached = await _redisService.GetAsync(key);
if (!string.IsNullOrEmpty(cached))
{
return JsonSerializer.Deserialize(cached);
}
var semaphore = _locks.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));
try
{
await semaphore.WaitAsync();
cached = await _redisService.GetAsync(key);
if (!string.IsNullOrEmpty(cached))
{
return JsonSerializer.Deserialize(cached);
}
var data = await fetchFunction();
if (data != null)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data));
}
return data;
}
finally
{
semaphore.Release();
_locks.TryRemove(key, out _);
}
}
}
4.3 缓存雪崩
public class CacheAvalancheService
{
public async Task SetWithRandomExpirationAsync(string key, T data, TimeSpan baseExpiration)
{
var random = new Random();
var extraExpiration = TimeSpan.FromSeconds(random.Next(60));
await _redisService.SetAsync(key, JsonSerializer.Serialize(data), baseExpiration + extraExpiration);
}
public async Task SetWithDistributedExpirationAsync(string key, T data, TimeSpan baseExpiration)
{
var hash = key.GetHashCode();
var distributedExpiration = TimeSpan.FromSeconds(Math.Abs(hash) % 300);
await _redisService.SetAsync(key, JsonSerializer.Serialize(data), baseExpiration + distributedExpiration);
}
public async Task SetWithWarmupAsync(string key, T data)
{
await _redisService.SetAsync(key, JsonSerializer.Serialize(data), TimeSpan.FromHours(1));
await _warmupScheduler.ScheduleWarmup(key, TimeSpan.FromMinutes(50));
}
}
五、多级缓存实现
5.1 多级缓存架构
graph TD
A[请求] --> B[本地缓存]
B --> C[分布式缓存]
C --> D[数据库]
B --> B1[命中]
B --> B2[未命中]
C --> C1[命中]
C --> C2[未命中]
D --> D1[返回数据]
D1 --> C3[写入分布式缓存]
C3 --> B3[写入本地缓存]
5.2 多级缓存实现
public class MultiLevelCacheService
{
private readonly IMemoryCache _localCache;
private readonly IRedisCache _redisCache;
private readonly IDatabaseService _databaseService;
public async Task GetAsync(string key, Func> fetchFunction, TimeSpan? localExpiration = null, TimeSpan? remoteExpiration = null)
{
var localCached = _localCache.Get(key);
if (localCached != null)
{
return localCached;
}
var remoteCached = await _redisCache.GetAsync(key);
if (!string.IsNullOrEmpty(remoteCached))
{
var data = JsonSerializer.Deserialize(remoteCached);
_localCache.Set(key, data, localExpiration ?? TimeSpan.FromMinutes(5));
return data;
}
var data = await fetchFunction();
if (data != null)
{
await _redisCache.SetAsync(key, JsonSerializer.Serialize(data), remoteExpiration ?? TimeSpan.FromMinutes(30));
_localCache.Set(key, data, localExpiration ?? TimeSpan.FromMinutes(5));
}
return data;
}
public async Task InvalidateAsync(string key)
{
_localCache.Remove(key);
await _redisCache.RemoveAsync(key);
}
public async Task InvalidateLocalAsync(string key)
{
_localCache.Remove(key);
}
public async Task InvalidateRemoteAsync(string key)
{
await _redisCache.RemoveAsync(key);
}
}
5.3 热点数据处理
public class HotDataService
{
public async Task GetHotDataAsync(string key, Func> fetchFunction)
{
var localKey = $"hot:{key}";
var localCached = _localCache.Get(localKey);
if (localCached != null)
{
return localCached;
}
var remoteKey = $"hot:{key}";
var remoteCached = await _redisCache.GetAsync(remoteKey);
if (!string.IsNullOrEmpty(remoteCached))
{
var data = JsonSerializer.Deserialize(remoteCached);
_localCache.Set(localKey, data, TimeSpan.FromMinutes(10));
return data;
}
var data = await fetchFunction();
if (data != null)
{
await _redisCache.SetAsync(remoteKey, JsonSerializer.Serialize(data), TimeSpan.FromHours(1));
_localCache.Set(localKey, data, TimeSpan.FromMinutes(10));
}
return data;
}
public async Task WarmupHotDataAsync(List keys)
{
foreach (var key in keys)
{
await GetHotDataAsync
六、缓存监控与优化
6.1 缓存监控
public class CacheMonitor
{
public async Task GetMetricsAsync()
{
var redisInfo = await _redisService.GetInfoAsync();
return new CacheMetrics
{
Hits = redisInfo.KeyspaceHits,
Misses = redisInfo.KeyspaceMisses,
HitRate = redisInfo.KeyspaceHits / (double)(redisInfo.KeyspaceHits + redisInfo.KeyspaceMisses) * 100,
MemoryUsage = redisInfo.UsedMemory,
MemoryUsagePercent = redisInfo.UsedMemoryPercent,
KeyCount = redisInfo.KeyCount,
ExpiredKeys = redisInfo.ExpiredKeys
};
}
public async Task MonitorAsync()
{
var metrics = await GetMetricsAsync();
if (metrics.HitRate < 80)
{
await _alertService.SendAlert("缓存命中率低",
$"命中率: {metrics.HitRate:F1}%");
}
if (metrics.MemoryUsagePercent > 90)
{
await _alertService.SendAlert("缓存内存使用过高",
$"内存使用: {metrics.MemoryUsagePercent:F1}%");
}
}
}
public class CacheMetrics
{
public long Hits { get; set; }
public long Misses { get; set; }
public double HitRate { get; set; }
public long MemoryUsage { get; set; }
public double MemoryUsagePercent { get; set; }
public long KeyCount { get; set; }
public long ExpiredKeys { get; set; }
}
6.2 缓存优化
public class CacheOptimizer
{
public async Task OptimizeAsync()
{
await OptimizeMemoryUsageAsync();
await OptimizeHitRateAsync();
await OptimizeExpirationAsync();
}
private async Task OptimizeMemoryUsageAsync()
{
var memoryInfo = await _redisService.GetMemoryInfoAsync();
if (memoryInfo.UsedMemoryPercent > 80)
{
await _redisService.ConfigureMaxMemoryPolicy("allkeys-lru");
await _redisService.SetMaxMemory(2 * 1024 * 1024 * 1024);
}
}
private async Task OptimizeHitRateAsync()
{
var slowQueries = await _redisService.GetSlowQueriesAsync();
foreach (var query in slowQueries)
{
await _redisService.AddIndex(query.Key);
}
}
private async Task OptimizeExpirationAsync()
{
var keysWithNoExpiration = await _redisService.GetKeysWithNoExpirationAsync();
foreach (var key in keysWithNoExpiration)
{
await _redisService.SetExpiration(key, TimeSpan.FromHours(24));
}
}
}
七、缓存最佳实践
7.1 缓存设计原则
合理选择缓存策略
设置合理的过期时间
使用多级缓存
处理缓存一致性问题
监控缓存状态
7.2 缓存键设计
public class CacheKeyGenerator
{
public string GenerateKey(string prefix, params object[] parts)
{
var keyParts = new List { prefix };
keyParts.AddRange(parts.Select(p => p?.ToString() ?? "null"));
return string.Join(":", keyParts);
}
public string GenerateUserKey(long userId)
{
return GenerateKey("user", userId);
}
public string GenerateProductKey(long productId)
{
return GenerateKey("product", productId);
}
public string GenerateOrderKey(long orderId)
{
return GenerateKey("order", orderId);
}
public string GenerateHotKey(string key)
{
return GenerateKey("hot", key);
}
}
7.3 缓存一致性
public class CacheConsistencyService
{
public async Task UpdateWithConsistencyAsync(string key, T data)
{
await _databaseService.UpdateAsync(data);
await _redisCache.RemoveAsync(key);
_localCache.Remove(key);
await Task.Delay(100);
var freshData = await _databaseService.GetAsync(key);
if (freshData != null)
{
await _redisCache.SetAsync(key, JsonSerializer.Serialize(freshData));
_localCache.Set(key, freshData);
}
}
public async Task RebuildCacheAsync(string key)
{
var data = await _databaseService.GetAsync(key);
if (data != null)
{
await _redisCache.SetAsync(key, JsonSerializer.Serialize(data));
_localCache.Set(key, data);
}
}
}