樟刨鹊稍引言

在现代分布式应用架构中,缓存已成为提升系统性能和用户体验的关键技术组件。随着业务规模的不断扩大和并发量的持续增长,单一级别的缓存往往无法满足复杂的性能需求。多级缓存架构通过在不同层次构建缓存体系,能够显著提升数据访问效率,降低数据库负载,并提供更好的系统可扩展性。

本文将深入探讨C#环境下多级缓存的架构设计与实现,重点分析内存缓存(Memory Cache)与Redis分布式缓存的协同工作机制,并详细阐述如何通过Redis的发布-订阅(Pub/Sub)模式实现不同节点间的缓存状态同步。

1. 多级缓存理论基础

1.1 缓存层次结构理论

缓存的本质是利用时间局部性(Temporal Locality)和空间局部性(Spatial Locality)原理,将频繁访问的数据存储在更快的存储介质中。在计算机系统中,从CPU缓存到内存,从内存到磁盘,都遵循着这种层次化的存储架构。

1.1.1 缓存访问模式

CPU Cache (L1/L2/L3) → Memory → Disk Storage

↑ ↑ ↑

快速访问 中等速度 慢速访问

小容量 中等容量 大容量

昂贵 适中 便宜

在应用层面,多级缓存同样遵循类似的原理:

L1缓存(进程内存缓存): 访问速度最快,容量相对较小,仅在当前进程内有效

L2缓存(分布式缓存): 访问速度中等,容量较大,在多个节点间共享

L3缓存(数据库查询缓存): 访问速度最慢,但提供持久化存储

1.2 缓存一致性理论

1.2.1 CAP定理在缓存系统中的应用

根据CAP定理(Consistency, Availability, Partition tolerance),在分布式缓存系统中,我们无法同时保证:

一致性(Consistency): 所有节点在同一时间具有相同的数据

可用性(Availability): 系统持续可用,即使某些节点出现故障

分区容错性(Partition Tolerance): 系统能够容忍网络分区故障

在实际应用中,我们通常采用最终一致性(Eventually Consistency)模型,通过合理的同步策略和过期机制来平衡性能与一致性。

1.2.2 缓存穿透、击穿、雪崩问题

缓存穿透(Cache Penetration):

现象:查询不存在的数据,绕过缓存直接访问数据库

解决方案:布隆过滤器、空值缓存

缓存击穿(Cache Breakdown):

现象:热点数据过期时,大量并发请求同时访问数据库

解决方案:分布式锁、热点数据永不过期

缓存雪崩(Cache Avalanche):

现象:大量缓存同时失效,导致数据库压力骤增

解决方案:过期时间随机化、多级缓存、熔断机制

2. 架构设计与技术选型

2.0 系统架构流程图

2.0.1 多级缓存整体架构

数据层

多级缓存系统

监控系统

同步机制

缓存层

应用层

L2缓存 - Redis分布式缓存

L1缓存 - 内存缓存

客户端应用

Controller层

Service层

多级缓存管理器

IMemoryCache

高级内存缓存

Redis连接管理器

Redis分布式缓存

Redis集群

Redis Pub/Sub

缓存同步服务

事件队列

监控服务

健康检查

性能指标

数据库

外部API

2.0.2 缓存操作流程图

数据库

同步服务

L2 Redis缓存

L1内存缓存

多级缓存管理器

客户端

数据库

同步服务

L2 Redis缓存

L1内存缓存

多级缓存管理器

客户端

读取操作流程 (GetOrSet)

par

[并行设置缓存]

[发布同步事件]

alt

[L2 缓存命中]

[L2 缓存未命中]

alt

[L1 缓存命中]

[L1 缓存未命中]

更新操作流程

par

[并行更新所有级别]

删除操作流程

par

[并行删除所有级别]

GetOrSet(key, factory)

Get(key)

返回数据

返回结果 (L1 Hit)

返回 null

Get(key)

返回数据

Set(key, data) [异步提升]

返回结果 (L2 Hit)

返回 null

factory() 执行

返回原始数据

Set(key, data)

Set(key, data)

PublishSync(SET, key)

返回结果 (DB Hit)

Set(key, data)

Set(key, data)

Set(key, data)

PublishSync(SET, key)

通知其他节点更新L1缓存

返回结果

Remove(key)

Remove(key)

Remove(key)

PublishSync(REMOVE, key)

通知其他节点删除L1缓存

返回结果

2.0.3 Redis发布-订阅同步机制

Redis集群

节点C

节点B

节点A

Unsupported markdown: list

Unsupported markdown: list

Unsupported markdown: list

Unsupported markdown: list

Unsupported markdown: list

Unsupported markdown: list

Unsupported markdown: list

应用A

L1缓存A

L2缓存A

同步服务A

应用B

L1缓存B

L2缓存B

同步服务B

应用C

L1缓存C

L2缓存C

同步服务C

Redis Pub/Sub频道

cache_sync:events

2.0.4 缓存降级策略流程

L1Only

DirectAccess

ThrowException

开始缓存操作

L1缓存

是否可用?

尝试L1缓存操作

L1操作

成功?

返回L1结果

L2缓存

是否可用?

尝试L2缓存操作

L2操作

成功?

返回L2结果

降级策略

仅使用L1缓存

直接访问数据库

抛出异常

尝试L1操作

成功?

返回L1结果

执行数据库查询

返回数据库结果

返回错误

结束

2. 架构设计与技术选型

2.1 整体架构设计

多级缓存架构采用分层设计模式,每一层都有明确的职责和边界:

┌─────────────────────────────────────────────────────┐

│ 应用层 │

├─────────────────────────────────────────────────────┤

│ 多级缓存管理器 │

├─────────────────┬───────────────────────────────────┤

│ L1内存缓存 │ L2 Redis缓存 │

│ (MemoryCache) │ (StackExchange.Redis) │

├─────────────────┴───────────────────────────────────┤

│ Redis Pub/Sub 同步机制 │

├─────────────────────────────────────────────────────┤

│ 数据持久层 │

└─────────────────────────────────────────────────────┘

2.2 技术选型分析

2.2.1 内存缓存选型

Microsoft.Extensions.Caching.Memory:

优势:.NET官方支持,与DI容器无缝集成,支持过期策略和内存压力驱逐

适用场景:单体应用、微服务单实例缓存

特性:线程安全、支持泛型、内置压缩和序列化

System.Runtime.Caching.MemoryCache:

优势:.NET Framework传统方案,功能成熟

劣势:不支持.NET Core,API相对古老

2.2.2 分布式缓存选型

StackExchange.Redis:

优势:高性能、功能全面、支持集群、活跃的社区支持

特性:异步操作、连接复用、故障转移、Lua脚本支持

版本选择:推荐使用2.6+版本,支持.NET 6+的新特性

ServiceStack.Redis:

优势:易用性好,文档完善

劣势:商业许可限制,性能相对较低

2.3 架构模式选择

2.3.1 Cache-Aside Pattern(缓存旁路模式)

这是最常用的缓存模式,应用程序负责管理缓存的读取和更新:

读取流程:

1. 应用程序尝试从缓存读取数据

2. 如果缓存命中,直接返回数据

3. 如果缓存未命中,从数据库读取数据

4. 将数据写入缓存,然后返回给应用程序

更新流程:

1. 更新数据库

2. 删除或更新缓存中的对应数据

2.3.2 Write-Through Pattern(写透模式)

写入流程:

1. 应用程序写入缓存

2. 缓存服务同步写入数据库

3. 确认写入完成后返回成功

2.3.3 Write-Behind Pattern(写回模式)

写入流程:

1. 应用程序写入缓存

2. 立即返回成功

3. 缓存服务异步批量写入数据库

3. 内存缓存层实现详解

3.1 IMemoryCache 核心接口分析

Microsoft.Extensions.Caching.Memory.IMemoryCache接口提供了缓存操作的核心方法:

public interface IMemoryCache : IDisposable

{

bool TryGetValue(object key, out object value);

ICacheEntry CreateEntry(object key);

void Remove(object key);

}

3.2 高级内存缓存封装实现

using Microsoft.Extensions.Caching.Memory;

using Microsoft.Extensions.Logging;

using Microsoft.Extensions.Options;

using System;

using System.Collections.Concurrent;

using System.Threading;

using System.Threading.Tasks;

using System.Text.RegularExpressions;

using System.Runtime.Serialization;

///

/// 缓存异常基类

///

public abstract class CacheException : Exception

{

protected CacheException(string message) : base(message) { }

protected CacheException(string message, Exception innerException) : base(message, innerException) { }

}

///

/// 缓存连接异常

///

public class CacheConnectionException : CacheException

{

public CacheConnectionException(string message) : base(message) { }

public CacheConnectionException(string message, Exception innerException) : base(message, innerException) { }

}

///

/// 缓存序列化异常

///

public class CacheSerializationException : CacheException

{

public CacheSerializationException(string message) : base(message) { }

public CacheSerializationException(string message, Exception innerException) : base(message, innerException) { }

}

///

/// 缓存超时异常

///

public class CacheTimeoutException : CacheException

{

public CacheTimeoutException(string message) : base(message) { }

public CacheTimeoutException(string message, Exception innerException) : base(message, innerException) { }

}

///

/// 缓存验证异常

///

public class CacheValidationException : CacheException

{

public CacheValidationException(string message) : base(message) { }

public CacheValidationException(string message, Exception innerException) : base(message, innerException) { }

}

///

/// 线程安全的缓存统计追踪器

///

public class CacheStatisticsTracker

{

private long _totalOperations = 0;

private long _l1Hits = 0;

private long _l2Hits = 0;

private long _totalMisses = 0;

private readonly object _lock = new object();

public void RecordOperation()

{

Interlocked.Increment(ref _totalOperations);

}

public void RecordHit(CacheLevel level)

{

switch (level)

{

case CacheLevel.L1:

Interlocked.Increment(ref _l1Hits);

break;

case CacheLevel.L2:

Interlocked.Increment(ref _l2Hits);

break;

}

}

public void RecordMiss()

{

Interlocked.Increment(ref _totalMisses);

}

public CacheStatisticsSnapshot GetSnapshot()

{

return new CacheStatisticsSnapshot

{

TotalOperations = Interlocked.Read(ref _totalOperations),

L1Hits = Interlocked.Read(ref _l1Hits),

L2Hits = Interlocked.Read(ref _l2Hits),

TotalMisses = Interlocked.Read(ref _totalMisses)

};

}

public void Reset()

{

lock (_lock)

{

Interlocked.Exchange(ref _totalOperations, 0);

Interlocked.Exchange(ref _l1Hits, 0);

Interlocked.Exchange(ref _l2Hits, 0);

Interlocked.Exchange(ref _totalMisses, 0);

}

}

}

///

/// 缓存统计快照

///

public class CacheStatisticsSnapshot

{

public long TotalOperations { get; init; }

public long L1Hits { get; init; }

public long L2Hits { get; init; }

public long TotalMisses { get; init; }

public long TotalHits => L1Hits + L2Hits;

public double OverallHitRatio => TotalOperations == 0 ? 0 : (double)TotalHits / TotalOperations;

public double L1HitRatio => TotalOperations == 0 ? 0 : (double)L1Hits / TotalOperations;

public double L2HitRatio => TotalOperations == 0 ? 0 : (double)L2Hits / TotalOperations;

}

///

/// 缓存数据验证器接口

///

public interface ICacheDataValidator

{

bool IsValid(T value);

void ValidateKey(string key);

bool IsSafeForSerialization(T value);

}

///

/// 默认缓存数据验证器

///

public class DefaultCacheDataValidator : ICacheDataValidator

{

private readonly ILogger _logger;

private readonly HashSet _forbiddenTypes;

private readonly Regex _keyValidationRegex;

public DefaultCacheDataValidator(ILogger logger)

{

_logger = logger;

_forbiddenTypes = new HashSet

{

typeof(System.IO.FileStream),

typeof(System.Net.Sockets.Socket),

typeof(System.Threading.Thread),

typeof(System.Threading.Tasks.Task)

};

// 限制key格式:只允许字母数字下划线冒号和点

_keyValidationRegex = new Regex(@"^[a-zA-Z0-9_:.-]+$", RegexOptions.Compiled);

}

public bool IsValid(T value)

{

if (value == null) return true;

var valueType = value.GetType();

// 检查禁止类型

if (_forbiddenTypes.Contains(valueType))

{

_logger.LogWarning("Forbidden type in cache: {Type}", valueType.Name);

return false;

}

// 检查循环引用(简化版)

if (HasCircularReference(value))

{

_logger.LogWarning("Circular reference detected in cache value");

return false;

}

return true;

}

public void ValidateKey(string key)

{

if (string.IsNullOrWhiteSpace(key))

throw new CacheValidationException("Cache key cannot be null or empty");

if (key.Length > 250)

throw new CacheValidationException($"Cache key too long: {key.Length} characters");

if (!_keyValidationRegex.IsMatch(key))

throw new CacheValidationException($"Invalid characters in cache key: {key}");

}

public bool IsSafeForSerialization(T value)

{

if (value == null) return true;

var valueType = value.GetType();

// 检查是否有序列化属性

if (valueType.IsSerializable ||

valueType.GetCustomAttributes(typeof(DataContractAttribute), false).Length > 0)

{

return true;

}

// 原始类型和字符串通常安全

return valueType.IsPrimitive || valueType == typeof(string) || valueType == typeof(DateTime);

}

private bool HasCircularReference(object obj, HashSet visited = null)

{

if (obj == null) return false;

visited ??= new HashSet();

if (visited.Contains(obj))

return true;

visited.Add(obj);

// 简化的循环检测,只检查一层

var type = obj.GetType();

if (type.IsPrimitive || type == typeof(string))

return false;

visited.Remove(obj);

return false;

}

}

///

/// 安全缓存管理器装饰器

///

public class SecureCacheManagerDecorator : IAdvancedMemoryCache

{

private readonly IAdvancedMemoryCache _innerCache;

private readonly ICacheDataValidator _validator;

private readonly ILogger _logger;

public SecureCacheManagerDecorator(

IAdvancedMemoryCache innerCache,

ICacheDataValidator validator,

ILogger logger)

{

_innerCache = innerCache ?? throw new ArgumentNullException(nameof(innerCache));

_validator = validator ?? throw new ArgumentNullException(nameof(validator));

_logger = logger ?? throw new ArgumentNullException(nameof(logger));

}

public async Task GetOrSetAsync(string key, Func> factory, TimeSpan? expiry = null)

{

_validator.ValidateKey(key);

return await _innerCache.GetOrSetAsync(key, async () =>

{

var value = await factory();

if (!_validator.IsValid(value))

{

throw new CacheValidationException($"Invalid cache value for key: {key}");

}

return value;

}, expiry);

}

public async Task GetAsync(string key)

{

_validator.ValidateKey(key);

return await _innerCache.GetAsync(key);

}

public async Task SetAsync(string key, T value, TimeSpan? expiry = null)

{

_validator.ValidateKey(key);

if (!_validator.IsValid(value))

{

throw new CacheValidationException($"Invalid cache value for key: {key}");

}

if (!_validator.IsSafeForSerialization(value))

{

_logger.LogWarning("Potentially unsafe serialization for key: {Key}, type: {Type}",

key, value?.GetType().Name);

}

await _innerCache.SetAsync(key, value, expiry);

}

public async Task RemoveAsync(string key)

{

_validator.ValidateKey(key);

await _innerCache.RemoveAsync(key);

}

public async Task RemoveByPatternAsync(string pattern)

{

if (string.IsNullOrWhiteSpace(pattern))

throw new CacheValidationException("Pattern cannot be null or empty");

await _innerCache.RemoveByPatternAsync(pattern);

}

public CacheStatistics GetStatistics() => _innerCache.GetStatistics();

public void ClearStatistics() => _innerCache.ClearStatistics();

}

///

/// 序列化器接口

///

public interface ICacheSerializer

{

byte[] Serialize(T value);

T Deserialize(byte[] data);

string SerializerName { get; }

bool SupportsType(Type type);

}

///

/// JSON序列化器(默认)

///

public class JsonCacheSerializer : ICacheSerializer

{

private readonly JsonSerializerOptions _options;

public string SerializerName => "JSON";

public JsonCacheSerializer()

{

_options = new JsonSerializerOptions

{

PropertyNamingPolicy = JsonNamingPolicy.CamelCase,

WriteIndented = false,

DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,

PropertyNameCaseInsensitive = true

};

}

public byte[] Serialize(T value)

{

if (value == null) return null;

if (typeof(T) == typeof(string)) return System.Text.Encoding.UTF8.GetBytes(value.ToString());

var json = JsonSerializer.Serialize(value, _options);

return System.Text.Encoding.UTF8.GetBytes(json);

}

public T Deserialize(byte[] data)

{

if (data == null || data.Length == 0) return default(T);

if (typeof(T) == typeof(string)) return (T)(object)System.Text.Encoding.UTF8.GetString(data);

var json = System.Text.Encoding.UTF8.GetString(data);

return JsonSerializer.Deserialize(json, _options);

}

public bool SupportsType(Type type)

{

return true; // JSON支持所有类型

}

}

///

/// 二进制序列化器(用于简单类型)

///

public class BinaryCacheSerializer : ICacheSerializer

{

public string SerializerName => "Binary";

private static readonly HashSet SupportedTypes = new()

{

typeof(int), typeof(long), typeof(double), typeof(float),

typeof(bool), typeof(byte), typeof(short),

typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan),

typeof(Guid), typeof(decimal)

};

public byte[] Serialize(T value)

{

if (value == null) return null;

var type = typeof(T);

// 专门处理常见类型,提高性能

return type switch

{

_ when type == typeof(int) => BitConverter.GetBytes((int)(object)value),

_ when type == typeof(long) => BitConverter.GetBytes((long)(object)value),

_ when type == typeof(double) => BitConverter.GetBytes((double)(object)value),

_ when type == typeof(float) => BitConverter.GetBytes((float)(object)value),

_ when type == typeof(bool) => BitConverter.GetBytes((bool)(object)value),

_ when type == typeof(DateTime) => BitConverter.GetBytes(((DateTime)(object)value).ToBinary()),

_ when type == typeof(Guid) => ((Guid)(object)value).ToByteArray(),

_ when type == typeof(string) => System.Text.Encoding.UTF8.GetBytes(value.ToString()),

_ => throw new NotSupportedException($"Type {type.Name} is not supported by BinaryCacheSerializer")

};

}

public T Deserialize(byte[] data)

{

if (data == null || data.Length == 0) return default(T);

var type = typeof(T);

object result = type switch

{

_ when type == typeof(int) => BitConverter.ToInt32(data, 0),

_ when type == typeof(long) => BitConverter.ToInt64(data, 0),

_ when type == typeof(double) => BitConverter.ToDouble(data, 0),

_ when type == typeof(float) => BitConverter.ToSingle(data, 0),

_ when type == typeof(bool) => BitConverter.ToBoolean(data, 0),

_ when type == typeof(DateTime) => DateTime.FromBinary(BitConverter.ToInt64(data, 0)),

_ when type == typeof(Guid) => new Guid(data),

_ when type == typeof(string) => System.Text.Encoding.UTF8.GetString(data),

_ => throw new NotSupportedException($"Type {type.Name} is not supported by BinaryCacheSerializer")

};

return (T)result;

}

public bool SupportsType(Type type)

{

return SupportedTypes.Contains(type) || type == typeof(string);

}

}

///

/// 智能序列化器管理器

///

public class SmartCacheSerializer : ICacheSerializer

{

private readonly ICacheSerializer[] _serializers;

private readonly ILogger _logger;

public string SerializerName => "Smart";

public SmartCacheSerializer(ILogger logger)

{

_logger = logger;

_serializers = new ICacheSerializer[]

{

new BinaryCacheSerializer(), // 优先使用二进制序列化

new JsonCacheSerializer() // 备选JSON序列化

};

}

public byte[] Serialize(T value)

{

if (value == null) return null;

var type = typeof(T);

foreach (var serializer in _serializers)

{

if (serializer.SupportsType(type))

{

try

{

var data = serializer.Serialize(value);

// 在数据开头添加序列化器标识

var header = System.Text.Encoding.UTF8.GetBytes(serializer.SerializerName.PadRight(8));

var result = new byte[header.Length + data.Length];

Array.Copy(header, 0, result, 0, header.Length);

Array.Copy(data, 0, result, header.Length, data.Length);

return result;

}

catch (Exception ex)

{

_logger.LogWarning(ex, "Serializer {SerializerName} failed for type {TypeName}",

serializer.SerializerName, type.Name);

continue;

}

}

}

throw new CacheSerializationException($"No suitable serializer found for type: {type.Name}");

}

public T Deserialize(byte[] data)

{

if (data == null || data.Length < 8) return default(T);

// 读取序列化器标识

var headerBytes = new byte[8];

Array.Copy(data, 0, headerBytes, 0, 8);

var serializerName = System.Text.Encoding.UTF8.GetString(headerBytes).Trim();

// 获取实际数据

var actualData = new byte[data.Length - 8];

Array.Copy(data, 8, actualData, 0, actualData.Length);

// 找到对应的序列化器

var serializer = _serializers.FirstOrDefault(s => s.SerializerName == serializerName);

if (serializer == null)

{

_logger.LogWarning("Unknown serializer: {SerializerName}, falling back to JSON", serializerName);

serializer = new JsonCacheSerializer();

}

try

{

return serializer.Deserialize(actualData);

}

catch (Exception ex)

{

_logger.LogError(ex, "Failed to deserialize with {SerializerName}", serializerName);

throw new CacheSerializationException($"Deserialization failed with {serializerName}", ex);

}

}

public bool SupportsType(Type type)

{

return _serializers.Any(s => s.SupportsType(type));

}

}

///

/// 断路器状态

///

public enum CircuitBreakerState

{

Closed, // 正常状态

Open, // 断路器打开,拒绝请求

HalfOpen // 半开状态,允许少量请求通过

}

///

/// 缓存断路器配置

///

public class CacheCircuitBreakerOptions

{

public int FailureThreshold { get; set; } = 5; // 连续失败阈值

public TimeSpan OpenTimeout { get; set; } = TimeSpan.FromMinutes(1); // 断路器打开时间

public int SuccessThreshold { get; set; } = 2; // 半开状态成功阈值

public TimeSpan SamplingDuration { get; set; } = TimeSpan.FromMinutes(2); // 采样时间窗口

}

///

/// 缓存断路器

///

public class CacheCircuitBreaker

{

private readonly CacheCircuitBreakerOptions _options;

private readonly ILogger _logger;

private readonly object _lock = new object();

private CircuitBreakerState _state = CircuitBreakerState.Closed;

private int _failureCount = 0;

private int _successCount = 0;

private DateTime _lastFailureTime = DateTime.MinValue;

private DateTime _lastStateChangeTime = DateTime.UtcNow;

public CacheCircuitBreaker(

CacheCircuitBreakerOptions options,

ILogger logger)

{

_options = options ?? throw new ArgumentNullException(nameof(options));

_logger = logger ?? throw new ArgumentNullException(nameof(logger));

}

public CircuitBreakerState State => _state;

///

/// 执行带断路器保护的操作

///

public async Task ExecuteAsync(Func> operation, string operationName = null)

{

if (!CanExecute())

{

throw new CacheException($"Circuit breaker is OPEN for operation: {operationName}");

}

try

{

var result = await operation();

OnSuccess();

return result;

}

catch (Exception ex)

{

OnFailure(ex, operationName);

throw;

}

}

///

/// 检查是否可以执行操作

///

private bool CanExecute()

{

lock (_lock)

{

switch (_state)

{

case CircuitBreakerState.Closed:

return true;

case CircuitBreakerState.Open:

// 检查是否可以转入半开状态

if (DateTime.UtcNow - _lastStateChangeTime >= _options.OpenTimeout)

{

_state = CircuitBreakerState.HalfOpen;

_successCount = 0;

_lastStateChangeTime = DateTime.UtcNow;

_logger.LogInformation("Circuit breaker entering HALF_OPEN state");

return true;

}

return false;

case CircuitBreakerState.HalfOpen:

return true;

default:

return false;

}

}

}

///

/// 操作成功回调

///

private void OnSuccess()

{

lock (_lock)

{

if (_state == CircuitBreakerState.HalfOpen)

{

_successCount++;

if (_successCount >= _options.SuccessThreshold)

{

_state = CircuitBreakerState.Closed;

_failureCount = 0;

_successCount = 0;

_lastStateChangeTime = DateTime.UtcNow;

_logger.LogInformation("Circuit breaker entering CLOSED state");

}

}

else if (_state == CircuitBreakerState.Closed)

{

// 在采样时间窗口内重置失败计数

if (DateTime.UtcNow - _lastFailureTime > _options.SamplingDuration)

{

_failureCount = 0;

}

}

}

}

///

/// 操作失败回调

///

private void OnFailure(Exception ex, string operationName)

{

lock (_lock)

{

_failureCount++;

_lastFailureTime = DateTime.UtcNow;

_logger.LogWarning(ex, "Circuit breaker recorded failure #{FailureCount} for operation: {Operation}",

_failureCount, operationName);

if (_state == CircuitBreakerState.Closed && _failureCount >= _options.FailureThreshold)

{

_state = CircuitBreakerState.Open;

_lastStateChangeTime = DateTime.UtcNow;

_logger.LogError("Circuit breaker entering OPEN state after {FailureCount} failures", _failureCount);

}

else if (_state == CircuitBreakerState.HalfOpen)

{

_state = CircuitBreakerState.Open;

_lastStateChangeTime = DateTime.UtcNow;

_logger.LogWarning("Circuit breaker returning to OPEN state from HALF_OPEN due to failure");

}

}

}

///

/// 获取当前状态信息

///

public object GetState()

{

lock (_lock)

{

return new

{

State = _state.ToString(),

FailureCount = _failureCount,

SuccessCount = _successCount,

LastFailureTime = _lastFailureTime,

LastStateChangeTime = _lastStateChangeTime,

CanExecute = CanExecute()

};

}

}

}

///

/// 带断路器的Redis缓存装饰器

///

public class CircuitBreakerRedisCache : IRedisDistributedCache

{

private readonly IRedisDistributedCache _innerCache;

private readonly CacheCircuitBreaker _circuitBreaker;

private readonly ILogger _logger;

public CircuitBreakerRedisCache(

IRedisDistributedCache innerCache,

CacheCircuitBreaker circuitBreaker,

ILogger logger)

{

_innerCache = innerCache ?? throw new ArgumentNullException(nameof(innerCache));

_circuitBreaker = circuitBreaker ?? throw new ArgumentNullException(nameof(circuitBreaker));

_logger = logger ?? throw new ArgumentNullException(nameof(logger));

}

public async Task GetAsync(string key)

{

try

{

return await _circuitBreaker.ExecuteAsync(() => _innerCache.GetAsync(key), $"GET:{key}");

}

catch (CacheException) when (_circuitBreaker.State == CircuitBreakerState.Open)

{

_logger.LogWarning("Circuit breaker open, returning default for key: {Key}", key);

return default(T);

}

}

public async Task SetAsync(string key, T value, TimeSpan? expiry = null)

{

try

{

await _circuitBreaker.ExecuteAsync(() => _innerCache.SetAsync(key, value, expiry), $"SET:{key}");

}

catch (CacheException) when (_circuitBreaker.State == CircuitBreakerState.Open)

{

_logger.LogWarning("Circuit breaker open, skipping cache set for key: {Key}", key);

// 不继续抛出异常,允许应用继续运行

}

}

// 继续实现其他接口方法...

public Task ExistsAsync(string key) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.ExistsAsync(key), $"EXISTS:{key}");

public Task RemoveAsync(string key) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.RemoveAsync(key), $"REMOVE:{key}");

public Task RemoveByPatternAsync(string pattern) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.RemoveByPatternAsync(pattern), $"REMOVE_PATTERN:{pattern}");

public Task GetOrSetAsync(string key, Func> factory, TimeSpan? expiry = null) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.GetOrSetAsync(key, factory, expiry), $"GET_OR_SET:{key}");

public Task> GetMultipleAsync(IEnumerable keys) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.GetMultipleAsync(keys), "GET_MULTIPLE");

public Task SetMultipleAsync(Dictionary keyValuePairs, TimeSpan? expiry = null) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.SetMultipleAsync(keyValuePairs, expiry), "SET_MULTIPLE");

public Task IncrementAsync(string key, long value = 1, TimeSpan? expiry = null) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.IncrementAsync(key, value, expiry), $"INCREMENT:{key}");

public Task IncrementAsync(string key, double value, TimeSpan? expiry = null) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.IncrementAsync(key, value, expiry), $"INCREMENT_DOUBLE:{key}");

public Task SetIfNotExistsAsync(string key, T value, TimeSpan? expiry = null) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.SetIfNotExistsAsync(key, value, expiry), $"SET_IF_NOT_EXISTS:{key}");

public Task GetExpiryAsync(string key) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.GetExpiryAsync(key), $"GET_EXPIRY:{key}");

public Task ExpireAsync(string key, TimeSpan expiry) =>

_circuitBreaker.ExecuteAsync(() => _innerCache.ExpireAsync(key, expiry), $"EXPIRE:{key}");

}

///

/// LRU缓存容器,用于防止内存泄漏

///

public class LRUCache

{

private readonly int _maxSize;

private readonly Dictionary>> _cache;

private readonly LinkedList> _lruList;

private readonly object _lock = new object();

public LRUCache(int maxSize)

{

if (maxSize <= 0)

throw new ArgumentException("Max size must be greater than 0", nameof(maxSize));

_maxSize = maxSize;

_cache = new Dictionary>>(maxSize);

_lruList = new LinkedList>();

}

public int Count

{

get

{

lock (_lock)

{

return _cache.Count;

}

}

}

public bool TryGet(TKey key, out TValue value)

{

lock (_lock)

{

if (_cache.TryGetValue(key, out var node))

{

// 移到链表头部(最近使用)

_lruList.Remove(node);

_lruList.AddFirst(node);

value = node.Value.Value;

return true;

}

value = default(TValue);

return false;

}

}

public void Add(TKey key, TValue value)

{

lock (_lock)

{

if (_cache.TryGetValue(key, out var existingNode))

{

// 更新已存在的项

existingNode.Value.Value = value;

existingNode.Value.LastAccessed = DateTime.UtcNow;

// 移到链表头部

_lruList.Remove(existingNode);

_lruList.AddFirst(existingNode);

}

else

{

// 检查容量限制

if (_cache.Count >= _maxSize)

{

// 移除最久未使用的项

var lastNode = _lruList.Last;

if (lastNode != null)

{

_cache.Remove(lastNode.Value.Key);

_lruList.RemoveLast();

}

}

// 添加新项

var newItem = new CacheItem

{

Key = key,

Value = value,

LastAccessed = DateTime.UtcNow

};

var newNode = _lruList.AddFirst(newItem);

_cache[key] = newNode;

}

}

}

public bool Remove(TKey key)

{

lock (_lock)

{

if (_cache.TryGetValue(key, out var node))

{

_cache.Remove(key);

_lruList.Remove(node);

return true;

}

return false;

}

}

public void Clear()

{

lock (_lock)

{

_cache.Clear();

_lruList.Clear();

}

}

public IEnumerable Keys

{

get

{

lock (_lock)

{

return _cache.Keys.ToList();

}

}

}

///

/// 清理过期项

///

public int CleanupExpired(TimeSpan maxAge)

{

var cutoffTime = DateTime.UtcNow - maxAge;

var expiredKeys = new List();

lock (_lock)

{

foreach (var item in _lruList)

{

if (item.LastAccessed < cutoffTime)

{

expiredKeys.Add(item.Key);

}

}

foreach (var key in expiredKeys)

{

Remove(key);

}

}

return expiredKeys.Count;

}

}

///

/// LRU缓存项

///

class CacheItem

{

public TKey Key { get; set; }

public TValue Value { get; set; }

public DateTime LastAccessed { get; set; }

}

///

/// 高级内存缓存管理器

/// 提供泛型支持、统计信息、性能监控等功能

///

public interface IAdvancedMemoryCache

{

Task GetOrSetAsync(string key, Func> factory, TimeSpan? expiry = null);

Task GetAsync(string key);

Task SetAsync(string key, T value, TimeSpan? expiry = null);

Task RemoveAsync(string key);

Task RemoveByPatternAsync(string pattern);

CacheStatistics GetStatistics();

void ClearStatistics();

}

///

/// 缓存统计信息

///

public class CacheStatistics

{

public long HitCount { get; set; }

public long MissCount { get; set; }

public long SetCount { get; set; }

public long RemoveCount { get; set; }

public double HitRatio => HitCount + MissCount == 0 ? 0 : (double)HitCount / (HitCount + MissCount);

public DateTime StartTime { get; set; }

public TimeSpan Duration => DateTime.UtcNow - StartTime;

}

///

/// 缓存配置选项

///

public class AdvancedMemoryCacheOptions

{

public int SizeLimit { get; set; } = 1000;

public TimeSpan DefaultExpiry { get; set; } = TimeSpan.FromMinutes(30);

public bool EnableStatistics { get; set; } = true;

public bool EnablePatternRemoval { get; set; } = true;

public double CompactionPercentage { get; set; } = 0.1;

}

///

/// 高级内存缓存实现

/// 基于IMemoryCache构建的功能增强版本

///

public class AdvancedMemoryCache : IAdvancedMemoryCache, IDisposable

{

private readonly IMemoryCache _cache;

private readonly ILogger _logger;

private readonly AdvancedMemoryCacheOptions _options;

private readonly CacheStatistics _statistics;

private readonly ConcurrentDictionary _keyTracker;

private readonly SemaphoreSlim _semaphore;

private readonly Timer _cleanupTimer;

public AdvancedMemoryCache(

IMemoryCache cache,

ILogger logger,

IOptions options)

{

_cache = cache ?? throw new ArgumentNullException(nameof(cache));

_logger = logger ?? throw new ArgumentNullException(nameof(logger));

_options = options?.Value ?? new AdvancedMemoryCacheOptions();

_statistics = new CacheStatistics { StartTime = DateTime.UtcNow };

_keyTracker = new ConcurrentDictionary();

_semaphore = new SemaphoreSlim(1, 1);

// 定期清理过期的key追踪记录

_cleanupTimer = new Timer(CleanupKeyTracker, null,

TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));

}

///

/// 获取或设置缓存项

/// 这是最常用的方法,实现了Cache-Aside模式

///

/// 缓存项类型

/// 缓存键

/// 数据工厂方法

/// 过期时间

/// 缓存的值

public async Task GetOrSetAsync(string key, Func> factory, TimeSpan? expiry = null)

{

if (string.IsNullOrEmpty(key))

throw new ArgumentException("Key cannot be null or empty", nameof(key));

if (factory == null)

throw new ArgumentNullException(nameof(factory));

// 尝试从缓存获取

var cachedValue = await GetAsync(key);

if (cachedValue != null)

{

_logger.LogDebug("Cache hit for key: {Key}", key);

return cachedValue;

}

// 使用信号量防止并发执行相同的factory方法

await _semaphore.WaitAsync();

try

{

// 双重检查锁定模式

cachedValue = await GetAsync(key);

if (cachedValue != null)

{

_logger.LogDebug("Cache hit on second check for key: {Key}", key);

return cachedValue;

}

// 执行工厂方法获取数据

_logger.LogDebug("Cache miss for key: {Key}, executing factory method", key);

var value = await factory();

// 将结果存入缓存

await SetAsync(key, value, expiry);

return value;

}

catch (CacheConnectionException ex)

{

_logger.LogWarning(ex, "Cache connection failed for key: {Key}, using fallback", key);

// 缓存连接失败时,仍执行工厂方法但不缓存结果

return await factory();

}

catch (CacheSerializationException ex)

{

_logger.LogError(ex, "Serialization failed for key: {Key}", key);

throw;

}

catch (CacheTimeoutException ex)

{

_logger.LogWarning(ex, "Cache operation timeout for key: {Key}", key);

return await factory();

}

catch (Exception ex)

{

_logger.LogError(ex, "Unexpected error occurred while executing factory method for key: {Key}", key);

throw new CacheException($"Cache operation failed for key: {key}", ex);

}

finally

{

_semaphore.Release();

}

}

///

/// 异步获取缓存项

///

/// 缓存项类型

/// 缓存键

/// 缓存的值,如果不存在则返回默认值

public Task GetAsync(string key)

{

if (string.IsNullOrEmpty(key))

throw new ArgumentException("Key cannot be null or empty", nameof(key));

var found = _cache.TryGetValue(key, out var value);

if (_options.EnableStatistics)

{

if (found)

Interlocked.Increment(ref _statistics.HitCount);

else

Interlocked.Increment(ref _statistics.MissCount);

}

if (found && value is T typedValue)

{

return Task.FromResult(typedValue);

}

return Task.FromResult(default(T));

}

///

/// 异步设置缓存项

///

/// 缓存项类型

/// 缓存键

/// 缓存值

/// 过期时间

public Task SetAsync(string key, T value, TimeSpan? expiry = null)

{

if (string.IsNullOrEmpty(key))

throw new ArgumentException("Key cannot be null or empty", nameof(key));

var cacheExpiry = expiry ?? _options.DefaultExpiry;

using var entry = _cache.CreateEntry(key);

entry.Value = value;

entry.AbsoluteExpirationRelativeToNow = cacheExpiry;

entry.Size = 1; // 简化的大小计算,实际应用中可根据对象大小设置

// 设置过期回调

entry.PostEvictionCallbacks.Add(new PostEvictionCallbackRegistration

{

EvictionCallback = OnCacheEntryEvicted,

State = key

});

// 追踪缓存键

if (_options.EnablePatternRemoval)

{

_keyTracker.TryAdd(key, 0);

}

if (_options.EnableStatistics)

{

Interlocked.Increment(ref _statistics.SetCount);

}

_logger.LogDebug("Set cache entry for key: {Key}, expiry: {Expiry}", key, cacheExpiry);

return Task.CompletedTask;

}

///

/// 异步移除缓存项

///

/// 缓存键

public Task RemoveAsync(string key)

{

if (string.IsNullOrEmpty(key))

throw new ArgumentException("Key cannot be null or empty", nameof(key));

_cache.Remove(key);

_keyTracker.TryRemove(key, out _);

if (_options.EnableStatistics)

{

Interlocked.Increment(ref _statistics.RemoveCount);

}

_logger.LogDebug("Removed cache entry for key: {Key}", key);

return Task.CompletedTask;

}

///

/// 根据模式异步移除缓存项

/// 支持通配符匹配,如 "user:*", "*:settings"

///

/// 匹配模式

public async Task RemoveByPatternAsync(string pattern)

{

if (string.IsNullOrEmpty(pattern))

throw new ArgumentException("Pattern cannot be null or empty", nameof(pattern));

if (!_options.EnablePatternRemoval)

{

_logger.LogWarning("Pattern removal is disabled");

return;

}

var keysToRemove = new List();

var regexPattern = ConvertWildcardToRegex(pattern);

var regex = new System.Text.RegularExpressions.Regex(regexPattern,

System.Text.RegularExpressions.RegexOptions.IgnoreCase);

foreach (var key in _keyTracker.Keys)

{

if (regex.IsMatch(key))

{

keysToRemove.Add(key);

}

}

foreach (var key in keysToRemove)

Logo

更多推荐