找回密码
 立即注册
首页 业界区 业界 C#中的多级缓存架构设计与实现深度解析 ...

C#中的多级缓存架构设计与实现深度解析

翁谌缜 2025-8-12 18:11:49
C#中的多级缓存架构设计与实现深度解析

引言

在现代分布式应用架构中,缓存已成为提升系统性能和用户体验的关键技术组件。随着业务规模的不断扩大和并发量的持续增长,单一级别的缓存往往无法满足复杂的性能需求。多级缓存架构通过在不同层次构建缓存体系,能够显著提升数据访问效率,降低数据库负载,并提供更好的系统可扩展性。
本文将深入探讨C#环境下多级缓存的架构设计与实现,重点分析内存缓存(Memory Cache)与Redis分布式缓存的协同工作机制,并详细阐述如何通过Redis的发布-订阅(Pub/Sub)模式实现不同节点间的缓存状态同步。
1. 多级缓存理论基础

1.1 缓存层次结构理论

缓存的本质是利用时间局部性(Temporal Locality)和空间局部性(Spatial Locality)原理,将频繁访问的数据存储在更快的存储介质中。在计算机系统中,从CPU缓存到内存,从内存到磁盘,都遵循着这种层次化的存储架构。
1.1.1 缓存访问模式
  1. CPU Cache (L1/L2/L3) → Memory → Disk Storage
  2.    ↑                    ↑         ↑
  3. 快速访问              中等速度    慢速访问
  4. 小容量                中等容量    大容量
  5. 昂贵                  适中        便宜
复制代码
在应用层面,多级缓存同样遵循类似的原理:

  • 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 多级缓存整体架构

graph TB    Client[客户端应用]        subgraph "多级缓存系统"        subgraph "应用层"            Controller[Controller层]            Service[Service层]            Manager[多级缓存管理器]        end                subgraph "缓存层"            subgraph "L1缓存 - 内存缓存"                MemCache[IMemoryCache]                AdvMemCache[高级内存缓存]            end                        subgraph "L2缓存 - Redis分布式缓存"                RedisConn[Redis连接管理器]                RedisCache[Redis分布式缓存]                RedisCluster[Redis集群]            end        end                subgraph "同步机制"            PubSub[Redis Pub/Sub]            SyncService[缓存同步服务]            EventQueue[事件队列]        end                subgraph "监控系统"            Monitor[监控服务]            HealthCheck[健康检查]            Metrics[性能指标]        end    end        subgraph "数据层"        Database[(数据库)]        External[外部API]    end        Client --> Controller    Controller --> Service    Service --> Manager        Manager --> AdvMemCache    Manager --> RedisCache        AdvMemCache --> MemCache    RedisCache --> RedisConn    RedisConn --> RedisCluster        RedisCache --> PubSub    PubSub --> SyncService    SyncService --> EventQueue    EventQueue --> AdvMemCache        Manager --> Monitor    Monitor --> HealthCheck    Monitor --> Metrics        Manager -.-> Database    Manager -.-> External        style Manager fill:#e1f5fe    style AdvMemCache fill:#f3e5f5    style RedisCache fill:#e8f5e8    style PubSub fill:#fff3e02.0.2 缓存操作流程图

sequenceDiagram    participant Client as 客户端    participant Manager as 多级缓存管理器    participant L1 as L1内存缓存    participant L2 as L2 Redis缓存    participant Sync as 同步服务    participant DB as 数据库    Note over Client,DB: 读取操作流程 (GetOrSet)    Client->>Manager: GetOrSet(key, factory)    Manager->>L1: Get(key)    alt L1 缓存命中        L1->>Manager: 返回数据        Manager->>Client: 返回结果 (L1 Hit)    else L1 缓存未命中        L1->>Manager: 返回 null        Manager->>L2: Get(key)        alt L2 缓存命中            L2->>Manager: 返回数据            Manager->>L1: Set(key, data) [异步提升]            Manager->>Client: 返回结果 (L2 Hit)        else L2 缓存未命中            L2->>Manager: 返回 null            Manager->>DB: factory() 执行            DB->>Manager: 返回原始数据            par 并行设置缓存                Manager->>L1: Set(key, data)                Manager->>L2: Set(key, data)            and 发布同步事件                Manager->>Sync: PublishSync(SET, key)            end            Manager->>Client: 返回结果 (DB Hit)        end    end    Note over Client,DB: 更新操作流程    Client->>Manager: Set(key, data)    par 并行更新所有级别        Manager->>L1: Set(key, data)        Manager->>L2: Set(key, data)    end    Manager->>Sync: PublishSync(SET, key)    Sync->>L1: 通知其他节点更新L1缓存    Manager->>Client: 返回结果    Note over Client,DB: 删除操作流程    Client->>Manager: Remove(key)    par 并行删除所有级别        Manager->>L1: Remove(key)        Manager->>L2: Remove(key)    end    Manager->>Sync: PublishSync(REMOVE, key)    Sync->>L1: 通知其他节点删除L1缓存    Manager->>Client: 返回结果2.0.3 Redis发布-订阅同步机制

graph TB    subgraph "节点A"        AppA[应用A]        L1A[L1缓存A]        L2A[L2缓存A]        SyncA[同步服务A]    end        subgraph "节点B"        AppB[应用B]        L1B[L1缓存B]        L2B[L2缓存B]        SyncB[同步服务B]    end        subgraph "节点C"        AppC[应用C]        L1C[L1缓存C]        L2C[L2缓存C]        SyncC[同步服务C]    end        subgraph "Redis集群"        RedisPubSub[Redis Pub/Sub频道
cache_sync:events]    end        %% 数据更新流程    AppA -->|1. 更新数据| L1A    AppA -->|2. 更新数据| L2A    SyncA -->|3. 发布同步事件| RedisPubSub        %% 同步通知    RedisPubSub -->|4. 广播事件| SyncB    RedisPubSub -->|4. 广播事件| SyncC        %% 本地缓存更新    SyncB -->|5. 更新本地缓存| L1B    SyncC -->|5. 更新本地缓存| L1C        style RedisPubSub fill:#ff9999    style SyncA fill:#99ccff    style SyncB fill:#99ccff    style SyncC fill:#99ccff2.0.4 缓存降级策略流程

flowchart TD    Start([开始缓存操作]) --> CheckL1{L1缓存
是否可用?}        CheckL1 -->|是| TryL1[尝试L1缓存操作]    TryL1 --> L1Success{L1操作
成功?}    L1Success -->|是| ReturnL1[返回L1结果]    L1Success -->|否| CheckL2        CheckL1 -->|否| CheckL2{L2缓存
是否可用?}    CheckL2 -->|是| TryL2[尝试L2缓存操作]    TryL2 --> L2Success{L2操作
成功?}    L2Success -->|是| ReturnL2[返回L2结果]    L2Success -->|否| CheckStrategy        CheckL2 -->|否| CheckStrategy{降级策略}    CheckStrategy -->|L1Only| L1OnlyMode[仅使用L1缓存]    CheckStrategy -->|DirectAccess| DirectDB[直接访问数据库]    CheckStrategy -->|ThrowException| ThrowError[抛出异常]        L1OnlyMode --> TryL1Only[尝试L1操作]    TryL1Only --> L1OnlySuccess{成功?}    L1OnlySuccess -->|是| ReturnL1Only[返回L1结果]    L1OnlySuccess -->|否| DirectDB        DirectDB --> DBAccess[执行数据库查询]    DBAccess --> ReturnDB[返回数据库结果]    ThrowError --> ErrorReturn[返回错误]        ReturnL1 --> End([结束])    ReturnL2 --> End    ReturnL1Only --> End    ReturnDB --> End    ErrorReturn --> End        style CheckL1 fill:#e3f2fd    style CheckL2 fill:#e3f2fd    style CheckStrategy fill:#fff3e0    style DirectDB fill:#ffebee    style ThrowError fill:#ffcdd22. 架构设计与技术选型

2.1 整体架构设计

多级缓存架构采用分层设计模式,每一层都有明确的职责和边界:
  1. ┌─────────────────────────────────────────────────────┐
  2. │                    应用层                           │
  3. ├─────────────────────────────────────────────────────┤
  4. │              多级缓存管理器                          │
  5. ├─────────────────┬───────────────────────────────────┤
  6. │   L1内存缓存    │         L2 Redis缓存              │
  7. │   (MemoryCache) │      (StackExchange.Redis)        │
  8. ├─────────────────┴───────────────────────────────────┤
  9. │              Redis Pub/Sub 同步机制                  │
  10. ├─────────────────────────────────────────────────────┤
  11. │                   数据持久层                         │
  12. └─────────────────────────────────────────────────────┘
复制代码
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. 1. 应用程序尝试从缓存读取数据
  3. 2. 如果缓存命中,直接返回数据
  4. 3. 如果缓存未命中,从数据库读取数据
  5. 4. 将数据写入缓存,然后返回给应用程序
  6. 更新流程:
  7. 1. 更新数据库
  8. 2. 删除或更新缓存中的对应数据
复制代码
2.3.2 Write-Through Pattern(写透模式)
  1. 写入流程:
  2. 1. 应用程序写入缓存
  3. 2. 缓存服务同步写入数据库
  4. 3. 确认写入完成后返回成功
复制代码
2.3.3 Write-Behind Pattern(写回模式)
  1. 写入流程:
  2. 1. 应用程序写入缓存
  3. 2. 立即返回成功
  4. 3. 缓存服务异步批量写入数据库
复制代码
3. 内存缓存层实现详解

3.1 IMemoryCache 核心接口分析

Microsoft.Extensions.Caching.Memory.IMemoryCache接口提供了缓存操作的核心方法:
  1. public interface IMemoryCache : IDisposable
  2. {
  3.     bool TryGetValue(object key, out object value);
  4.     ICacheEntry CreateEntry(object key);
  5.     void Remove(object key);
  6. }
复制代码
3.2 高级内存缓存封装实现
  1. using Microsoft.Extensions.Caching.Memory;
  2. using Microsoft.Extensions.Logging;
  3. using Microsoft.Extensions.Options;
  4. using System;
  5. using System.Collections.Concurrent;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using System.Text.RegularExpressions;
  9. using System.Runtime.Serialization;
  10. /// <summary>
  11. /// 缓存异常基类
  12. /// </summary>
  13. public abstract class CacheException : Exception
  14. {
  15.     protected CacheException(string message) : base(message) { }
  16.     protected CacheException(string message, Exception innerException) : base(message, innerException) { }
  17. }
  18. /// <summary>
  19. /// 缓存连接异常
  20. /// </summary>
  21. public class CacheConnectionException : CacheException
  22. {
  23.     public CacheConnectionException(string message) : base(message) { }
  24.     public CacheConnectionException(string message, Exception innerException) : base(message, innerException) { }
  25. }
  26. /// <summary>
  27. /// 缓存序列化异常
  28. /// </summary>
  29. public class CacheSerializationException : CacheException
  30. {
  31.     public CacheSerializationException(string message) : base(message) { }
  32.     public CacheSerializationException(string message, Exception innerException) : base(message, innerException) { }
  33. }
  34. /// <summary>
  35. /// 缓存超时异常
  36. /// </summary>
  37. public class CacheTimeoutException : CacheException
  38. {
  39.     public CacheTimeoutException(string message) : base(message) { }
  40.     public CacheTimeoutException(string message, Exception innerException) : base(message, innerException) { }
  41. }
  42. /// <summary>
  43. /// 缓存验证异常
  44. /// </summary>
  45. public class CacheValidationException : CacheException
  46. {
  47.     public CacheValidationException(string message) : base(message) { }
  48.     public CacheValidationException(string message, Exception innerException) : base(message, innerException) { }
  49. }
  50. /// <summary>
  51. /// 线程安全的缓存统计追踪器
  52. /// </summary>
  53. public class CacheStatisticsTracker
  54. {
  55.     private long _totalOperations = 0;
  56.     private long _l1Hits = 0;
  57.     private long _l2Hits = 0;
  58.     private long _totalMisses = 0;
  59.     private readonly object _lock = new object();
  60.     public void RecordOperation()
  61.     {
  62.         Interlocked.Increment(ref _totalOperations);
  63.     }
  64.     public void RecordHit(CacheLevel level)
  65.     {
  66.         switch (level)
  67.         {
  68.             case CacheLevel.L1:
  69.                 Interlocked.Increment(ref _l1Hits);
  70.                 break;
  71.             case CacheLevel.L2:
  72.                 Interlocked.Increment(ref _l2Hits);
  73.                 break;
  74.         }
  75.     }
  76.     public void RecordMiss()
  77.     {
  78.         Interlocked.Increment(ref _totalMisses);
  79.     }
  80.     public CacheStatisticsSnapshot GetSnapshot()
  81.     {
  82.         return new CacheStatisticsSnapshot
  83.         {
  84.             TotalOperations = Interlocked.Read(ref _totalOperations),
  85.             L1Hits = Interlocked.Read(ref _l1Hits),
  86.             L2Hits = Interlocked.Read(ref _l2Hits),
  87.             TotalMisses = Interlocked.Read(ref _totalMisses)
  88.         };
  89.     }
  90.     public void Reset()
  91.     {
  92.         lock (_lock)
  93.         {
  94.             Interlocked.Exchange(ref _totalOperations, 0);
  95.             Interlocked.Exchange(ref _l1Hits, 0);
  96.             Interlocked.Exchange(ref _l2Hits, 0);
  97.             Interlocked.Exchange(ref _totalMisses, 0);
  98.         }
  99.     }
  100. }
  101. /// <summary>
  102. /// 缓存统计快照
  103. /// </summary>
  104. public class CacheStatisticsSnapshot
  105. {
  106.     public long TotalOperations { get; init; }
  107.     public long L1Hits { get; init; }
  108.     public long L2Hits { get; init; }
  109.     public long TotalMisses { get; init; }
  110.     public long TotalHits => L1Hits + L2Hits;
  111.     public double OverallHitRatio => TotalOperations == 0 ? 0 : (double)TotalHits / TotalOperations;
  112.     public double L1HitRatio => TotalOperations == 0 ? 0 : (double)L1Hits / TotalOperations;
  113.     public double L2HitRatio => TotalOperations == 0 ? 0 : (double)L2Hits / TotalOperations;
  114. }
  115. /// <summary>
  116. /// 缓存数据验证器接口
  117. /// </summary>
  118. public interface ICacheDataValidator
  119. {
  120.     bool IsValid<T>(T value);
  121.     void ValidateKey(string key);
  122.     bool IsSafeForSerialization<T>(T value);
  123. }
  124. /// <summary>
  125. /// 默认缓存数据验证器
  126. /// </summary>
  127. public class DefaultCacheDataValidator : ICacheDataValidator
  128. {
  129.     private readonly ILogger<DefaultCacheDataValidator> _logger;
  130.     private readonly HashSet<Type> _forbiddenTypes;
  131.     private readonly Regex _keyValidationRegex;
  132.    
  133.     public DefaultCacheDataValidator(ILogger<DefaultCacheDataValidator> logger)
  134.     {
  135.         _logger = logger;
  136.         _forbiddenTypes = new HashSet<Type>
  137.         {
  138.             typeof(System.IO.FileStream),
  139.             typeof(System.Net.Sockets.Socket),
  140.             typeof(System.Threading.Thread),
  141.             typeof(System.Threading.Tasks.Task)
  142.         };
  143.         
  144.         // 限制key格式:只允许字母数字下划线冒号和点
  145.         _keyValidationRegex = new Regex(@"^[a-zA-Z0-9_:.-]+$", RegexOptions.Compiled);
  146.     }
  147.    
  148.     public bool IsValid<T>(T value)
  149.     {
  150.         if (value == null) return true;
  151.         
  152.         var valueType = value.GetType();
  153.         
  154.         // 检查禁止类型
  155.         if (_forbiddenTypes.Contains(valueType))
  156.         {
  157.             _logger.LogWarning("Forbidden type in cache: {Type}", valueType.Name);
  158.             return false;
  159.         }
  160.         
  161.         // 检查循环引用(简化版)
  162.         if (HasCircularReference(value))
  163.         {
  164.             _logger.LogWarning("Circular reference detected in cache value");
  165.             return false;
  166.         }
  167.         
  168.         return true;
  169.     }
  170.    
  171.     public void ValidateKey(string key)
  172.     {
  173.         if (string.IsNullOrWhiteSpace(key))
  174.             throw new CacheValidationException("Cache key cannot be null or empty");
  175.         
  176.         if (key.Length > 250)
  177.             throw new CacheValidationException($"Cache key too long: {key.Length} characters");
  178.         
  179.         if (!_keyValidationRegex.IsMatch(key))
  180.             throw new CacheValidationException($"Invalid characters in cache key: {key}");
  181.     }
  182.    
  183.     public bool IsSafeForSerialization<T>(T value)
  184.     {
  185.         if (value == null) return true;
  186.         
  187.         var valueType = value.GetType();
  188.         
  189.         // 检查是否有序列化属性
  190.         if (valueType.IsSerializable ||
  191.             valueType.GetCustomAttributes(typeof(DataContractAttribute), false).Length > 0)
  192.         {
  193.             return true;
  194.         }
  195.         
  196.         // 原始类型和字符串通常安全
  197.         return valueType.IsPrimitive || valueType == typeof(string) || valueType == typeof(DateTime);
  198.     }
  199.    
  200.     private bool HasCircularReference(object obj, HashSet<object> visited = null)
  201.     {
  202.         if (obj == null) return false;
  203.         
  204.         visited ??= new HashSet<object>();
  205.         
  206.         if (visited.Contains(obj))
  207.             return true;
  208.         
  209.         visited.Add(obj);
  210.         
  211.         // 简化的循环检测,只检查一层
  212.         var type = obj.GetType();
  213.         if (type.IsPrimitive || type == typeof(string))
  214.             return false;
  215.         
  216.         visited.Remove(obj);
  217.         return false;
  218.     }
  219. }
  220. /// <summary>
  221. /// 安全缓存管理器装饰器
  222. /// </summary>
  223. public class SecureCacheManagerDecorator : IAdvancedMemoryCache
  224. {
  225.     private readonly IAdvancedMemoryCache _innerCache;
  226.     private readonly ICacheDataValidator _validator;
  227.     private readonly ILogger<SecureCacheManagerDecorator> _logger;
  228.    
  229.     public SecureCacheManagerDecorator(
  230.         IAdvancedMemoryCache innerCache,
  231.         ICacheDataValidator validator,
  232.         ILogger<SecureCacheManagerDecorator> logger)
  233.     {
  234.         _innerCache = innerCache ?? throw new ArgumentNullException(nameof(innerCache));
  235.         _validator = validator ?? throw new ArgumentNullException(nameof(validator));
  236.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  237.     }
  238.    
  239.     public async Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
  240.     {
  241.         _validator.ValidateKey(key);
  242.         return await _innerCache.GetOrSetAsync(key, async () =>
  243.         {
  244.             var value = await factory();
  245.             if (!_validator.IsValid(value))
  246.             {
  247.                 throw new CacheValidationException($"Invalid cache value for key: {key}");
  248.             }
  249.             return value;
  250.         }, expiry);
  251.     }
  252.    
  253.     public async Task<T> GetAsync<T>(string key)
  254.     {
  255.         _validator.ValidateKey(key);
  256.         return await _innerCache.GetAsync<T>(key);
  257.     }
  258.    
  259.     public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
  260.     {
  261.         _validator.ValidateKey(key);
  262.         
  263.         if (!_validator.IsValid(value))
  264.         {
  265.             throw new CacheValidationException($"Invalid cache value for key: {key}");
  266.         }
  267.         
  268.         if (!_validator.IsSafeForSerialization(value))
  269.         {
  270.             _logger.LogWarning("Potentially unsafe serialization for key: {Key}, type: {Type}",
  271.                 key, value?.GetType().Name);
  272.         }
  273.         
  274.         await _innerCache.SetAsync(key, value, expiry);
  275.     }
  276.    
  277.     public async Task RemoveAsync(string key)
  278.     {
  279.         _validator.ValidateKey(key);
  280.         await _innerCache.RemoveAsync(key);
  281.     }
  282.    
  283.     public async Task RemoveByPatternAsync(string pattern)
  284.     {
  285.         if (string.IsNullOrWhiteSpace(pattern))
  286.             throw new CacheValidationException("Pattern cannot be null or empty");
  287.         
  288.         await _innerCache.RemoveByPatternAsync(pattern);
  289.     }
  290.    
  291.     public CacheStatistics GetStatistics() => _innerCache.GetStatistics();
  292.    
  293.     public void ClearStatistics() => _innerCache.ClearStatistics();
  294. }
  295. /// <summary>
  296. /// 序列化器接口
  297. /// </summary>
  298. public interface ICacheSerializer
  299. {
  300.     byte[] Serialize<T>(T value);
  301.     T Deserialize<T>(byte[] data);
  302.     string SerializerName { get; }
  303.     bool SupportsType(Type type);
  304. }
  305. /// <summary>
  306. /// JSON序列化器(默认)
  307. /// </summary>
  308. public class JsonCacheSerializer : ICacheSerializer
  309. {
  310.     private readonly JsonSerializerOptions _options;
  311.    
  312.     public string SerializerName => "JSON";
  313.    
  314.     public JsonCacheSerializer()
  315.     {
  316.         _options = new JsonSerializerOptions
  317.         {
  318.             PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
  319.             WriteIndented = false,
  320.             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
  321.             PropertyNameCaseInsensitive = true
  322.         };
  323.     }
  324.    
  325.     public byte[] Serialize<T>(T value)
  326.     {
  327.         if (value == null) return null;
  328.         if (typeof(T) == typeof(string)) return System.Text.Encoding.UTF8.GetBytes(value.ToString());
  329.         
  330.         var json = JsonSerializer.Serialize(value, _options);
  331.         return System.Text.Encoding.UTF8.GetBytes(json);
  332.     }
  333.    
  334.     public T Deserialize<T>(byte[] data)
  335.     {
  336.         if (data == null || data.Length == 0) return default(T);
  337.         if (typeof(T) == typeof(string)) return (T)(object)System.Text.Encoding.UTF8.GetString(data);
  338.         
  339.         var json = System.Text.Encoding.UTF8.GetString(data);
  340.         return JsonSerializer.Deserialize<T>(json, _options);
  341.     }
  342.    
  343.     public bool SupportsType(Type type)
  344.     {
  345.         return true; // JSON支持所有类型
  346.     }
  347. }
  348. /// <summary>
  349. /// 二进制序列化器(用于简单类型)
  350. /// </summary>
  351. public class BinaryCacheSerializer : ICacheSerializer
  352. {
  353.     public string SerializerName => "Binary";
  354.    
  355.     private static readonly HashSet<Type> SupportedTypes = new()
  356.     {
  357.         typeof(int), typeof(long), typeof(double), typeof(float),
  358.         typeof(bool), typeof(byte), typeof(short),
  359.         typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan),
  360.         typeof(Guid), typeof(decimal)
  361.     };
  362.    
  363.     public byte[] Serialize<T>(T value)
  364.     {
  365.         if (value == null) return null;
  366.         
  367.         var type = typeof(T);
  368.         
  369.         // 专门处理常见类型,提高性能
  370.         return type switch
  371.         {
  372.             _ when type == typeof(int) => BitConverter.GetBytes((int)(object)value),
  373.             _ when type == typeof(long) => BitConverter.GetBytes((long)(object)value),
  374.             _ when type == typeof(double) => BitConverter.GetBytes((double)(object)value),
  375.             _ when type == typeof(float) => BitConverter.GetBytes((float)(object)value),
  376.             _ when type == typeof(bool) => BitConverter.GetBytes((bool)(object)value),
  377.             _ when type == typeof(DateTime) => BitConverter.GetBytes(((DateTime)(object)value).ToBinary()),
  378.             _ when type == typeof(Guid) => ((Guid)(object)value).ToByteArray(),
  379.             _ when type == typeof(string) => System.Text.Encoding.UTF8.GetBytes(value.ToString()),
  380.             _ => throw new NotSupportedException($"Type {type.Name} is not supported by BinaryCacheSerializer")
  381.         };
  382.     }
  383.    
  384.     public T Deserialize<T>(byte[] data)
  385.     {
  386.         if (data == null || data.Length == 0) return default(T);
  387.         
  388.         var type = typeof(T);
  389.         
  390.         object result = type switch
  391.         {
  392.             _ when type == typeof(int) => BitConverter.ToInt32(data, 0),
  393.             _ when type == typeof(long) => BitConverter.ToInt64(data, 0),
  394.             _ when type == typeof(double) => BitConverter.ToDouble(data, 0),
  395.             _ when type == typeof(float) => BitConverter.ToSingle(data, 0),
  396.             _ when type == typeof(bool) => BitConverter.ToBoolean(data, 0),
  397.             _ when type == typeof(DateTime) => DateTime.FromBinary(BitConverter.ToInt64(data, 0)),
  398.             _ when type == typeof(Guid) => new Guid(data),
  399.             _ when type == typeof(string) => System.Text.Encoding.UTF8.GetString(data),
  400.             _ => throw new NotSupportedException($"Type {type.Name} is not supported by BinaryCacheSerializer")
  401.         };
  402.         
  403.         return (T)result;
  404.     }
  405.    
  406.     public bool SupportsType(Type type)
  407.     {
  408.         return SupportedTypes.Contains(type) || type == typeof(string);
  409.     }
  410. }
  411. /// <summary>
  412. /// 智能序列化器管理器
  413. /// </summary>
  414. public class SmartCacheSerializer : ICacheSerializer
  415. {
  416.     private readonly ICacheSerializer[] _serializers;
  417.     private readonly ILogger<SmartCacheSerializer> _logger;
  418.    
  419.     public string SerializerName => "Smart";
  420.    
  421.     public SmartCacheSerializer(ILogger<SmartCacheSerializer> logger)
  422.     {
  423.         _logger = logger;
  424.         _serializers = new ICacheSerializer[]
  425.         {
  426.             new BinaryCacheSerializer(), // 优先使用二进制序列化
  427.             new JsonCacheSerializer()    // 备选JSON序列化
  428.         };
  429.     }
  430.    
  431.     public byte[] Serialize<T>(T value)
  432.     {
  433.         if (value == null) return null;
  434.         
  435.         var type = typeof(T);
  436.         
  437.         foreach (var serializer in _serializers)
  438.         {
  439.             if (serializer.SupportsType(type))
  440.             {
  441.                 try
  442.                 {
  443.                     var data = serializer.Serialize(value);
  444.                     // 在数据开头添加序列化器标识
  445.                     var header = System.Text.Encoding.UTF8.GetBytes(serializer.SerializerName.PadRight(8));
  446.                     var result = new byte[header.Length + data.Length];
  447.                     Array.Copy(header, 0, result, 0, header.Length);
  448.                     Array.Copy(data, 0, result, header.Length, data.Length);
  449.                     
  450.                     return result;
  451.                 }
  452.                 catch (Exception ex)
  453.                 {
  454.                     _logger.LogWarning(ex, "Serializer {SerializerName} failed for type {TypeName}",
  455.                         serializer.SerializerName, type.Name);
  456.                     continue;
  457.                 }
  458.             }
  459.         }
  460.         
  461.         throw new CacheSerializationException($"No suitable serializer found for type: {type.Name}");
  462.     }
  463.    
  464.     public T Deserialize<T>(byte[] data)
  465.     {
  466.         if (data == null || data.Length < 8) return default(T);
  467.         
  468.         // 读取序列化器标识
  469.         var headerBytes = new byte[8];
  470.         Array.Copy(data, 0, headerBytes, 0, 8);
  471.         var serializerName = System.Text.Encoding.UTF8.GetString(headerBytes).Trim();
  472.         
  473.         // 获取实际数据
  474.         var actualData = new byte[data.Length - 8];
  475.         Array.Copy(data, 8, actualData, 0, actualData.Length);
  476.         
  477.         // 找到对应的序列化器
  478.         var serializer = _serializers.FirstOrDefault(s => s.SerializerName == serializerName);
  479.         if (serializer == null)
  480.         {
  481.             _logger.LogWarning("Unknown serializer: {SerializerName}, falling back to JSON", serializerName);
  482.             serializer = new JsonCacheSerializer();
  483.         }
  484.         
  485.         try
  486.         {
  487.             return serializer.Deserialize<T>(actualData);
  488.         }
  489.         catch (Exception ex)
  490.         {
  491.             _logger.LogError(ex, "Failed to deserialize with {SerializerName}", serializerName);
  492.             throw new CacheSerializationException($"Deserialization failed with {serializerName}", ex);
  493.         }
  494.     }
  495.    
  496.     public bool SupportsType(Type type)
  497.     {
  498.         return _serializers.Any(s => s.SupportsType(type));
  499.     }
  500. }
  501. /// <summary>
  502. /// 断路器状态
  503. /// </summary>
  504. public enum CircuitBreakerState
  505. {
  506.     Closed,     // 正常状态
  507.     Open,       // 断路器打开,拒绝请求
  508.     HalfOpen    // 半开状态,允许少量请求通过
  509. }
  510. /// <summary>
  511. /// 缓存断路器配置
  512. /// </summary>
  513. public class CacheCircuitBreakerOptions
  514. {
  515.     public int FailureThreshold { get; set; } = 5;                    // 连续失败阈值
  516.     public TimeSpan OpenTimeout { get; set; } = TimeSpan.FromMinutes(1); // 断路器打开时间
  517.     public int SuccessThreshold { get; set; } = 2;                    // 半开状态成功阈值
  518.     public TimeSpan SamplingDuration { get; set; } = TimeSpan.FromMinutes(2); // 采样时间窗口
  519. }
  520. /// <summary>
  521. /// 缓存断路器
  522. /// </summary>
  523. public class CacheCircuitBreaker
  524. {
  525.     private readonly CacheCircuitBreakerOptions _options;
  526.     private readonly ILogger<CacheCircuitBreaker> _logger;
  527.     private readonly object _lock = new object();
  528.    
  529.     private CircuitBreakerState _state = CircuitBreakerState.Closed;
  530.     private int _failureCount = 0;
  531.     private int _successCount = 0;
  532.     private DateTime _lastFailureTime = DateTime.MinValue;
  533.     private DateTime _lastStateChangeTime = DateTime.UtcNow;
  534.    
  535.     public CacheCircuitBreaker(
  536.         CacheCircuitBreakerOptions options,
  537.         ILogger<CacheCircuitBreaker> logger)
  538.     {
  539.         _options = options ?? throw new ArgumentNullException(nameof(options));
  540.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  541.     }
  542.    
  543.     public CircuitBreakerState State => _state;
  544.    
  545.     /// <summary>
  546.     /// 执行带断路器保护的操作
  547.     /// </summary>
  548.     public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation, string operationName = null)
  549.     {
  550.         if (!CanExecute())
  551.         {
  552.             throw new CacheException($"Circuit breaker is OPEN for operation: {operationName}");
  553.         }
  554.         
  555.         try
  556.         {
  557.             var result = await operation();
  558.             OnSuccess();
  559.             return result;
  560.         }
  561.         catch (Exception ex)
  562.         {
  563.             OnFailure(ex, operationName);
  564.             throw;
  565.         }
  566.     }
  567.    
  568.     /// <summary>
  569.     /// 检查是否可以执行操作
  570.     /// </summary>
  571.     private bool CanExecute()
  572.     {
  573.         lock (_lock)
  574.         {
  575.             switch (_state)
  576.             {
  577.                 case CircuitBreakerState.Closed:
  578.                     return true;
  579.                     
  580.                 case CircuitBreakerState.Open:
  581.                     // 检查是否可以转入半开状态
  582.                     if (DateTime.UtcNow - _lastStateChangeTime >= _options.OpenTimeout)
  583.                     {
  584.                         _state = CircuitBreakerState.HalfOpen;
  585.                         _successCount = 0;
  586.                         _lastStateChangeTime = DateTime.UtcNow;
  587.                         _logger.LogInformation("Circuit breaker entering HALF_OPEN state");
  588.                         return true;
  589.                     }
  590.                     return false;
  591.                     
  592.                 case CircuitBreakerState.HalfOpen:
  593.                     return true;
  594.                     
  595.                 default:
  596.                     return false;
  597.             }
  598.         }
  599.     }
  600.    
  601.     /// <summary>
  602.     /// 操作成功回调
  603.     /// </summary>
  604.     private void OnSuccess()
  605.     {
  606.         lock (_lock)
  607.         {
  608.             if (_state == CircuitBreakerState.HalfOpen)
  609.             {
  610.                 _successCount++;
  611.                 if (_successCount >= _options.SuccessThreshold)
  612.                 {
  613.                     _state = CircuitBreakerState.Closed;
  614.                     _failureCount = 0;
  615.                     _successCount = 0;
  616.                     _lastStateChangeTime = DateTime.UtcNow;
  617.                     _logger.LogInformation("Circuit breaker entering CLOSED state");
  618.                 }
  619.             }
  620.             else if (_state == CircuitBreakerState.Closed)
  621.             {
  622.                 // 在采样时间窗口内重置失败计数
  623.                 if (DateTime.UtcNow - _lastFailureTime > _options.SamplingDuration)
  624.                 {
  625.                     _failureCount = 0;
  626.                 }
  627.             }
  628.         }
  629.     }
  630.    
  631.     /// <summary>
  632.     /// 操作失败回调
  633.     /// </summary>
  634.     private void OnFailure(Exception ex, string operationName)
  635.     {
  636.         lock (_lock)
  637.         {
  638.             _failureCount++;
  639.             _lastFailureTime = DateTime.UtcNow;
  640.             
  641.             _logger.LogWarning(ex, "Circuit breaker recorded failure #{FailureCount} for operation: {Operation}",
  642.                 _failureCount, operationName);
  643.             
  644.             if (_state == CircuitBreakerState.Closed && _failureCount >= _options.FailureThreshold)
  645.             {
  646.                 _state = CircuitBreakerState.Open;
  647.                 _lastStateChangeTime = DateTime.UtcNow;
  648.                 _logger.LogError("Circuit breaker entering OPEN state after {FailureCount} failures", _failureCount);
  649.             }
  650.             else if (_state == CircuitBreakerState.HalfOpen)
  651.             {
  652.                 _state = CircuitBreakerState.Open;
  653.                 _lastStateChangeTime = DateTime.UtcNow;
  654.                 _logger.LogWarning("Circuit breaker returning to OPEN state from HALF_OPEN due to failure");
  655.             }
  656.         }
  657.     }
  658.    
  659.     /// <summary>
  660.     /// 获取当前状态信息
  661.     /// </summary>
  662.     public object GetState()
  663.     {
  664.         lock (_lock)
  665.         {
  666.             return new
  667.             {
  668.                 State = _state.ToString(),
  669.                 FailureCount = _failureCount,
  670.                 SuccessCount = _successCount,
  671.                 LastFailureTime = _lastFailureTime,
  672.                 LastStateChangeTime = _lastStateChangeTime,
  673.                 CanExecute = CanExecute()
  674.             };
  675.         }
  676.     }
  677. }
  678. /// <summary>
  679. /// 带断路器的Redis缓存装饰器
  680. /// </summary>
  681. public class CircuitBreakerRedisCache : IRedisDistributedCache
  682. {
  683.     private readonly IRedisDistributedCache _innerCache;
  684.     private readonly CacheCircuitBreaker _circuitBreaker;
  685.     private readonly ILogger<CircuitBreakerRedisCache> _logger;
  686.    
  687.     public CircuitBreakerRedisCache(
  688.         IRedisDistributedCache innerCache,
  689.         CacheCircuitBreaker circuitBreaker,
  690.         ILogger<CircuitBreakerRedisCache> logger)
  691.     {
  692.         _innerCache = innerCache ?? throw new ArgumentNullException(nameof(innerCache));
  693.         _circuitBreaker = circuitBreaker ?? throw new ArgumentNullException(nameof(circuitBreaker));
  694.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  695.     }
  696.    
  697.     public async Task<T> GetAsync<T>(string key)
  698.     {
  699.         try
  700.         {
  701.             return await _circuitBreaker.ExecuteAsync(() => _innerCache.GetAsync<T>(key), $"GET:{key}");
  702.         }
  703.         catch (CacheException) when (_circuitBreaker.State == CircuitBreakerState.Open)
  704.         {
  705.             _logger.LogWarning("Circuit breaker open, returning default for key: {Key}", key);
  706.             return default(T);
  707.         }
  708.     }
  709.    
  710.     public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
  711.     {
  712.         try
  713.         {
  714.             await _circuitBreaker.ExecuteAsync(() => _innerCache.SetAsync(key, value, expiry), $"SET:{key}");
  715.         }
  716.         catch (CacheException) when (_circuitBreaker.State == CircuitBreakerState.Open)
  717.         {
  718.             _logger.LogWarning("Circuit breaker open, skipping cache set for key: {Key}", key);
  719.             // 不继续抛出异常,允许应用继续运行
  720.         }
  721.     }
  722.    
  723.     // 继续实现其他接口方法...
  724.     public Task<bool> ExistsAsync(string key) =>
  725.         _circuitBreaker.ExecuteAsync(() => _innerCache.ExistsAsync(key), $"EXISTS:{key}");
  726.    
  727.     public Task<bool> RemoveAsync(string key) =>
  728.         _circuitBreaker.ExecuteAsync(() => _innerCache.RemoveAsync(key), $"REMOVE:{key}");
  729.         
  730.     public Task<long> RemoveByPatternAsync(string pattern) =>
  731.         _circuitBreaker.ExecuteAsync(() => _innerCache.RemoveByPatternAsync(pattern), $"REMOVE_PATTERN:{pattern}");
  732.    
  733.     public Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null) =>
  734.         _circuitBreaker.ExecuteAsync(() => _innerCache.GetOrSetAsync(key, factory, expiry), $"GET_OR_SET:{key}");
  735.    
  736.     public Task<Dictionary<string, T>> GetMultipleAsync<T>(IEnumerable<string> keys) =>
  737.         _circuitBreaker.ExecuteAsync(() => _innerCache.GetMultipleAsync<T>(keys), "GET_MULTIPLE");
  738.    
  739.     public Task SetMultipleAsync<T>(Dictionary<string, T> keyValuePairs, TimeSpan? expiry = null) =>
  740.         _circuitBreaker.ExecuteAsync(() => _innerCache.SetMultipleAsync(keyValuePairs, expiry), "SET_MULTIPLE");
  741.    
  742.     public Task<long> IncrementAsync(string key, long value = 1, TimeSpan? expiry = null) =>
  743.         _circuitBreaker.ExecuteAsync(() => _innerCache.IncrementAsync(key, value, expiry), $"INCREMENT:{key}");
  744.    
  745.     public Task<double> IncrementAsync(string key, double value, TimeSpan? expiry = null) =>
  746.         _circuitBreaker.ExecuteAsync(() => _innerCache.IncrementAsync(key, value, expiry), $"INCREMENT_DOUBLE:{key}");
  747.    
  748.     public Task<bool> SetIfNotExistsAsync<T>(string key, T value, TimeSpan? expiry = null) =>
  749.         _circuitBreaker.ExecuteAsync(() => _innerCache.SetIfNotExistsAsync(key, value, expiry), $"SET_IF_NOT_EXISTS:{key}");
  750.    
  751.     public Task<TimeSpan?> GetExpiryAsync(string key) =>
  752.         _circuitBreaker.ExecuteAsync(() => _innerCache.GetExpiryAsync(key), $"GET_EXPIRY:{key}");
  753.    
  754.     public Task<bool> ExpireAsync(string key, TimeSpan expiry) =>
  755.         _circuitBreaker.ExecuteAsync(() => _innerCache.ExpireAsync(key, expiry), $"EXPIRE:{key}");
  756. }
  757. /// <summary>
  758. /// LRU缓存容器,用于防止内存泄漏
  759. /// </summary>
  760. public class LRUCache<TKey, TValue>
  761. {
  762.     private readonly int _maxSize;
  763.     private readonly Dictionary<TKey, LinkedListNode<CacheItem<TKey, TValue>>> _cache;
  764.     private readonly LinkedList<CacheItem<TKey, TValue>> _lruList;
  765.     private readonly object _lock = new object();
  766.    
  767.     public LRUCache(int maxSize)
  768.     {
  769.         if (maxSize <= 0)
  770.             throw new ArgumentException("Max size must be greater than 0", nameof(maxSize));
  771.         
  772.         _maxSize = maxSize;
  773.         _cache = new Dictionary<TKey, LinkedListNode<CacheItem<TKey, TValue>>>(maxSize);
  774.         _lruList = new LinkedList<CacheItem<TKey, TValue>>();
  775.     }
  776.    
  777.     public int Count
  778.     {
  779.         get
  780.         {
  781.             lock (_lock)
  782.             {
  783.                 return _cache.Count;
  784.             }
  785.         }
  786.     }
  787.    
  788.     public bool TryGet(TKey key, out TValue value)
  789.     {
  790.         lock (_lock)
  791.         {
  792.             if (_cache.TryGetValue(key, out var node))
  793.             {
  794.                 // 移到链表头部(最近使用)
  795.                 _lruList.Remove(node);
  796.                 _lruList.AddFirst(node);
  797.                
  798.                 value = node.Value.Value;
  799.                 return true;
  800.             }
  801.             
  802.             value = default(TValue);
  803.             return false;
  804.         }
  805.     }
  806.    
  807.     public void Add(TKey key, TValue value)
  808.     {
  809.         lock (_lock)
  810.         {
  811.             if (_cache.TryGetValue(key, out var existingNode))
  812.             {
  813.                 // 更新已存在的项
  814.                 existingNode.Value.Value = value;
  815.                 existingNode.Value.LastAccessed = DateTime.UtcNow;
  816.                
  817.                 // 移到链表头部
  818.                 _lruList.Remove(existingNode);
  819.                 _lruList.AddFirst(existingNode);
  820.             }
  821.             else
  822.             {
  823.                 // 检查容量限制
  824.                 if (_cache.Count >= _maxSize)
  825.                 {
  826.                     // 移除最久未使用的项
  827.                     var lastNode = _lruList.Last;
  828.                     if (lastNode != null)
  829.                     {
  830.                         _cache.Remove(lastNode.Value.Key);
  831.                         _lruList.RemoveLast();
  832.                     }
  833.                 }
  834.                
  835.                 // 添加新项
  836.                 var newItem = new CacheItem<TKey, TValue>
  837.                 {
  838.                     Key = key,
  839.                     Value = value,
  840.                     LastAccessed = DateTime.UtcNow
  841.                 };
  842.                
  843.                 var newNode = _lruList.AddFirst(newItem);
  844.                 _cache[key] = newNode;
  845.             }
  846.         }
  847.     }
  848.    
  849.     public bool Remove(TKey key)
  850.     {
  851.         lock (_lock)
  852.         {
  853.             if (_cache.TryGetValue(key, out var node))
  854.             {
  855.                 _cache.Remove(key);
  856.                 _lruList.Remove(node);
  857.                 return true;
  858.             }
  859.             
  860.             return false;
  861.         }
  862.     }
  863.    
  864.     public void Clear()
  865.     {
  866.         lock (_lock)
  867.         {
  868.             _cache.Clear();
  869.             _lruList.Clear();
  870.         }
  871.     }
  872.    
  873.     public IEnumerable<TKey> Keys
  874.     {
  875.         get
  876.         {
  877.             lock (_lock)
  878.             {
  879.                 return _cache.Keys.ToList();
  880.             }
  881.         }
  882.     }
  883.    
  884.     /// <summary>
  885.     /// 清理过期项
  886.     /// </summary>
  887.     public int CleanupExpired(TimeSpan maxAge)
  888.     {
  889.         var cutoffTime = DateTime.UtcNow - maxAge;
  890.         var expiredKeys = new List<TKey>();
  891.         
  892.         lock (_lock)
  893.         {
  894.             foreach (var item in _lruList)
  895.             {
  896.                 if (item.LastAccessed < cutoffTime)
  897.                 {
  898.                     expiredKeys.Add(item.Key);
  899.                 }
  900.             }
  901.             
  902.             foreach (var key in expiredKeys)
  903.             {
  904.                 Remove(key);
  905.             }
  906.         }
  907.         
  908.         return expiredKeys.Count;
  909.     }
  910. }
  911. /// <summary>
  912. /// LRU缓存项
  913. /// </summary>
  914. class CacheItem<TKey, TValue>
  915. {
  916.     public TKey Key { get; set; }
  917.     public TValue Value { get; set; }
  918.     public DateTime LastAccessed { get; set; }
  919. }
  920. /// <summary>
  921. /// 高级内存缓存管理器
  922. /// 提供泛型支持、统计信息、性能监控等功能
  923. /// </summary>
  924. public interface IAdvancedMemoryCache
  925. {
  926.     Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null);
  927.     Task<T> GetAsync<T>(string key);
  928.     Task SetAsync<T>(string key, T value, TimeSpan? expiry = null);
  929.     Task RemoveAsync(string key);
  930.     Task RemoveByPatternAsync(string pattern);
  931.     CacheStatistics GetStatistics();
  932.     void ClearStatistics();
  933. }
  934. /// <summary>
  935. /// 缓存统计信息
  936. /// </summary>
  937. public class CacheStatistics
  938. {
  939.     public long HitCount { get; set; }
  940.     public long MissCount { get; set; }
  941.     public long SetCount { get; set; }
  942.     public long RemoveCount { get; set; }
  943.     public double HitRatio => HitCount + MissCount == 0 ? 0 : (double)HitCount / (HitCount + MissCount);
  944.     public DateTime StartTime { get; set; }
  945.     public TimeSpan Duration => DateTime.UtcNow - StartTime;
  946. }
  947. /// <summary>
  948. /// 缓存配置选项
  949. /// </summary>
  950. public class AdvancedMemoryCacheOptions
  951. {
  952.     public int SizeLimit { get; set; } = 1000;
  953.     public TimeSpan DefaultExpiry { get; set; } = TimeSpan.FromMinutes(30);
  954.     public bool EnableStatistics { get; set; } = true;
  955.     public bool EnablePatternRemoval { get; set; } = true;
  956.     public double CompactionPercentage { get; set; } = 0.1;
  957. }
  958. /// <summary>
  959. /// 高级内存缓存实现
  960. /// 基于IMemoryCache构建的功能增强版本
  961. /// </summary>
  962. public class AdvancedMemoryCache : IAdvancedMemoryCache, IDisposable
  963. {
  964.     private readonly IMemoryCache _cache;
  965.     private readonly ILogger _logger;
  966.     private readonly AdvancedMemoryCacheOptions _options;
  967.     private readonly CacheStatistics _statistics;
  968.     private readonly ConcurrentDictionary<string, byte> _keyTracker;
  969.     private readonly SemaphoreSlim _semaphore;
  970.     private readonly Timer _cleanupTimer;
  971.    
  972.     public AdvancedMemoryCache(
  973.         IMemoryCache cache,
  974.         ILogger logger,
  975.         IOptions options)
  976.     {
  977.         _cache = cache ?? throw new ArgumentNullException(nameof(cache));
  978.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  979.         _options = options?.Value ?? new AdvancedMemoryCacheOptions();
  980.         
  981.         _statistics = new CacheStatistics { StartTime = DateTime.UtcNow };
  982.         _keyTracker = new ConcurrentDictionary<string, byte>();
  983.         _semaphore = new SemaphoreSlim(1, 1);
  984.         
  985.         // 定期清理过期的key追踪记录
  986.         _cleanupTimer = new Timer(CleanupKeyTracker, null,
  987.             TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
  988.     }
  989.     /// <summary>
  990.     /// 获取或设置缓存项
  991.     /// 这是最常用的方法,实现了Cache-Aside模式
  992.     /// </summary>
  993.     /// <typeparam name="T">缓存项类型</typeparam>
  994.     /// <param name="key">缓存键</param>
  995.     /// <param name="factory">数据工厂方法</param>
  996.     /// <param name="expiry">过期时间</param>
  997.     /// <returns>缓存的值</returns>
  998.     public async Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
  999.     {
  1000.         if (string.IsNullOrEmpty(key))
  1001.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  1002.         
  1003.         if (factory == null)
  1004.             throw new ArgumentNullException(nameof(factory));
  1005.         // 尝试从缓存获取
  1006.         var cachedValue = await GetAsync<T>(key);
  1007.         if (cachedValue != null)
  1008.         {
  1009.             _logger.LogDebug("Cache hit for key: {Key}", key);
  1010.             return cachedValue;
  1011.         }
  1012.         // 使用信号量防止并发执行相同的factory方法
  1013.         await _semaphore.WaitAsync();
  1014.         try
  1015.         {
  1016.             // 双重检查锁定模式
  1017.             cachedValue = await GetAsync<T>(key);
  1018.             if (cachedValue != null)
  1019.             {
  1020.                 _logger.LogDebug("Cache hit on second check for key: {Key}", key);
  1021.                 return cachedValue;
  1022.             }
  1023.             // 执行工厂方法获取数据
  1024.             _logger.LogDebug("Cache miss for key: {Key}, executing factory method", key);
  1025.             var value = await factory();
  1026.             
  1027.             // 将结果存入缓存
  1028.             await SetAsync(key, value, expiry);
  1029.             
  1030.             return value;
  1031.         }
  1032.         catch (CacheConnectionException ex)
  1033.         {
  1034.             _logger.LogWarning(ex, "Cache connection failed for key: {Key}, using fallback", key);
  1035.             // 缓存连接失败时,仍执行工厂方法但不缓存结果
  1036.             return await factory();
  1037.         }
  1038.         catch (CacheSerializationException ex)
  1039.         {
  1040.             _logger.LogError(ex, "Serialization failed for key: {Key}", key);
  1041.             throw;
  1042.         }
  1043.         catch (CacheTimeoutException ex)
  1044.         {
  1045.             _logger.LogWarning(ex, "Cache operation timeout for key: {Key}", key);
  1046.             return await factory();
  1047.         }
  1048.         catch (Exception ex)
  1049.         {
  1050.             _logger.LogError(ex, "Unexpected error occurred while executing factory method for key: {Key}", key);
  1051.             throw new CacheException($"Cache operation failed for key: {key}", ex);
  1052.         }
  1053.         finally
  1054.         {
  1055.             _semaphore.Release();
  1056.         }
  1057.     }
  1058.     /// <summary>
  1059.     /// 异步获取缓存项
  1060.     /// </summary>
  1061.     /// <typeparam name="T">缓存项类型</typeparam>
  1062.     /// <param name="key">缓存键</param>
  1063.     /// <returns>缓存的值,如果不存在则返回默认值</returns>
  1064.     public Task<T> GetAsync<T>(string key)
  1065.     {
  1066.         if (string.IsNullOrEmpty(key))
  1067.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  1068.         var found = _cache.TryGetValue(key, out var value);
  1069.         
  1070.         if (_options.EnableStatistics)
  1071.         {
  1072.             if (found)
  1073.                 Interlocked.Increment(ref _statistics.HitCount);
  1074.             else
  1075.                 Interlocked.Increment(ref _statistics.MissCount);
  1076.         }
  1077.         if (found && value is T typedValue)
  1078.         {
  1079.             return Task.FromResult(typedValue);
  1080.         }
  1081.         return Task.FromResult(default(T));
  1082.     }
  1083.     /// <summary>
  1084.     /// 异步设置缓存项
  1085.     /// </summary>
  1086.     /// <typeparam name="T">缓存项类型</typeparam>
  1087.     /// <param name="key">缓存键</param>
  1088.     /// <param name="value">缓存值</param>
  1089.     /// <param name="expiry">过期时间</param>
  1090.     public Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
  1091.     {
  1092.         if (string.IsNullOrEmpty(key))
  1093.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  1094.         var cacheExpiry = expiry ?? _options.DefaultExpiry;
  1095.         
  1096.         using var entry = _cache.CreateEntry(key);
  1097.         entry.Value = value;
  1098.         entry.AbsoluteExpirationRelativeToNow = cacheExpiry;
  1099.         entry.Size = 1; // 简化的大小计算,实际应用中可根据对象大小设置
  1100.         
  1101.         // 设置过期回调
  1102.         entry.PostEvictionCallbacks.Add(new PostEvictionCallbackRegistration
  1103.         {
  1104.             EvictionCallback = OnCacheEntryEvicted,
  1105.             State = key
  1106.         });
  1107.         // 追踪缓存键
  1108.         if (_options.EnablePatternRemoval)
  1109.         {
  1110.             _keyTracker.TryAdd(key, 0);
  1111.         }
  1112.         if (_options.EnableStatistics)
  1113.         {
  1114.             Interlocked.Increment(ref _statistics.SetCount);
  1115.         }
  1116.         _logger.LogDebug("Set cache entry for key: {Key}, expiry: {Expiry}", key, cacheExpiry);
  1117.         
  1118.         return Task.CompletedTask;
  1119.     }
  1120.     /// <summary>
  1121.     /// 异步移除缓存项
  1122.     /// </summary>
  1123.     /// <param name="key">缓存键</param>
  1124.     public Task RemoveAsync(string key)
  1125.     {
  1126.         if (string.IsNullOrEmpty(key))
  1127.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  1128.         _cache.Remove(key);
  1129.         _keyTracker.TryRemove(key, out _);
  1130.         if (_options.EnableStatistics)
  1131.         {
  1132.             Interlocked.Increment(ref _statistics.RemoveCount);
  1133.         }
  1134.         _logger.LogDebug("Removed cache entry for key: {Key}", key);
  1135.         
  1136.         return Task.CompletedTask;
  1137.     }
  1138.     /// <summary>
  1139.     /// 根据模式异步移除缓存项
  1140.     /// 支持通配符匹配,如 "user:*", "*:settings"
  1141.     /// </summary>
  1142.     /// <param name="pattern">匹配模式</param>
  1143.     public async Task RemoveByPatternAsync(string pattern)
  1144.     {
  1145.         if (string.IsNullOrEmpty(pattern))
  1146.             throw new ArgumentException("Pattern cannot be null or empty", nameof(pattern));
  1147.         if (!_options.EnablePatternRemoval)
  1148.         {
  1149.             _logger.LogWarning("Pattern removal is disabled");
  1150.             return;
  1151.         }
  1152.         var keysToRemove = new List<string>();
  1153.         var regexPattern = ConvertWildcardToRegex(pattern);
  1154.         var regex = new System.Text.RegularExpressions.Regex(regexPattern,
  1155.             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
  1156.         foreach (var key in _keyTracker.Keys)
  1157.         {
  1158.             if (regex.IsMatch(key))
  1159.             {
  1160.                 keysToRemove.Add(key);
  1161.             }
  1162.         }
  1163.         foreach (var key in keysToRemove)
  1164.         {
  1165.             await RemoveAsync(key);
  1166.         }
  1167.         _logger.LogInformation("Removed {Count} cache entries matching pattern: {Pattern}",
  1168.             keysToRemove.Count, pattern);
  1169.     }
  1170.     /// <summary>
  1171.     /// 获取缓存统计信息
  1172.     /// </summary>
  1173.     /// <returns>统计信息对象</returns>
  1174.     public CacheStatistics GetStatistics()
  1175.     {
  1176.         if (!_options.EnableStatistics)
  1177.         {
  1178.             return new CacheStatistics();
  1179.         }
  1180.         return new CacheStatistics
  1181.         {
  1182.             HitCount = _statistics.HitCount,
  1183.             MissCount = _statistics.MissCount,
  1184.             SetCount = _statistics.SetCount,
  1185.             RemoveCount = _statistics.RemoveCount,
  1186.             StartTime = _statistics.StartTime
  1187.         };
  1188.     }
  1189.     /// <summary>
  1190.     /// 清除统计信息
  1191.     /// </summary>
  1192.     public void ClearStatistics()
  1193.     {
  1194.         if (_options.EnableStatistics)
  1195.         {
  1196.             Interlocked.Exchange(ref _statistics.HitCount, 0);
  1197.             Interlocked.Exchange(ref _statistics.MissCount, 0);
  1198.             Interlocked.Exchange(ref _statistics.SetCount, 0);
  1199.             Interlocked.Exchange(ref _statistics.RemoveCount, 0);
  1200.             _statistics.StartTime = DateTime.UtcNow;
  1201.         }
  1202.     }
  1203.     /// <summary>
  1204.     /// 缓存项被驱逐时的回调方法
  1205.     /// </summary>
  1206.     /// <param name="key">缓存键</param>
  1207.     /// <param name="value">缓存值</param>
  1208.     /// <param name="reason">驱逐原因</param>
  1209.     /// <param name="state">状态对象</param>
  1210.     private void OnCacheEntryEvicted(object key, object value, EvictionReason reason, object state)
  1211.     {
  1212.         var cacheKey = state?.ToString();
  1213.         if (!string.IsNullOrEmpty(cacheKey))
  1214.         {
  1215.             _keyTracker.TryRemove(cacheKey, out _);
  1216.         }
  1217.         _logger.LogDebug("Cache entry evicted - Key: {Key}, Reason: {Reason}", key, reason);
  1218.     }
  1219.     /// <summary>
  1220.     /// 将通配符模式转换为正则表达式
  1221.     /// </summary>
  1222.     /// <param name="wildcardPattern">通配符模式</param>
  1223.     /// <returns>正则表达式字符串</returns>
  1224.     private static string ConvertWildcardToRegex(string wildcardPattern)
  1225.     {
  1226.         return "^" + System.Text.RegularExpressions.Regex.Escape(wildcardPattern)
  1227.             .Replace("\\*", ".*")
  1228.             .Replace("\\?", ".") + "$";
  1229.     }
  1230.     /// <summary>
  1231.     /// 定期清理key追踪器中的过期项
  1232.     /// </summary>
  1233.     /// <param name="state">定时器状态</param>
  1234.     private void CleanupKeyTracker(object state)
  1235.     {
  1236.         var keysToRemove = new List<string>();
  1237.         
  1238.         foreach (var key in _keyTracker.Keys)
  1239.         {
  1240.             if (!_cache.TryGetValue(key, out _))
  1241.             {
  1242.                 keysToRemove.Add(key);
  1243.             }
  1244.         }
  1245.         foreach (var key in keysToRemove)
  1246.         {
  1247.             _keyTracker.TryRemove(key, out _);
  1248.         }
  1249.         if (keysToRemove.Count > 0)
  1250.         {
  1251.             _logger.LogDebug("Cleaned up {Count} expired keys from tracker", keysToRemove.Count);
  1252.         }
  1253.     }
  1254.     /// <summary>
  1255.     /// 释放资源
  1256.     /// </summary>
  1257.     public void Dispose()
  1258.     {
  1259.         _cleanupTimer?.Dispose();
  1260.         _semaphore?.Dispose();
  1261.         _cache?.Dispose();
  1262.     }
  1263. }
复制代码
3.3 内存缓存配置和依赖注入
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Hosting;
  3. /// <summary>
  4. /// 内存缓存服务扩展
  5. /// </summary>
  6. public static class MemoryCacheServiceExtensions
  7. {
  8.     /// <summary>
  9.     /// 添加高级内存缓存服务
  10.     /// </summary>
  11.     /// <param name="services">服务集合</param>
  12.     /// <param name="setupAction">配置委托</param>
  13.     /// <returns>服务集合</returns>
  14.     public static IServiceCollection AddAdvancedMemoryCache(
  15.         this IServiceCollection services,
  16.         Action setupAction = null)
  17.     {
  18.         // 添加基础内存缓存
  19.         services.AddMemoryCache(options =>
  20.         {
  21.             options.SizeLimit = 1000; // 设置缓存大小限制
  22.             options.CompactionPercentage = 0.1; // 内存压力时的压缩百分比
  23.             options.ExpirationScanFrequency = TimeSpan.FromMinutes(1); // 过期扫描频率
  24.         });
  25.         // 配置选项
  26.         if (setupAction != null)
  27.         {
  28.             services.Configure(setupAction);
  29.         }
  30.         else
  31.         {
  32.             services.Configure(options =>
  33.             {
  34.                 // 默认配置
  35.                 options.SizeLimit = 1000;
  36.                 options.DefaultExpiry = TimeSpan.FromMinutes(30);
  37.                 options.EnableStatistics = true;
  38.                 options.EnablePatternRemoval = true;
  39.                 options.CompactionPercentage = 0.1;
  40.             });
  41.         }
  42.         // 注册高级内存缓存服务(带安全装饰器)
  43.         services.AddSingleton();
  44.         services.AddSingleton<IAdvancedMemoryCache>(provider =>
  45.         {
  46.             var innerCache = provider.GetRequiredService();
  47.             var validator = provider.GetRequiredService<ICacheDataValidator>();
  48.             var logger = provider.GetRequiredService<ILogger<SecureCacheManagerDecorator>>();
  49.             return new SecureCacheManagerDecorator(innerCache, validator, logger);
  50.         });
  51.         return services;
  52.     }
  53. }
  54. /// <summary>
  55. /// 示例:在Program.cs中的配置
  56. /// </summary>
  57. public class Program
  58. {
  59.     public static void Main(string[] args)
  60.     {
  61.         var builder = WebApplication.CreateBuilder(args);
  62.         // 添加增强组件
  63.         builder.Services.AddSingleton<ICacheDataValidator, DefaultCacheDataValidator>();
  64.         builder.Services.AddSingleton<ICacheSerializer, SmartCacheSerializer>();
  65.         
  66.         // 添加断路器配置
  67.         builder.Services.Configure<CacheCircuitBreakerOptions>(options =>
  68.         {
  69.             options.FailureThreshold = 5;
  70.             options.OpenTimeout = TimeSpan.FromMinutes(1);
  71.             options.SuccessThreshold = 2;
  72.         });
  73.         builder.Services.AddSingleton<CacheCircuitBreaker>();
  74.         
  75.         // 添加高级内存缓存(带安全验证)
  76.         builder.Services.AddAdvancedMemoryCache(options =>
  77.         {
  78.             options.SizeLimit = 2000;
  79.             options.DefaultExpiry = TimeSpan.FromHours(1);
  80.             options.EnableStatistics = true;
  81.             options.EnablePatternRemoval = true;
  82.             options.CompactionPercentage = 0.15;
  83.         });
  84.         var app = builder.Build();
  85.         
  86.         app.Run();
  87.     }
  88. }
复制代码
4. Redis分布式缓存层实现

4.1 Redis连接管理和配置
  1. using StackExchange.Redis;
  2. using Microsoft.Extensions.Options;
  3. using Microsoft.Extensions.Logging;
  4. using System.Text.Json;
  5. /// <summary>
  6. /// Redis缓存配置选项
  7. /// </summary>
  8. public class RedisCacheOptions
  9. {
  10.     public string ConnectionString { get; set; } = "localhost:6379";
  11.     public int Database { get; set; } = 0;
  12.     public string KeyPrefix { get; set; } = "app:";
  13.     public TimeSpan DefaultExpiry { get; set; } = TimeSpan.FromHours(1);
  14.     public int ConnectTimeout { get; set; } = 5000;
  15.     public int SyncTimeout { get; set; } = 1000;
  16.     public bool AllowAdmin { get; set; } = false;
  17.     public string Password { get; set; }
  18.     public bool Ssl { get; set; } = false;
  19.     public int ConnectRetry { get; set; } = 3;
  20.     public bool AbortOnConnectFail { get; set; } = false;
  21.     public string ClientName { get; set; } = "MultiLevelCache";
  22. }
  23. /// <summary>
  24. /// Redis连接管理器
  25. /// 提供连接池管理和故障恢复功能
  26. /// </summary>
  27. public interface IRedisConnectionManager : IDisposable
  28. {
  29.     IDatabase GetDatabase();
  30.     ISubscriber GetSubscriber();
  31.     IServer GetServer();
  32.     bool IsConnected { get; }
  33.     Task<bool> TestConnectionAsync();
  34. }
  35. /// <summary>
  36. /// Redis连接管理器实现
  37. /// </summary>
  38. public class RedisConnectionManager : IRedisConnectionManager
  39. {
  40.     private readonly RedisCacheOptions _options;
  41.     private readonly ILogger<RedisConnectionManager> _logger;
  42.     private readonly Lazy<ConnectionMultiplexer> _connectionMultiplexer;
  43.     private bool _disposed = false;
  44.     public RedisConnectionManager(
  45.         IOptions<RedisCacheOptions> options,
  46.         ILogger<RedisConnectionManager> logger)
  47.     {
  48.         _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
  49.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  50.         
  51.         _connectionMultiplexer = new Lazy<ConnectionMultiplexer>(CreateConnection);
  52.     }
  53.     /// <summary>
  54.     /// 创建Redis连接
  55.     /// </summary>
  56.     /// <returns>ConnectionMultiplexer实例</returns>
  57.     private ConnectionMultiplexer CreateConnection()
  58.     {
  59.         var configurationOptions = new ConfigurationOptions
  60.         {
  61.             EndPoints = { _options.ConnectionString },
  62.             ConnectTimeout = _options.ConnectTimeout,
  63.             SyncTimeout = _options.SyncTimeout,
  64.             AllowAdmin = _options.AllowAdmin,
  65.             ConnectRetry = _options.ConnectRetry,
  66.             AbortOnConnectFail = _options.AbortOnConnectFail,
  67.             ClientName = _options.ClientName,
  68.             Ssl = _options.Ssl
  69.         };
  70.         if (!string.IsNullOrEmpty(_options.Password))
  71.         {
  72.             configurationOptions.Password = _options.Password;
  73.         }
  74.         try
  75.         {
  76.             var connection = ConnectionMultiplexer.Connect(configurationOptions);
  77.             
  78.             // 注册连接事件
  79.             connection.ConnectionFailed += OnConnectionFailed;
  80.             connection.ConnectionRestored += OnConnectionRestored;
  81.             connection.ErrorMessage += OnErrorMessage;
  82.             connection.InternalError += OnInternalError;
  83.             _logger.LogInformation("Redis connection established successfully");
  84.             return connection;
  85.         }
  86.         catch (Exception ex)
  87.         {
  88.             _logger.LogError(ex, "Failed to establish Redis connection");
  89.             throw;
  90.         }
  91.     }
  92.     /// <summary>
  93.     /// 获取数据库实例
  94.     /// </summary>
  95.     /// <returns>IDatabase实例</returns>
  96.     public IDatabase GetDatabase()
  97.     {
  98.         return _connectionMultiplexer.Value.GetDatabase(_options.Database);
  99.     }
  100.     /// <summary>
  101.     /// 获取订阅者实例
  102.     /// </summary>
  103.     /// <returns>ISubscriber实例</returns>
  104.     public ISubscriber GetSubscriber()
  105.     {
  106.         return _connectionMultiplexer.Value.GetSubscriber();
  107.     }
  108.     /// <summary>
  109.     /// 获取服务器实例
  110.     /// </summary>
  111.     /// <returns>IServer实例</returns>
  112.     public IServer GetServer()
  113.     {
  114.         var endpoints = _connectionMultiplexer.Value.GetEndPoints();
  115.         return _connectionMultiplexer.Value.GetServer(endpoints.First());
  116.     }
  117.     /// <summary>
  118.     /// 检查连接状态
  119.     /// </summary>
  120.     public bool IsConnected => _connectionMultiplexer.IsValueCreated &&
  121.                               _connectionMultiplexer.Value.IsConnected;
  122.     /// <summary>
  123.     /// 测试连接
  124.     /// </summary>
  125.     /// <returns>连接是否成功</returns>
  126.     public async Task<bool> TestConnectionAsync()
  127.     {
  128.         try
  129.         {
  130.             var database = GetDatabase();
  131.             await database.PingAsync();
  132.             return true;
  133.         }
  134.         catch (Exception ex)
  135.         {
  136.             _logger.LogError(ex, "Redis connection test failed");
  137.             return false;
  138.         }
  139.     }
  140.     #region 事件处理
  141.     private void OnConnectionFailed(object sender, ConnectionFailedEventArgs e)
  142.     {
  143.         _logger.LogError(e.Exception, "Redis connection failed: {EndPoint}", e.EndPoint);
  144.     }
  145.     private void OnConnectionRestored(object sender, ConnectionFailedEventArgs e)
  146.     {
  147.         _logger.LogInformation("Redis connection restored: {EndPoint}", e.EndPoint);
  148.     }
  149.     private void OnErrorMessage(object sender, RedisErrorEventArgs e)
  150.     {
  151.         _logger.LogError("Redis error: {Message}", e.Message);
  152.     }
  153.     private void OnInternalError(object sender, InternalErrorEventArgs e)
  154.     {
  155.         _logger.LogError(e.Exception, "Redis internal error");
  156.     }
  157.     #endregion
  158.     /// <summary>
  159.     /// 释放资源
  160.     /// </summary>
  161.     public void Dispose()
  162.     {
  163.         if (!_disposed)
  164.         {
  165.             if (_connectionMultiplexer.IsValueCreated)
  166.             {
  167.                 _connectionMultiplexer.Value.Close();
  168.                 _connectionMultiplexer.Value.Dispose();
  169.             }
  170.             _disposed = true;
  171.         }
  172.     }
  173. }
复制代码
4.2 Redis分布式缓存服务实现
  1. using StackExchange.Redis;
  2. using System.Text.Json;
  3. using Microsoft.Extensions.Logging;
  4. using Microsoft.Extensions.Options;
  5. /// <summary>
  6. /// Redis分布式缓存接口
  7. /// </summary>
  8. public interface IRedisDistributedCache
  9. {
  10.     Task<T> GetAsync<T>(string key);
  11.     Task SetAsync<T>(string key, T value, TimeSpan? expiry = null);
  12.     Task<bool> ExistsAsync(string key);
  13.     Task<bool> RemoveAsync(string key);
  14.     Task<long> RemoveByPatternAsync(string pattern);
  15.     Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null);
  16.     Task<Dictionary<string, T>> GetMultipleAsync<T>(IEnumerable<string> keys);
  17.     Task SetMultipleAsync<T>(Dictionary<string, T> keyValuePairs, TimeSpan? expiry = null);
  18.     Task<long> IncrementAsync(string key, long value = 1, TimeSpan? expiry = null);
  19.     Task<double> IncrementAsync(string key, double value, TimeSpan? expiry = null);
  20.     Task<bool> SetIfNotExistsAsync<T>(string key, T value, TimeSpan? expiry = null);
  21.     Task<TimeSpan?> GetExpiryAsync(string key);
  22.     Task<bool> ExpireAsync(string key, TimeSpan expiry);
  23. }
  24. /// <summary>
  25. /// Redis分布式缓存实现
  26. /// </summary>
  27. public class RedisDistributedCache : IRedisDistributedCache
  28. {
  29.     private readonly IRedisConnectionManager _connectionManager;
  30.     private readonly RedisCacheOptions _options;
  31.     private readonly ILogger<RedisDistributedCache> _logger;
  32.     private readonly ICacheSerializer _serializer;
  33.     public RedisDistributedCache(
  34.         IRedisConnectionManager connectionManager,
  35.         IOptions<RedisCacheOptions> options,
  36.         ILogger<RedisDistributedCache> logger)
  37.     {
  38.         _connectionManager = connectionManager ?? throw new ArgumentNullException(nameof(connectionManager));
  39.         _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
  40.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  41.         // 配置JSON序列化选项
  42.         // 使用智能序列化器替代直接的JSON序列化器
  43.         _serializer = serviceProvider?.GetService<ICacheSerializer>() ?? new JsonCacheSerializer();
  44.     }
  45.     /// <summary>
  46.     /// 异步获取缓存项
  47.     /// </summary>
  48.     /// <typeparam name="T">缓存项类型</typeparam>
  49.     /// <param name="key">缓存键</param>
  50.     /// <returns>缓存的值</returns>
  51.     public async Task<T> GetAsync<T>(string key)
  52.     {
  53.         if (string.IsNullOrEmpty(key))
  54.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  55.         try
  56.         {
  57.             var database = _connectionManager.GetDatabase();
  58.             var fullKey = GetFullKey(key);
  59.             var value = await database.StringGetAsync(fullKey);
  60.             if (!value.HasValue)
  61.             {
  62.                 _logger.LogDebug("Cache miss for key: {Key}", key);
  63.                 return default(T);
  64.             }
  65.             _logger.LogDebug("Cache hit for key: {Key}", key);
  66.             return DeserializeValue<T>(value);
  67.         }
  68.         catch (Exception ex)
  69.         {
  70.             _logger.LogError(ex, "Error getting value from Redis for key: {Key}", key);
  71.             return default(T);
  72.         }
  73.     }
  74.     /// <summary>
  75.     /// 异步设置缓存项
  76.     /// </summary>
  77.     /// <typeparam name="T">缓存项类型</typeparam>
  78.     /// <param name="key">缓存键</param>
  79.     /// <param name="value">缓存值</param>
  80.     /// <param name="expiry">过期时间</param>
  81.     public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
  82.     {
  83.         if (string.IsNullOrEmpty(key))
  84.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  85.         try
  86.         {
  87.             var database = _connectionManager.GetDatabase();
  88.             var fullKey = GetFullKey(key);
  89.             var serializedValue = SerializeValue(value);
  90.             var expiration = expiry ?? _options.DefaultExpiry;
  91.             await database.StringSetAsync(fullKey, serializedValue, expiration);
  92.             _logger.LogDebug("Set cache value for key: {Key}, expiry: {Expiry}", key, expiration);
  93.         }
  94.         catch (Exception ex)
  95.         {
  96.             _logger.LogError(ex, "Error setting value in Redis for key: {Key}", key);
  97.             throw;
  98.         }
  99.     }
  100.     /// <summary>
  101.     /// 检查键是否存在
  102.     /// </summary>
  103.     /// <param name="key">缓存键</param>
  104.     /// <returns>键是否存在</returns>
  105.     public async Task<bool> ExistsAsync(string key)
  106.     {
  107.         if (string.IsNullOrEmpty(key))
  108.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  109.         try
  110.         {
  111.             var database = _connectionManager.GetDatabase();
  112.             var fullKey = GetFullKey(key);
  113.             return await database.KeyExistsAsync(fullKey);
  114.         }
  115.         catch (Exception ex)
  116.         {
  117.             _logger.LogError(ex, "Error checking existence in Redis for key: {Key}", key);
  118.             return false;
  119.         }
  120.     }
  121.     /// <summary>
  122.     /// 异步移除缓存项
  123.     /// </summary>
  124.     /// <param name="key">缓存键</param>
  125.     /// <returns>是否成功移除</returns>
  126.     public async Task<bool> RemoveAsync(string key)
  127.     {
  128.         if (string.IsNullOrEmpty(key))
  129.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  130.         try
  131.         {
  132.             var database = _connectionManager.GetDatabase();
  133.             var fullKey = GetFullKey(key);
  134.             var result = await database.KeyDeleteAsync(fullKey);
  135.             
  136.             _logger.LogDebug("Remove cache key: {Key}, success: {Success}", key, result);
  137.             return result;
  138.         }
  139.         catch (Exception ex)
  140.         {
  141.             _logger.LogError(ex, "Error removing key from Redis: {Key}", key);
  142.             return false;
  143.         }
  144.     }
  145.     /// <summary>
  146.     /// 根据模式批量删除缓存项
  147.     /// </summary>
  148.     /// <param name="pattern">匹配模式</param>
  149.     /// <returns>删除的项目数量</returns>
  150.     public async Task<long> RemoveByPatternAsync(string pattern)
  151.     {
  152.         if (string.IsNullOrEmpty(pattern))
  153.             throw new ArgumentException("Pattern cannot be null or empty", nameof(pattern));
  154.         try
  155.         {
  156.             var server = _connectionManager.GetServer();
  157.             var database = _connectionManager.GetDatabase();
  158.             var fullPattern = GetFullKey(pattern);
  159.             var keys = server.Keys(database.Database, fullPattern).ToArray();
  160.             if (keys.Length == 0)
  161.             {
  162.                 return 0;
  163.             }
  164.             var deletedCount = await database.KeyDeleteAsync(keys);
  165.             _logger.LogInformation("Deleted {Count} keys matching pattern: {Pattern}", deletedCount, pattern);
  166.             
  167.             return deletedCount;
  168.         }
  169.         catch (Exception ex)
  170.         {
  171.             _logger.LogError(ex, "Error removing keys by pattern from Redis: {Pattern}", pattern);
  172.             return 0;
  173.         }
  174.     }
  175.     /// <summary>
  176.     /// 获取或设置缓存项(分布式锁实现)
  177.     /// </summary>
  178.     /// <typeparam name="T">缓存项类型</typeparam>
  179.     /// <param name="key">缓存键</param>
  180.     /// <param name="factory">数据工厂方法</param>
  181.     /// <param name="expiry">过期时间</param>
  182.     /// <returns>缓存的值</returns>
  183.     public async Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
  184.     {
  185.         if (string.IsNullOrEmpty(key))
  186.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  187.         
  188.         if (factory == null)
  189.             throw new ArgumentNullException(nameof(factory));
  190.         // 尝试从缓存获取
  191.         var cachedValue = await GetAsync<T>(key);
  192.         if (cachedValue != null)
  193.         {
  194.             return cachedValue;
  195.         }
  196.         // 使用分布式锁防止缓存击穿
  197.         var lockKey = $"{key}:lock";
  198.         var lockValue = Guid.NewGuid().ToString();
  199.         var database = _connectionManager.GetDatabase();
  200.         try
  201.         {
  202.             // 尝试获取分布式锁
  203.             var lockAcquired = await database.StringSetAsync(
  204.                 GetFullKey(lockKey),
  205.                 lockValue,
  206.                 TimeSpan.FromMinutes(1),
  207.                 When.NotExists);
  208.             if (lockAcquired)
  209.             {
  210.                 try
  211.                 {
  212.                     // 再次检查缓存
  213.                     cachedValue = await GetAsync<T>(key);
  214.                     if (cachedValue != null)
  215.                     {
  216.                         return cachedValue;
  217.                     }
  218.                     // 执行工厂方法
  219.                     _logger.LogDebug("Executing factory method for key: {Key}", key);
  220.                     var value = await factory();
  221.                     
  222.                     // 设置缓存
  223.                     await SetAsync(key, value, expiry);
  224.                     
  225.                     return value;
  226.                 }
  227.                 finally
  228.                 {
  229.                     // 释放分布式锁(使用Lua脚本确保原子性)
  230.                     const string releaseLockScript = @"
  231.                         if redis.call('GET', KEYS[1]) == ARGV[1] then
  232.                             return redis.call('DEL', KEYS[1])
  233.                         else
  234.                             return 0
  235.                         end";
  236.                     
  237.                     await database.ScriptEvaluateAsync(
  238.                         releaseLockScript,
  239.                         new RedisKey[] { GetFullKey(lockKey) },
  240.                         new RedisValue[] { lockValue });
  241.                 }
  242.             }
  243.             else
  244.             {
  245.                 // 等待锁释放并重试
  246.                 _logger.LogDebug("Waiting for lock to be released for key: {Key}", key);
  247.                 await Task.Delay(50); // 短暂等待
  248.                
  249.                 // 重试获取缓存
  250.                 cachedValue = await GetAsync<T>(key);
  251.                 if (cachedValue != null)
  252.                 {
  253.                     return cachedValue;
  254.                 }
  255.                 // 如果仍未获取到,执行降级策略
  256.                 _logger.LogWarning("Failed to acquire lock and cache miss for key: {Key}, executing factory method", key);
  257.                 return await factory();
  258.             }
  259.         }
  260.         catch (Exception ex)
  261.         {
  262.             _logger.LogError(ex, "Error in GetOrSetAsync for key: {Key}", key);
  263.             // 降级到直接执行工厂方法
  264.             return await factory();
  265.         }
  266.     }
  267.     /// <summary>
  268.     /// 批量获取缓存项
  269.     /// </summary>
  270.     /// <typeparam name="T">缓存项类型</typeparam>
  271.     /// <param name="keys">缓存键集合</param>
  272.     /// <returns>键值对字典</returns>
  273.     public async Task<Dictionary<string, T>> GetMultipleAsync<T>(IEnumerable<string> keys)
  274.     {
  275.         if (keys == null)
  276.             throw new ArgumentNullException(nameof(keys));
  277.         var keyList = keys.ToList();
  278.         if (!keyList.Any())
  279.         {
  280.             return new Dictionary<string, T>();
  281.         }
  282.         try
  283.         {
  284.             var database = _connectionManager.GetDatabase();
  285.             var fullKeys = keyList.Select(k => (RedisKey)GetFullKey(k)).ToArray();
  286.             var values = await database.StringGetAsync(fullKeys);
  287.             var result = new Dictionary<string, T>();
  288.             for (int i = 0; i < keyList.Count; i++)
  289.             {
  290.                 if (values[i].HasValue)
  291.                 {
  292.                     result[keyList[i]] = DeserializeValue<T>(values[i]);
  293.                 }
  294.             }
  295.             _logger.LogDebug("Retrieved {Count} out of {Total} keys from Redis",
  296.                 result.Count, keyList.Count);
  297.             
  298.             return result;
  299.         }
  300.         catch (Exception ex)
  301.         {
  302.             _logger.LogError(ex, "Error getting multiple values from Redis");
  303.             return new Dictionary<string, T>();
  304.         }
  305.     }
  306.     /// <summary>
  307.     /// 批量设置缓存项
  308.     /// </summary>
  309.     /// <typeparam name="T">缓存项类型</typeparam>
  310.     /// <param name="keyValuePairs">键值对字典</param>
  311.     /// <param name="expiry">过期时间</param>
  312.     public async Task SetMultipleAsync<T>(Dictionary<string, T> keyValuePairs, TimeSpan? expiry = null)
  313.     {
  314.         if (keyValuePairs == null || !keyValuePairs.Any())
  315.             return;
  316.         try
  317.         {
  318.             var database = _connectionManager.GetDatabase();
  319.             var expiration = expiry ?? _options.DefaultExpiry;
  320.             
  321.             var tasks = keyValuePairs.Select(async kvp =>
  322.             {
  323.                 var fullKey = GetFullKey(kvp.Key);
  324.                 var serializedValue = SerializeValue(kvp.Value);
  325.                 await database.StringSetAsync(fullKey, serializedValue, expiration);
  326.             });
  327.             await Task.WhenAll(tasks);
  328.             
  329.             _logger.LogDebug("Set {Count} cache values with expiry: {Expiry}",
  330.                 keyValuePairs.Count, expiration);
  331.         }
  332.         catch (Exception ex)
  333.         {
  334.             _logger.LogError(ex, "Error setting multiple values in Redis");
  335.             throw;
  336.         }
  337.     }
  338.     /// <summary>
  339.     /// 原子递增操作
  340.     /// </summary>
  341.     /// <param name="key">缓存键</param>
  342.     /// <param name="value">递增值</param>
  343.     /// <param name="expiry">过期时间</param>
  344.     /// <returns>递增后的值</returns>
  345.     public async Task<long> IncrementAsync(string key, long value = 1, TimeSpan? expiry = null)
  346.     {
  347.         if (string.IsNullOrEmpty(key))
  348.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  349.         try
  350.         {
  351.             var database = _connectionManager.GetDatabase();
  352.             var fullKey = GetFullKey(key);
  353.             
  354.             var result = await database.StringIncrementAsync(fullKey, value);
  355.             
  356.             if (expiry.HasValue)
  357.             {
  358.                 await database.KeyExpireAsync(fullKey, expiry.Value);
  359.             }
  360.             return result;
  361.         }
  362.         catch (Exception ex)
  363.         {
  364.             _logger.LogError(ex, "Error incrementing value in Redis for key: {Key}", key);
  365.             throw;
  366.         }
  367.     }
  368.     /// <summary>
  369.     /// 原子递增操作(浮点数)
  370.     /// </summary>
  371.     /// <param name="key">缓存键</param>
  372.     /// <param name="value">递增值</param>
  373.     /// <param name="expiry">过期时间</param>
  374.     /// <returns>递增后的值</returns>
  375.     public async Task<double> IncrementAsync(string key, double value, TimeSpan? expiry = null)
  376.     {
  377.         if (string.IsNullOrEmpty(key))
  378.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  379.         try
  380.         {
  381.             var database = _connectionManager.GetDatabase();
  382.             var fullKey = GetFullKey(key);
  383.             
  384.             var result = await database.StringIncrementAsync(fullKey, value);
  385.             
  386.             if (expiry.HasValue)
  387.             {
  388.                 await database.KeyExpireAsync(fullKey, expiry.Value);
  389.             }
  390.             return result;
  391.         }
  392.         catch (Exception ex)
  393.         {
  394.             _logger.LogError(ex, "Error incrementing double value in Redis for key: {Key}", key);
  395.             throw;
  396.         }
  397.     }
  398.     /// <summary>
  399.     /// 仅在键不存在时设置值
  400.     /// </summary>
  401.     /// <typeparam name="T">缓存项类型</typeparam>
  402.     /// <param name="key">缓存键</param>
  403.     /// <param name="value">缓存值</param>
  404.     /// <param name="expiry">过期时间</param>
  405.     /// <returns>是否设置成功</returns>
  406.     public async Task<bool> SetIfNotExistsAsync<T>(string key, T value, TimeSpan? expiry = null)
  407.     {
  408.         if (string.IsNullOrEmpty(key))
  409.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  410.         try
  411.         {
  412.             var database = _connectionManager.GetDatabase();
  413.             var fullKey = GetFullKey(key);
  414.             var serializedValue = SerializeValue(value);
  415.             var expiration = expiry ?? _options.DefaultExpiry;
  416.             var result = await database.StringSetAsync(fullKey, serializedValue, expiration, When.NotExists);
  417.             
  418.             _logger.LogDebug("SetIfNotExists for key: {Key}, success: {Success}", key, result);
  419.             return result;
  420.         }
  421.         catch (Exception ex)
  422.         {
  423.             _logger.LogError(ex, "Error in SetIfNotExists for key: {Key}", key);
  424.             return false;
  425.         }
  426.     }
  427.     /// <summary>
  428.     /// 获取键的过期时间
  429.     /// </summary>
  430.     /// <param name="key">缓存键</param>
  431.     /// <returns>过期时间,如果键不存在或无过期时间则返回null</returns>
  432.     public async Task<TimeSpan?> GetExpiryAsync(string key)
  433.     {
  434.         if (string.IsNullOrEmpty(key))
  435.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  436.         try
  437.         {
  438.             var database = _connectionManager.GetDatabase();
  439.             var fullKey = GetFullKey(key);
  440.             return await database.KeyTimeToLiveAsync(fullKey);
  441.         }
  442.         catch (Exception ex)
  443.         {
  444.             _logger.LogError(ex, "Error getting expiry for key: {Key}", key);
  445.             return null;
  446.         }
  447.     }
  448.     /// <summary>
  449.     /// 设置键的过期时间
  450.     /// </summary>
  451.     /// <param name="key">缓存键</param>
  452.     /// <param name="expiry">过期时间</param>
  453.     /// <returns>是否设置成功</returns>
  454.     public async Task<bool> ExpireAsync(string key, TimeSpan expiry)
  455.     {
  456.         if (string.IsNullOrEmpty(key))
  457.             throw new ArgumentException("Key cannot be null or empty", nameof(key));
  458.         try
  459.         {
  460.             var database = _connectionManager.GetDatabase();
  461.             var fullKey = GetFullKey(key);
  462.             return await database.KeyExpireAsync(fullKey, expiry);
  463.         }
  464.         catch (Exception ex)
  465.         {
  466.             _logger.LogError(ex, "Error setting expiry for key: {Key}", key);
  467.             return false;
  468.         }
  469.     }
  470.     #region 辅助方法
  471.     /// <summary>
  472.     /// 获取完整的缓存键(带前缀)
  473.     /// </summary>
  474.     /// <param name="key">原始键</param>
  475.     /// <returns>完整键</returns>
  476.     private string GetFullKey(string key)
  477.     {
  478.         return $"{_options.KeyPrefix}{key}";
  479.     }
  480.     /// <summary>
  481.     /// 序列化值
  482.     /// </summary>
  483.     /// <typeparam name="T">值类型</typeparam>
  484.     /// <param name="value">要序列化的值</param>
  485.     /// <returns>序列化后的字符串</returns>
  486.     private string SerializeValue<T>(T value)
  487.     {
  488.         if (value == null) return null;
  489.         
  490.         try
  491.         {
  492.             var serializedBytes = _serializer.Serialize(value);
  493.             return Convert.ToBase64String(serializedBytes);
  494.         }
  495.         catch (Exception ex)
  496.         {
  497.             _logger.LogError(ex, "Error serializing value of type: {Type}", typeof(T).Name);
  498.             throw new CacheSerializationException($"Failed to serialize value of type: {typeof(T).Name}", ex);
  499.         }
  500.     }
  501.     /// <summary>
  502.     /// 反序列化值
  503.     /// </summary>
  504.     /// <typeparam name="T">目标类型</typeparam>
  505.     /// <param name="value">要反序列化的值</param>
  506.     /// <returns>反序列化后的对象</returns>
  507.     private T DeserializeValue<T>(string value)
  508.     {
  509.         if (string.IsNullOrEmpty(value)) return default(T);
  510.         
  511.         try
  512.         {
  513.             var serializedBytes = Convert.FromBase64String(value);
  514.             return _serializer.Deserialize<T>(serializedBytes);
  515.         }
  516.         catch (Exception ex)
  517.         {
  518.             _logger.LogError(ex, "Error deserializing value to type: {Type}", typeof(T).Name);
  519.             throw new CacheSerializationException($"Failed to deserialize value to type: {typeof(T).Name}", ex);
  520.         }
  521.     }
  522.     #endregion
  523. }
复制代码
5. Redis发布-订阅同步机制实现

5.1 缓存同步事件模型
  1. using System.Text.Json;
  2. /// <summary>
  3. /// 缓存同步事件类型
  4. /// </summary>
  5. public enum CacheSyncEventType
  6. {
  7.     /// <summary>
  8.     /// 缓存项被设置
  9.     /// </summary>
  10.     Set,
  11.    
  12.     /// <summary>
  13.     /// 缓存项被删除
  14.     /// </summary>
  15.     Remove,
  16.    
  17.     /// <summary>
  18.     /// 缓存项过期
  19.     /// </summary>
  20.     Expire,
  21.    
  22.     /// <summary>
  23.     /// 批量删除(按模式)
  24.     /// </summary>
  25.     RemovePattern,
  26.    
  27.     /// <summary>
  28.     /// 清空所有缓存
  29.     /// </summary>
  30.     Clear
  31. }
  32. /// <summary>
  33. /// 缓存同步事件
  34. /// </summary>
  35. public class CacheSyncEvent
  36. {
  37.     /// <summary>
  38.     /// 事件ID(用于幂等性控制)
  39.     /// </summary>
  40.     public string EventId { get; set; } = Guid.NewGuid().ToString();
  41.    
  42.     /// <summary>
  43.     /// 事件类型
  44.     /// </summary>
  45.     public CacheSyncEventType EventType { get; set; }
  46.    
  47.     /// <summary>
  48.     /// 缓存键
  49.     /// </summary>
  50.     public string Key { get; set; }
  51.    
  52.     /// <summary>
  53.     /// 模式(用于批量删除)
  54.     /// </summary>
  55.     public string Pattern { get; set; }
  56.    
  57.     /// <summary>
  58.     /// 事件发生时间
  59.     /// </summary>
  60.     public DateTime Timestamp { get; set; } = DateTime.UtcNow;
  61.    
  62.     /// <summary>
  63.     /// 发起节点标识
  64.     /// </summary>
  65.     public string NodeId { get; set; }
  66.    
  67.     /// <summary>
  68.     /// 附加数据
  69.     /// </summary>
  70.     public Dictionary<string, object> Metadata { get; set; } = new();
  71.     /// <summary>
  72.     /// 序列化为JSON
  73.     /// </summary>
  74.     /// <returns>JSON字符串</returns>
  75.     public string ToJson()
  76.     {
  77.         return JsonSerializer.Serialize(this, new JsonSerializerOptions
  78.         {
  79.             PropertyNamingPolicy = JsonNamingPolicy.CamelCase
  80.         });
  81.     }
  82.     /// <summary>
  83.     /// 从JSON反序列化
  84.     /// </summary>
  85.     /// <param name="json">JSON字符串</param>
  86.     /// <returns>缓存同步事件</returns>
  87.     public static CacheSyncEvent FromJson(string json)
  88.     {
  89.         return JsonSerializer.Deserialize<CacheSyncEvent>(json, new JsonSerializerOptions
  90.         {
  91.             PropertyNamingPolicy = JsonNamingPolicy.CamelCase
  92.         });
  93.     }
  94. }
  95. /// <summary>
  96. /// 缓存同步配置选项
  97. /// </summary>
  98. public class CacheSyncOptions
  99. {
  100.     /// <summary>
  101.     /// Redis发布订阅频道前缀
  102.     /// </summary>
  103.     public string ChannelPrefix { get; set; } = "cache_sync";
  104.    
  105.     /// <summary>
  106.     /// 当前节点ID
  107.     /// </summary>
  108.     public string NodeId { get; set; } = Environment.MachineName;
  109.    
  110.     /// <summary>
  111.     /// 是否启用缓存同步
  112.     /// </summary>
  113.     public bool EnableSync { get; set; } = true;
  114.    
  115.     /// <summary>
  116.     /// 事件去重窗口时间
  117.     /// </summary>
  118.     public TimeSpan DeduplicationWindow { get; set; } = TimeSpan.FromSeconds(30);
  119.    
  120.     /// <summary>
  121.     /// 最大重试次数
  122.     /// </summary>
  123.     public int MaxRetryAttempts { get; set; } = 3;
  124.    
  125.     /// <summary>
  126.     /// 重试延迟
  127.     /// </summary>
  128.     public TimeSpan RetryDelay { get; set; } = TimeSpan.FromSeconds(1);
  129.    
  130.     /// <summary>
  131.     /// 批量处理的最大延迟
  132.     /// </summary>
  133.     public TimeSpan BatchMaxDelay { get; set; } = TimeSpan.FromMilliseconds(100);
  134.    
  135.     /// <summary>
  136.     /// 批量处理的最大大小
  137.     /// </summary>
  138.     public int BatchMaxSize { get; set; } = 50;
  139. }
复制代码
5.2 Redis发布-订阅同步服务
  1. using Microsoft.Extensions.Hosting;
  2. using Microsoft.Extensions.Logging;
  3. using Microsoft.Extensions.Options;
  4. using StackExchange.Redis;
  5. using System.Collections.Concurrent;
  6. using System.Threading.Channels;
  7. /// <summary>
  8. /// 缓存同步服务接口
  9. /// </summary>
  10. public interface ICacheSyncService
  11. {
  12.     /// <summary>
  13.     /// 发布缓存同步事件
  14.     /// </summary>
  15.     /// <param name="syncEvent">同步事件</param>
  16.     Task PublishAsync(CacheSyncEvent syncEvent);
  17.    
  18.     /// <summary>
  19.     /// 订阅缓存同步事件
  20.     /// </summary>
  21.     /// <param name="handler">事件处理器</param>
  22.     Task SubscribeAsync(Func<CacheSyncEvent, Task> handler);
  23.    
  24.     /// <summary>
  25.     /// 取消订阅
  26.     /// </summary>
  27.     Task UnsubscribeAsync();
  28.    
  29.     /// <summary>
  30.     /// 检查服务状态
  31.     /// </summary>
  32.     bool IsHealthy { get; }
  33. }
  34. /// <summary>
  35. /// Redis发布-订阅缓存同步服务
  36. /// </summary>
  37. public class RedisCacheSyncService : ICacheSyncService, IHostedService, IDisposable
  38. {
  39.     private readonly IRedisConnectionManager _connectionManager;
  40.     private readonly CacheSyncOptions _options;
  41.     private readonly ILogger<RedisCacheSyncService> _logger;
  42.    
  43.     // 事件处理器集合
  44.     private readonly ConcurrentBag<Func<CacheSyncEvent, Task>> _handlers;
  45.    
  46.     // 事件去重缓存
  47.     private readonly ConcurrentDictionary<string, DateTime> _processedEvents;
  48.    
  49.     // 批量处理通道
  50.     private readonly Channel<CacheSyncEvent> _eventChannel;
  51.     private readonly ChannelWriter<CacheSyncEvent> _eventWriter;
  52.     private readonly ChannelReader<CacheSyncEvent> _eventReader;
  53.    
  54.     // 订阅和处理任务
  55.     private Task _subscriptionTask;
  56.     private Task _processingTask;
  57.     private CancellationTokenSource _cancellationTokenSource;
  58.    
  59.     // 服务状态
  60.     private volatile bool _isHealthy = false;
  61.     private bool _disposed = false;
  62.     public RedisCacheSyncService(
  63.         IRedisConnectionManager connectionManager,
  64.         IOptions<CacheSyncOptions> options,
  65.         ILogger<RedisCacheSyncService> logger)
  66.     {
  67.         _connectionManager = connectionManager ?? throw new ArgumentNullException(nameof(connectionManager));
  68.         _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
  69.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  70.         _handlers = new ConcurrentBag<Func<CacheSyncEvent, Task>>();
  71.         _processedEvents = new ConcurrentDictionary<string, DateTime>();
  72.         // 创建有界通道用于批量处理
  73.         var channelOptions = new BoundedChannelOptions(_options.BatchMaxSize * 2)
  74.         {
  75.             FullMode = BoundedChannelFullMode.Wait,
  76.             SingleReader = true,
  77.             SingleWriter = false
  78.         };
  79.         
  80.         _eventChannel = Channel.CreateBounded<CacheSyncEvent>(channelOptions);
  81.         _eventWriter = _eventChannel.Writer;
  82.         _eventReader = _eventChannel.Reader;
  83.     }
  84.     /// <summary>
  85.     /// 服务健康状态
  86.     /// </summary>
  87.     public bool IsHealthy => _isHealthy;
  88.     /// <summary>
  89.     /// 发布缓存同步事件
  90.     /// </summary>
  91.     /// <param name="syncEvent">同步事件</param>
  92.     public async Task PublishAsync(CacheSyncEvent syncEvent)
  93.     {
  94.         if (!_options.EnableSync || syncEvent == null)
  95.             return;
  96.         try
  97.         {
  98.             // 设置节点ID
  99.             syncEvent.NodeId = _options.NodeId;
  100.             
  101.             var subscriber = _connectionManager.GetSubscriber();
  102.             var channel = GetChannelName();
  103.             var message = syncEvent.ToJson();
  104.             await subscriber.PublishAsync(channel, message);
  105.             
  106.             _logger.LogDebug("Published sync event: {EventType} for key: {Key}",
  107.                 syncEvent.EventType, syncEvent.Key);
  108.         }
  109.         catch (Exception ex)
  110.         {
  111.             _logger.LogError(ex, "Failed to publish sync event: {EventType} for key: {Key}",
  112.                 syncEvent.EventType, syncEvent.Key);
  113.         }
  114.     }
  115.     /// <summary>
  116.     /// 订阅缓存同步事件
  117.     /// </summary>
  118.     /// <param name="handler">事件处理器</param>
  119.     public Task SubscribeAsync(Func<CacheSyncEvent, Task> handler)
  120.     {
  121.         if (handler == null)
  122.             throw new ArgumentNullException(nameof(handler));
  123.         _handlers.Add(handler);
  124.         _logger.LogDebug("Added sync event handler");
  125.         
  126.         return Task.CompletedTask;
  127.     }
  128.     /// <summary>
  129.     /// 取消订阅
  130.     /// </summary>
  131.     public async Task UnsubscribeAsync()
  132.     {
  133.         try
  134.         {
  135.             if (_subscriptionTask != null && !_subscriptionTask.IsCompleted)
  136.             {
  137.                 _cancellationTokenSource?.Cancel();
  138.                 await _subscriptionTask;
  139.             }
  140.             
  141.             _logger.LogDebug("Unsubscribed from sync events");
  142.         }
  143.         catch (Exception ex)
  144.         {
  145.             _logger.LogError(ex, "Error during unsubscribe");
  146.         }
  147.     }
  148.     /// <summary>
  149.     /// 启动服务
  150.     /// </summary>
  151.     /// <param name="cancellationToken">取消令牌</param>
  152.     public Task StartAsync(CancellationToken cancellationToken)
  153.     {
  154.         if (!_options.EnableSync)
  155.         {
  156.             _logger.LogInformation("Cache sync is disabled");
  157.             return Task.CompletedTask;
  158.         }
  159.         _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
  160.         
  161.         // 启动Redis订阅任务
  162.         _subscriptionTask = StartSubscriptionAsync(_cancellationTokenSource.Token);
  163.         
  164.         // 启动事件处理任务
  165.         _processingTask = StartProcessingAsync(_cancellationTokenSource.Token);
  166.         
  167.         // 启动清理任务
  168.         _ = Task.Run(() => StartCleanupAsync(_cancellationTokenSource.Token), cancellationToken);
  169.         _logger.LogInformation("Cache sync service started with NodeId: {NodeId}", _options.NodeId);
  170.         return Task.CompletedTask;
  171.     }
  172.     /// <summary>
  173.     /// 停止服务
  174.     /// </summary>
  175.     /// <param name="cancellationToken">取消令牌</param>
  176.     public async Task StopAsync(CancellationToken cancellationToken)
  177.     {
  178.         _logger.LogInformation("Stopping cache sync service");
  179.         _cancellationTokenSource?.Cancel();
  180.         
  181.         // 完成事件通道写入
  182.         _eventWriter.TryComplete();
  183.         try
  184.         {
  185.             // 等待订阅任务完成
  186.             if (_subscriptionTask != null)
  187.             {
  188.                 await _subscriptionTask.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken);
  189.             }
  190.             
  191.             // 等待处理任务完成
  192.             if (_processingTask != null)
  193.             {
  194.                 await _processingTask.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken);
  195.             }
  196.         }
  197.         catch (TimeoutException)
  198.         {
  199.             _logger.LogWarning("Cache sync service stop timed out");
  200.         }
  201.         catch (Exception ex)
  202.         {
  203.             _logger.LogError(ex, "Error stopping cache sync service");
  204.         }
  205.         _isHealthy = false;
  206.         _logger.LogInformation("Cache sync service stopped");
  207.     }
  208.     /// <summary>
  209.     /// 启动Redis订阅
  210.     /// </summary>
  211.     /// <param name="cancellationToken">取消令牌</param>
  212.     private async Task StartSubscriptionAsync(CancellationToken cancellationToken)
  213.     {
  214.         var retryCount = 0;
  215.         
  216.         while (!cancellationToken.IsCancellationRequested && retryCount < _options.MaxRetryAttempts)
  217.         {
  218.             try
  219.             {
  220.                 var subscriber = _connectionManager.GetSubscriber();
  221.                 var channel = GetChannelName();
  222.                 await subscriber.SubscribeAsync(channel, OnMessageReceived);
  223.                
  224.                 _isHealthy = true;
  225.                 _logger.LogInformation("Successfully subscribed to Redis channel: {Channel}", channel);
  226.                
  227.                 // 保持订阅状态
  228.                 while (!cancellationToken.IsCancellationRequested)
  229.                 {
  230.                     await Task.Delay(1000, cancellationToken);
  231.                 }
  232.                
  233.                 break;
  234.             }
  235.             catch (OperationCanceledException)
  236.             {
  237.                 break;
  238.             }
  239.             catch (Exception ex)
  240.             {
  241.                 retryCount++;
  242.                 _isHealthy = false;
  243.                
  244.                 _logger.LogError(ex, "Redis subscription failed, retry {RetryCount}/{MaxRetries}",
  245.                     retryCount, _options.MaxRetryAttempts);
  246.                 if (retryCount < _options.MaxRetryAttempts)
  247.                 {
  248.                     await Task.Delay(_options.RetryDelay, cancellationToken);
  249.                 }
  250.             }
  251.         }
  252.     }
  253.     /// <summary>
  254.     /// 启动事件批量处理
  255.     /// </summary>
  256.     /// <param name="cancellationToken">取消令牌</param>
  257.     private async Task StartProcessingAsync(CancellationToken cancellationToken)
  258.     {
  259.         var eventBatch = new List<CacheSyncEvent>();
  260.         var batchTimer = Stopwatch.StartNew();
  261.         try
  262.         {
  263.             while (!cancellationToken.IsCancellationRequested)
  264.             {
  265.                 // 尝试读取事件(带超时)
  266.                 var hasEvent = await _eventReader.WaitToReadAsync(cancellationToken);
  267.                 if (!hasEvent)
  268.                     break;
  269.                 // 收集批量事件
  270.                 while (_eventReader.TryRead(out var syncEvent) &&
  271.                        eventBatch.Count < _options.BatchMaxSize)
  272.                 {
  273.                     eventBatch.Add(syncEvent);
  274.                 }
  275.                 // 检查是否应该处理批次
  276.                 var shouldProcess = eventBatch.Count >= _options.BatchMaxSize ||
  277.                                    batchTimer.Elapsed >= _options.BatchMaxDelay ||
  278.                                    !_eventReader.TryPeek(out _); // 没有更多事件
  279.                 if (shouldProcess && eventBatch.Count > 0)
  280.                 {
  281.                     await ProcessEventBatchAsync(eventBatch, cancellationToken);
  282.                     
  283.                     eventBatch.Clear();
  284.                     batchTimer.Restart();
  285.                 }
  286.                 else if (eventBatch.Count > 0)
  287.                 {
  288.                     // 短暂等待以收集更多事件
  289.                     await Task.Delay(10, cancellationToken);
  290.                 }
  291.             }
  292.         }
  293.         catch (OperationCanceledException)
  294.         {
  295.             // 正常取消
  296.         }
  297.         catch (Exception ex)
  298.         {
  299.             _logger.LogError(ex, "Error in event processing loop");
  300.         }
  301.         finally
  302.         {
  303.             // 处理剩余的事件
  304.             if (eventBatch.Count > 0)
  305.             {
  306.                 try
  307.                 {
  308.                     await ProcessEventBatchAsync(eventBatch, CancellationToken.None);
  309.                 }
  310.                 catch (Exception ex)
  311.                 {
  312.                     _logger.LogError(ex, "Error processing final event batch");
  313.                 }
  314.             }
  315.         }
  316.     }
  317.     /// <summary>
  318.     /// 处理事件批次
  319.     /// </summary>
  320.     /// <param name="events">事件列表</param>
  321.     /// <param name="cancellationToken">取消令牌</param>
  322.     private async Task ProcessEventBatchAsync(List<CacheSyncEvent> events, CancellationToken cancellationToken)
  323.     {
  324.         if (!events.Any())
  325.             return;
  326.         try
  327.         {
  328.             var tasks = events
  329.                 .Where(e => !IsEventProcessed(e.EventId))
  330.                 .Select(async e =>
  331.                 {
  332.                     try
  333.                     {
  334.                         // 标记事件为已处理
  335.                         MarkEventAsProcessed(e.EventId);
  336.                         
  337.                         // 并行调用所有处理器
  338.                         var handlerTasks = _handlers.Select(handler => handler(e));
  339.                         await Task.WhenAll(handlerTasks);
  340.                         
  341.                         _logger.LogDebug("Processed sync event: {EventType} for key: {Key}",
  342.                             e.EventType, e.Key);
  343.                     }
  344.                     catch (Exception ex)
  345.                     {
  346.                         _logger.LogError(ex, "Error processing sync event: {EventId}", e.EventId);
  347.                     }
  348.                 });
  349.             await Task.WhenAll(tasks);
  350.             
  351.             _logger.LogDebug("Processed batch of {Count} sync events", events.Count);
  352.         }
  353.         catch (Exception ex)
  354.         {
  355.             _logger.LogError(ex, "Error processing event batch");
  356.         }
  357.     }
  358.     /// <summary>
  359.     /// 处理接收到的Redis消息
  360.     /// </summary>
  361.     /// <param name="channel">频道</param>
  362.     /// <param name="message">消息</param>
  363.     private async void OnMessageReceived(RedisChannel channel, RedisValue message)
  364.     {
  365.         try
  366.         {
  367.             if (!message.HasValue)
  368.                 return;
  369.             var syncEvent = CacheSyncEvent.FromJson(message);
  370.             
  371.             // 忽略自己发送的事件
  372.             if (syncEvent.NodeId == _options.NodeId)
  373.             {
  374.                 _logger.LogTrace("Ignoring self-generated event: {EventId}", syncEvent.EventId);
  375.                 return;
  376.             }
  377.             // 将事件加入处理队列
  378.             if (!await _eventWriter.WaitToWriteAsync())
  379.             {
  380.                 _logger.LogWarning("Event channel is closed, dropping event: {EventId}", syncEvent.EventId);
  381.                 return;
  382.             }
  383.             if (!_eventWriter.TryWrite(syncEvent))
  384.             {
  385.                 _logger.LogWarning("Failed to queue sync event: {EventId}", syncEvent.EventId);
  386.             }
  387.         }
  388.         catch (JsonException ex)
  389.         {
  390.             _logger.LogError(ex, "Failed to deserialize sync event message: {Message}", message.ToString());
  391.         }
  392.         catch (Exception ex)
  393.         {
  394.             _logger.LogError(ex, "Error processing received message");
  395.         }
  396.     }
  397.     /// <summary>
  398.     /// 检查事件是否已处理(防止重复处理)
  399.     /// </summary>
  400.     /// <param name="eventId">事件ID</param>
  401.     /// <returns>是否已处理</returns>
  402.     private bool IsEventProcessed(string eventId)
  403.     {
  404.         return _processedEvents.ContainsKey(eventId);
  405.     }
  406.     /// <summary>
  407.     /// 标记事件为已处理
  408.     /// </summary>
  409.     /// <param name="eventId">事件ID</param>
  410.     private void MarkEventAsProcessed(string eventId)
  411.     {
  412.         _processedEvents.TryAdd(eventId, DateTime.UtcNow);
  413.     }
  414.     /// <summary>
  415.     /// 启动定期清理已处理事件记录
  416.     /// </summary>
  417.     /// <param name="cancellationToken">取消令牌</param>
  418.     private async Task StartCleanupAsync(CancellationToken cancellationToken)
  419.     {
  420.         while (!cancellationToken.IsCancellationRequested)
  421.         {
  422.             try
  423.             {
  424.                 await Task.Delay(TimeSpan.FromMinutes(5), cancellationToken);
  425.                
  426.                 var cutoffTime = DateTime.UtcNow - _options.DeduplicationWindow;
  427.                 var keysToRemove = _processedEvents
  428.                     .Where(kvp => kvp.Value < cutoffTime)
  429.                     .Select(kvp => kvp.Key)
  430.                     .ToList();
  431.                 foreach (var key in keysToRemove)
  432.                 {
  433.                     _processedEvents.TryRemove(key, out _);
  434.                 }
  435.                 if (keysToRemove.Count > 0)
  436.                 {
  437.                     _logger.LogDebug("Cleaned up {Count} processed event records", keysToRemove.Count);
  438.                 }
  439.             }
  440.             catch (OperationCanceledException)
  441.             {
  442.                 break;
  443.             }
  444.             catch (Exception ex)
  445.             {
  446.                 _logger.LogError(ex, "Error in cleanup task");
  447.             }
  448.         }
  449.     }
  450.     /// <summary>
  451.     /// 获取Redis频道名称
  452.     /// </summary>
  453.     /// <returns>频道名称</returns>
  454.     private string GetChannelName()
  455.     {
  456.         return $"{_options.ChannelPrefix}:events";
  457.     }
  458.     /// <summary>
  459.     /// 释放资源
  460.     /// </summary>
  461.     public void Dispose()
  462.     {
  463.         if (!_disposed)
  464.         {
  465.             _cancellationTokenSource?.Cancel();
  466.             _eventWriter?.TryComplete();
  467.             
  468.             try
  469.             {
  470.                 Task.WhenAll(
  471.                     _subscriptionTask ?? Task.CompletedTask,
  472.                     _processingTask ?? Task.CompletedTask
  473.                 ).Wait(TimeSpan.FromSeconds(5));
  474.             }
  475.             catch (Exception ex)
  476.             {
  477.                 _logger.LogError(ex, "Error during disposal");
  478.             }
  479.             
  480.             _cancellationTokenSource?.Dispose();
  481.             _disposed = true;
  482.         }
  483.     }
  484. }
复制代码
5.3 缓存同步扩展方法
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Hosting;
  3. /// <summary>
  4. /// 缓存同步服务扩展方法
  5. /// </summary>
  6. public static class CacheSyncServiceExtensions
  7. {
  8.     /// <summary>
  9.     /// 添加Redis缓存同步服务
  10.     /// </summary>
  11.     /// <param name="services">服务集合</param>
  12.     /// <param name="setupAction">配置委托</param>
  13.     /// <returns>服务集合</returns>
  14.     public static IServiceCollection AddRedisCacheSync(
  15.         this IServiceCollection services,
  16.         Action<CacheSyncOptions> setupAction = null)
  17.     {
  18.         // 配置选项
  19.         if (setupAction != null)
  20.         {
  21.             services.Configure(setupAction);
  22.         }
  23.         else
  24.         {
  25.             services.Configure<CacheSyncOptions>(options =>
  26.             {
  27.                 // 使用默认配置
  28.             });
  29.         }
  30.         // 注册Redis缓存服务(带断路器装饰器)
  31.         services.AddSingleton<RedisDistributedCache>();
  32.         services.AddSingleton<IRedisDistributedCache>(provider =>
  33.         {
  34.             var innerCache = provider.GetRequiredService<RedisDistributedCache>();
  35.             var circuitBreaker = provider.GetRequiredService<CacheCircuitBreaker>();
  36.             var logger = provider.GetRequiredService<ILogger<CircuitBreakerRedisCache>>();
  37.             return new CircuitBreakerRedisCache(innerCache, circuitBreaker, logger);
  38.         });
  39.         
  40.         // 注册缓存同步服务
  41.         services.AddSingleton<ICacheSyncService, RedisCacheSyncService>();
  42.         services.AddHostedService<RedisCacheSyncService>(provider =>
  43.             (RedisCacheSyncService)provider.GetRequiredService<ICacheSyncService>());
  44.         return services;
  45.     }
  46. }
复制代码
6. 完整的多级缓存管理器实现

现在我将完成多级缓存管理器的实现,这是整个系统的核心组件:
  1. using Microsoft.Extensions.Logging;
  2. using Microsoft.Extensions.Options;
  3. using System.Diagnostics;
  4. /// <summary>
  5. /// 多级缓存配置选项
  6. /// </summary>
  7. public class MultiLevelCacheOptions
  8. {
  9.     /// <summary>
  10.     /// L1缓存(内存缓存)配置
  11.     /// </summary>
  12.     public AdvancedMemoryCacheOptions L1Options { get; set; } = new();
  13.    
  14.     /// <summary>
  15.     /// L2缓存(Redis缓存)配置
  16.     /// </summary>
  17.     public RedisCacheOptions L2Options { get; set; } = new();
  18.    
  19.     /// <summary>
  20.     /// 缓存同步配置
  21.     /// </summary>
  22.     public CacheSyncOptions SyncOptions { get; set; } = new();
  23.    
  24.     /// <summary>
  25.     /// 是否启用L1缓存
  26.     /// </summary>
  27.     public bool EnableL1Cache { get; set; } = true;
  28.    
  29.     /// <summary>
  30.     /// 是否启用L2缓存
  31.     /// </summary>
  32.     public bool EnableL2Cache { get; set; } = true;
  33.    
  34.     /// <summary>
  35.     /// 是否启用缓存同步
  36.     /// </summary>
  37.     public bool EnableCacheSync { get; set; } = true;
  38.    
  39.     /// <summary>
  40.     /// L1缓存与L2缓存的一致性策略
  41.     /// </summary>
  42.     public CacheConsistencyStrategy ConsistencyStrategy { get; set; } = CacheConsistencyStrategy.EventualConsistency;
  43.    
  44.     /// <summary>
  45.     /// L2缓存回写延迟(用于Write-Behind模式)
  46.     /// </summary>
  47.     public TimeSpan L2WriteDelay { get; set; } = TimeSpan.FromSeconds(1);
  48.    
  49.     /// <summary>
  50.     /// 降级策略:L2缓存不可用时的行为
  51.     /// </summary>
  52.     public CacheDegradationStrategy DegradationStrategy { get; set; } = CacheDegradationStrategy.L1Only;
  53.    
  54.     /// <summary>
  55.     /// 健康检查间隔
  56.     /// </summary>
  57.     public TimeSpan HealthCheckInterval { get; set; } = TimeSpan.FromSeconds(30);
  58.    
  59.     /// <summary>
  60.     /// 是否启用性能指标收集
  61.     /// </summary>
  62.     public bool EnableMetrics { get; set; } = true;
  63. }
  64. /// <summary>
  65. /// 缓存一致性策略
  66. /// </summary>
  67. public enum CacheConsistencyStrategy
  68. {
  69.     /// <summary>
  70.     /// 强一致性:所有操作同步到所有层级
  71.     /// </summary>
  72.     StrongConsistency,
  73.    
  74.     /// <summary>
  75.     /// 最终一致性:异步同步,容忍短期不一致
  76.     /// </summary>
  77.     EventualConsistency,
  78.    
  79.     /// <summary>
  80.     /// 会话一致性:同一会话内保证一致性
  81.     /// </summary>
  82.     SessionConsistency
  83. }
  84. /// <summary>
  85. /// 缓存降级策略
  86. /// </summary>
  87. public enum CacheDegradationStrategy
  88. {
  89.     /// <summary>
  90.     /// 仅使用L1缓存
  91.     /// </summary>
  92.     L1Only,
  93.    
  94.     /// <summary>
  95.     /// 直接访问数据源
  96.     /// </summary>
  97.     DirectAccess,
  98.    
  99.     /// <summary>
  100.     /// 抛出异常
  101.     /// </summary>
  102.     ThrowException
  103. }
  104. /// <summary>
  105. /// 缓存操作上下文
  106. /// </summary>
  107. public class CacheOperationContext
  108. {
  109.     public string Key { get; set; }
  110.     public string SessionId { get; set; }
  111.     public bool ForceRefresh { get; set; }
  112.     public TimeSpan? CustomExpiry { get; set; }
  113.     public CacheLevel TargetLevel { get; set; } = CacheLevel.All;
  114.     public Dictionary<string, object> Metadata { get; set; } = new();
  115. }
  116. /// <summary>
  117. /// 缓存级别
  118. /// </summary>
  119. [Flags]
  120. public enum CacheLevel
  121. {
  122.     None = 0,
  123.     L1 = 1,
  124.     L2 = 2,
  125.     All = L1 | L2
  126. }
  127. /// <summary>
  128. /// 缓存操作结果
  129. /// </summary>
  130. public class CacheOperationResult<T>
  131. {
  132.     public T Value { get; set; }
  133.     public bool Success { get; set; }
  134.     public CacheLevel HitLevel { get; set; }
  135.     public TimeSpan Duration { get; set; }
  136.     public string Error { get; set; }
  137.     public CacheStatistics Statistics { get; set; }
  138. }
  139. /// <summary>
  140. /// 多级缓存管理器接口
  141. /// </summary>
  142. public interface IMultiLevelCacheManager
  143. {
  144.     Task<CacheOperationResult<T>> GetAsync<T>(string key, CacheOperationContext context = null);
  145.     Task<CacheOperationResult<T>> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null, CacheOperationContext context = null);
  146.     Task<CacheOperationResult<bool>> SetAsync<T>(string key, T value, TimeSpan? expiry = null, CacheOperationContext context = null);
  147.     Task<CacheOperationResult<bool>> RemoveAsync(string key, CacheOperationContext context = null);
  148.     Task<CacheOperationResult<long>> RemoveByPatternAsync(string pattern, CacheOperationContext context = null);
  149.     Task<CacheOperationResult<bool>> ExistsAsync(string key, CacheLevel level = CacheLevel.All);
  150.     Task<MultiLevelCacheStatistics> GetStatisticsAsync();
  151.     Task<bool> IsHealthyAsync();
  152.     Task ClearAsync(CacheLevel level = CacheLevel.All);
  153. }
  154. /// <summary>
  155. /// 多级缓存统计信息
  156. /// </summary>
  157. public class MultiLevelCacheStatistics
  158. {
  159.     public CacheStatistics L1Statistics { get; set; } = new();
  160.     public CacheStatistics L2Statistics { get; set; } = new();
  161.     public long TotalOperations { get; set; }
  162.     public double OverallHitRatio { get; set; }
  163.     public Dictionary<string, object> PerformanceMetrics { get; set; } = new();
  164.     public DateTime CollectionTime { get; set; } = DateTime.UtcNow;
  165. }
  166. /// <summary>
  167. /// 多级缓存管理器实现
  168. /// </summary>
  169. public class MultiLevelCacheManager : IMultiLevelCacheManager, IDisposable
  170. {
  171.     private readonly IAdvancedMemoryCache _l1Cache;
  172.     private readonly IRedisDistributedCache _l2Cache;
  173.     private readonly ICacheSyncService _syncService;
  174.     private readonly MultiLevelCacheOptions _options;
  175.     private readonly ILogger<MultiLevelCacheManager> _logger;
  176.    
  177.     // 性能计数器 - 线程安全的统计记录
  178.     private readonly CacheStatisticsTracker _statisticsTracker = new();
  179.     private readonly object _statsLock = new object();
  180.    
  181.     // 健康状态监控
  182.     private volatile bool _l2HealthStatus = true;
  183.     private readonly Timer _healthCheckTimer;
  184.    
  185.     // 同步状态管理 - 使用LRU防止内存泄漏
  186.     private readonly LRUCache<string, DateTime> _recentUpdates = new(10000);
  187.    
  188.     // 降级状态
  189.     private volatile bool _isDegraded = false;
  190.     private DateTime _degradationStartTime;
  191.    
  192.     // 资源释放标识
  193.     private bool _disposed = false;
  194.     public MultiLevelCacheManager(
  195.         IAdvancedMemoryCache l1Cache,
  196.         IRedisDistributedCache l2Cache,
  197.         ICacheSyncService syncService,
  198.         IOptions<MultiLevelCacheOptions> options,
  199.         ILogger<MultiLevelCacheManager> logger)
  200.     {
  201.         _l1Cache = l1Cache ?? throw new ArgumentNullException(nameof(l1Cache));
  202.         _l2Cache = l2Cache ?? throw new ArgumentNullException(nameof(l2Cache));
  203.         _syncService = syncService ?? throw new ArgumentNullException(nameof(syncService));
  204.         _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
  205.         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  206.         // 订阅缓存同步事件
  207.         if (_options.EnableCacheSync)
  208.         {
  209.             _ = _syncService.SubscribeAsync(OnCacheSyncEventReceived);
  210.         }
  211.         // 启动健康检查定时器
  212.         _healthCheckTimer = new Timer(PerformHealthCheck, null,
  213.             TimeSpan.Zero, _options.HealthCheckInterval);
  214.         _logger.LogInformation("MultiLevel cache manager initialized with L1: {L1Enabled}, L2: {L2Enabled}, Sync: {SyncEnabled}",
  215.             _options.EnableL1Cache, _options.EnableL2Cache, _options.EnableCacheSync);
  216.     }
  217.     /// <summary>
  218.     /// 异步获取缓存项
  219.     /// </summary>
  220.     public async Task<CacheOperationResult<T>> GetAsync<T>(string key, CacheOperationContext context = null)
  221.     {
  222.         var stopwatch = Stopwatch.StartNew();
  223.         context ??= new CacheOperationContext { Key = key };
  224.         
  225.         _statisticsTracker.RecordOperation();
  226.         try
  227.         {
  228.             // L1缓存查找
  229.             if (_options.EnableL1Cache && (context.TargetLevel & CacheLevel.L1) != 0)
  230.             {
  231.                 var l1Result = await _l1Cache.GetAsync<T>(key);
  232.                 if (l1Result != null)
  233.                 {
  234.                     _statisticsTracker.RecordHit(CacheLevel.L1);
  235.                     _logger.LogDebug("L1 cache hit for key: {Key}", key);
  236.                     
  237.                     return new CacheOperationResult<T>
  238.                     {
  239.                         Value = l1Result,
  240.                         Success = true,
  241.                         HitLevel = CacheLevel.L1,
  242.                         Duration = stopwatch.Elapsed
  243.                     };
  244.                 }
  245.             }
  246.             // L2缓存查找
  247.             if (_options.EnableL2Cache && (context.TargetLevel & CacheLevel.L2) != 0 && _l2HealthStatus)
  248.             {
  249.                 var l2Result = await _l2Cache.GetAsync<T>(key);
  250.                 if (l2Result != null)
  251.                 {
  252.                     _statisticsTracker.RecordHit(CacheLevel.L2);
  253.                     _logger.LogDebug("L2 cache hit for key: {Key}", key);
  254.                     // 将L2结果提升到L1缓存
  255.                     if (_options.EnableL1Cache)
  256.                     {
  257.                         _ = Task.Run(async () =>
  258.                         {
  259.                             try
  260.                             {
  261.                                 await _l1Cache.SetAsync(key, l2Result, context.CustomExpiry);
  262.                                 _logger.LogTrace("Promoted key to L1 cache: {Key}", key);
  263.                             }
  264.                             catch (Exception ex)
  265.                             {
  266.                                 _logger.LogWarning(ex, "Failed to promote key to L1 cache: {Key}", key);
  267.                             }
  268.                         });
  269.                     }
  270.                     return new CacheOperationResult<T>
  271.                     {
  272.                         Value = l2Result,
  273.                         Success = true,
  274.                         HitLevel = CacheLevel.L2,
  275.                         Duration = stopwatch.Elapsed
  276.                     };
  277.                 }
  278.             }
  279.             // 缓存完全未命中
  280.             _statisticsTracker.RecordMiss();
  281.             _logger.LogDebug("Cache miss for key: {Key}", key);
  282.             return new CacheOperationResult<T>
  283.             {
  284.                 Success = false,
  285.                 HitLevel = CacheLevel.None,
  286.                 Duration = stopwatch.Elapsed
  287.             };
  288.         }
  289.         catch (Exception ex)
  290.         {
  291.             _logger.LogError(ex, "Error during cache get operation for key: {Key}", key);
  292.             
  293.             return new CacheOperationResult<T>
  294.             {
  295.                 Success = false,
  296.                 Error = ex.Message,
  297.                 Duration = stopwatch.Elapsed
  298.             };
  299.         }
  300.     }
  301.     /// <summary>
  302.     /// 获取或设置缓存项(Cache-Aside模式)
  303.     /// </summary>
  304.     public async Task<CacheOperationResult<T>> GetOrSetAsync<T>(
  305.         string key,
  306.         Func<Task<T>> factory,
  307.         TimeSpan? expiry = null,
  308.         CacheOperationContext context = null)
  309.     {
  310.         if (factory == null)
  311.             throw new ArgumentNullException(nameof(factory));
  312.         var stopwatch = Stopwatch.StartNew();
  313.         context ??= new CacheOperationContext { Key = key };
  314.         try
  315.         {
  316.             // 如果不强制刷新,先尝试获取缓存
  317.             if (!context.ForceRefresh)
  318.             {
  319.                 var getCacheResult = await GetAsync<T>(key, context);
  320.                 if (getCacheResult.Success)
  321.                 {
  322.                     return getCacheResult;
  323.                 }
  324.             }
  325.             // 使用分布式锁防止缓存击穿
  326.             var lockKey = $"{key}:getorset_lock";
  327.             var lockAcquired = false;
  328.             if (_options.EnableL2Cache && _l2HealthStatus)
  329.             {
  330.                 try
  331.                 {
  332.                     lockAcquired = await _l2Cache.SetIfNotExistsAsync(lockKey, "locked", TimeSpan.FromMinutes(1));
  333.                 }
  334.                 catch (Exception ex)
  335.                 {
  336.                     _logger.LogWarning(ex, "Failed to acquire distributed lock for key: {Key}", key);
  337.                 }
  338.             }
  339.             if (lockAcquired || !_options.EnableL2Cache || !_l2HealthStatus)
  340.             {
  341.                 try
  342.                 {
  343.                     // 再次检查缓存(双重检查锁定)
  344.                     if (!context.ForceRefresh)
  345.                     {
  346.                         var doubleCheckResult = await GetAsync<T>(key, context);
  347.                         if (doubleCheckResult.Success)
  348.                         {
  349.                             return doubleCheckResult;
  350.                         }
  351.                     }
  352.                     // 执行工厂方法
  353.                     _logger.LogDebug("Executing factory method for key: {Key}", key);
  354.                     var value = await factory();
  355.                     // 设置到所有缓存层级
  356.                     var setResult = await SetAsync(key, value, expiry, context);
  357.                     
  358.                     return new CacheOperationResult<T>
  359.                     {
  360.                         Value = value,
  361.                         Success = setResult.Success,
  362.                         HitLevel = CacheLevel.None, // 表示从数据源获取
  363.                         Duration = stopwatch.Elapsed
  364.                     };
  365.                 }
  366.                 finally
  367.                 {
  368.                     // 释放分布式锁
  369.                     if (lockAcquired)
  370.                     {
  371.                         try
  372.                         {
  373.                             await _l2Cache.RemoveAsync(lockKey);
  374.                         }
  375.                         catch (Exception ex)
  376.                         {
  377.                             _logger.LogWarning(ex, "Failed to release distributed lock for key: {Key}", key);
  378.                         }
  379.                     }
  380.                 }
  381.             }
  382.             else
  383.             {
  384.                 // 等待锁释放并重试获取缓存
  385.                 await Task.Delay(Random.Shared.Next(50, 200)); // 随机退避
  386.                 var retryResult = await GetAsync<T>(key, context);
  387.                
  388.                 if (retryResult.Success)
  389.                 {
  390.                     return retryResult;
  391.                 }
  392.                 // 降级:直接执行工厂方法
  393.                 _logger.LogWarning("Failed to acquire lock and cache miss for key: {Key}, executing factory method", key);
  394.                 var fallbackValue = await factory();
  395.                
  396.                 // 尝试异步设置缓存
  397.                 _ = Task.Run(async () =>
  398.                 {
  399.                     try
  400.                     {
  401.                         await SetAsync(key, fallbackValue, expiry, context);
  402.                     }
  403.                     catch (Exception ex)
  404.                     {
  405.                         _logger.LogWarning(ex, "Failed to set cache in fallback scenario for key: {Key}", key);
  406.                     }
  407.                 });
  408.                 return new CacheOperationResult<T>
  409.                 {
  410.                     Value = fallbackValue,
  411.                     Success = true,
  412.                     HitLevel = CacheLevel.None,
  413.                     Duration = stopwatch.Elapsed
  414.                 };
  415.             }
  416.         }
  417.         catch (Exception ex)
  418.         {
  419.             _logger.LogError(ex, "Error in GetOrSetAsync for key: {Key}", key);
  420.             
  421.             // 最终降级:直接执行工厂方法
  422.             try
  423.             {
  424.                 var fallbackValue = await factory();
  425.                 return new CacheOperationResult<T>
  426.                 {
  427.                     Value = fallbackValue,
  428.                     Success = true,
  429.                     HitLevel = CacheLevel.None,
  430.                     Duration = stopwatch.Elapsed,
  431.                     Error = $"Cache operation failed, used fallback: {ex.Message}"
  432.                 };
  433.             }
  434.             catch (Exception factoryEx)
  435.             {
  436.                 _logger.LogError(factoryEx, "Factory method also failed for key: {Key}", key);
  437.                 return new CacheOperationResult<T>
  438.                 {
  439.                     Success = false,
  440.                     Error = $"Both cache and factory failed: {ex.Message}, {factoryEx.Message}",
  441.                     Duration = stopwatch.Elapsed
  442.                 };
  443.             }
  444.         }
  445.     }
  446.     /// <summary>
  447.     /// 异步设置缓存项
  448.     /// </summary>
  449.     public async Task<CacheOperationResult<bool>> SetAsync<T>(
  450.         string key,
  451.         T value,
  452.         TimeSpan? expiry = null,
  453.         CacheOperationContext context = null)
  454.     {
  455.         var stopwatch = Stopwatch.StartNew();
  456.         context ??= new CacheOperationContext { Key = key };
  457.         
  458.         var results = new List<bool>();
  459.         var errors = new List<string>();
  460.         try
  461.         {
  462.             // 记录更新时间(用于同步控制)
  463.             _recentUpdates.Add(key, DateTime.UtcNow);
  464.             // 根据一致性策略决定同步还是异步设置
  465.             if (_options.ConsistencyStrategy == CacheConsistencyStrategy.StrongConsistency)
  466.             {
  467.                 // 强一致性:同步设置所有层级
  468.                 await SetAllLevelsAsync();
  469.             }
  470.             else
  471.             {
  472.                 // 最终一致性:异步设置非关键层级
  473.                 await SetCriticalLevelAsync();
  474.                 _ = Task.Run(SetNonCriticalLevelsAsync);
  475.             }
  476.             // 发送同步事件
  477.             if (_options.EnableCacheSync)
  478.             {
  479.                 var syncEvent = new CacheSyncEvent
  480.                 {
  481.                     EventType = CacheSyncEventType.Set,
  482.                     Key = key,
  483.                     Timestamp = DateTime.UtcNow
  484.                 };
  485.                 _ = Task.Run(async () =>
  486.                 {
  487.                     try
  488.                     {
  489.                         await _syncService.PublishAsync(syncEvent);
  490.                     }
  491.                     catch (Exception ex)
  492.                     {
  493.                         _logger.LogWarning(ex, "Failed to publish sync event for key: {Key}", key);
  494.                     }
  495.                 });
  496.             }
  497.             var success = results.Count > 0 && results.Any(r => r);
  498.             
  499.             return new CacheOperationResult<bool>
  500.             {
  501.                 Value = success,
  502.                 Success = success,
  503.                 Duration = stopwatch.Elapsed,
  504.                 Error = errors.Count > 0 ? string.Join("; ", errors) : null
  505.             };
  506.         }
  507.         catch (Exception ex)
  508.         {
  509.             _logger.LogError(ex, "Error setting cache for key: {Key}", key);
  510.             
  511.             return new CacheOperationResult<bool>
  512.             {
  513.                 Success = false,
  514.                 Error = ex.Message,
  515.                 Duration = stopwatch.Elapsed
  516.             };
  517.         }
  518.         // 本地方法:设置所有层级(同步)
  519.         async Task SetAllLevelsAsync()
  520.         {
  521.             var tasks = new List<Task<bool>>();
  522.             if (_options.EnableL1Cache && (context.TargetLevel & CacheLevel.L1) != 0)
  523.             {
  524.                 tasks.Add(SetL1CacheAsync());
  525.             }
  526.             if (_options.EnableL2Cache && (context.TargetLevel & CacheLevel.L2) != 0 && _l2HealthStatus)
  527.             {
  528.                 tasks.Add(SetL2CacheAsync());
  529.             }
  530.             var taskResults = await Task.WhenAll(tasks);
  531.             results.AddRange(taskResults);
  532.         }
  533.         // 本地方法:设置关键层级(通常是L1)
  534.         async Task SetCriticalLevelAsync()
  535.         {
  536.             if (_options.EnableL1Cache && (context.TargetLevel & CacheLevel.L1) != 0)
  537.             {
  538.                 var result = await SetL1CacheAsync();
  539.                 results.Add(result);
  540.             }
  541.         }
  542.         // 本地方法:异步设置非关键层级(通常是L2)
  543.         async Task SetNonCriticalLevelsAsync()
  544.         {
  545.             if (_options.EnableL2Cache && (context.TargetLevel & CacheLevel.L2) != 0 && _l2HealthStatus)
  546.             {
  547.                 try
  548.                 {
  549.                     await Task.Delay(_options.L2WriteDelay); // 可选的写延迟
  550.                     await SetL2CacheAsync();
  551.                 }
  552.                 catch (Exception ex)
  553.                 {
  554.                     _logger.LogWarning(ex, "Failed to set L2 cache for key: {Key}", key);
  555.                 }
  556.             }
  557.         }
  558.         // 本地方法:设置L1缓存
  559.         async Task<bool> SetL1CacheAsync()
  560.         {
  561.             try
  562.             {
  563.                 await _l1Cache.SetAsync(key, value, expiry ?? context.CustomExpiry);
  564.                 _logger.LogTrace("Set L1 cache for key: {Key}", key);
  565.                 return true;
  566.             }
  567.             catch (Exception ex)
  568.             {
  569.                 var error = $"L1 set failed: {ex.Message}";
  570.                 errors.Add(error);
  571.                 _logger.LogWarning(ex, "Failed to set L1 cache for key: {Key}", key);
  572.                 return false;
  573.             }
  574.         }
  575.         // 本地方法:设置L2缓存
  576.         async Task<bool> SetL2CacheAsync()
  577.         {
  578.             try
  579.             {
  580.                 await _l2Cache.SetAsync(key, value, expiry ?? context.CustomExpiry);
  581.                 _logger.LogTrace("Set L2 cache for key: {Key}", key);
  582.                 return true;
  583.             }
  584.             catch (Exception ex)
  585.             {
  586.                 var error = $"L2 set failed: {ex.Message}";
  587.                 errors.Add(error);
  588.                 _logger.LogWarning(ex, "Failed to set L2 cache for key: {Key}", key);
  589.                
  590.                 // L2缓存失败时标记不健康
  591.                 _l2HealthStatus = false;
  592.                 return false;
  593.             }
  594.         }
  595.     }
  596.     /// <summary>
  597.     /// 异步移除缓存项
  598.     /// </summary>
  599.     public async Task<CacheOperationResult<bool>> RemoveAsync(string key, CacheOperationContext context = null)
  600.     {
  601.         var stopwatch = Stopwatch.StartNew();
  602.         context ??= new CacheOperationContext { Key = key };
  603.         var results = new List<bool>();
  604.         var errors = new List<string>();
  605.         try
  606.         {
  607.             // 并行移除所有层级
  608.             var tasks = new List<Task<bool>>();
  609.             if (_options.EnableL1Cache && (context.TargetLevel & CacheLevel.L1) != 0)
  610.             {
  611.                 tasks.Add(RemoveL1CacheAsync());
  612.             }
  613.             if (_options.EnableL2Cache && (context.TargetLevel & CacheLevel.L2) != 0 && _l2HealthStatus)
  614.             {
  615.                 tasks.Add(RemoveL2CacheAsync());
  616.             }
  617.             if (tasks.Count > 0)
  618.             {
  619.                 var taskResults = await Task.WhenAll(tasks);
  620.                 results.AddRange(taskResults);
  621.             }
  622.             // 发送同步事件
  623.             if (_options.EnableCacheSync)
  624.             {
  625.                 var syncEvent = new CacheSyncEvent
  626.                 {
  627.                     EventType = CacheSyncEventType.Remove,
  628.                     Key = key,
  629.                     Timestamp = DateTime.UtcNow
  630.                 };
  631.                 _ = Task.Run(async () =>
  632.                 {
  633.                     try
  634.                     {
  635.                         await _syncService.PublishAsync(syncEvent);
  636.                     }
  637.                     catch (Exception ex)
  638.                     {
  639.                         _logger.LogWarning(ex, "Failed to publish sync event for key: {Key}", key);
  640.                     }
  641.                 });
  642.             }
  643.             // 清理更新记录
  644.             _recentUpdates.Remove(key);
  645.             var success = results.Count > 0 && results.Any(r => r);
  646.             
  647.             return new CacheOperationResult<bool>
  648.             {
  649.                 Value = success,
  650.                 Success = true, // 移除操作总是被认为是成功的
  651.                 Duration = stopwatch.Elapsed,
  652.                 Error = errors.Count > 0 ? string.Join("; ", errors) : null
  653.             };
  654.         }
  655.         catch (Exception ex)
  656.         {
  657.             _logger.LogError(ex, "Error removing cache for key: {Key}", key);
  658.             
  659.             return new CacheOperationResult<bool>
  660.             {
  661.                 Success = false,
  662.                 Error = ex.Message,
  663.                 Duration = stopwatch.Elapsed
  664.             };
  665.         }
  666.         // 本地方法:移除L1缓存
  667.         async Task<bool> RemoveL1CacheAsync()
  668.         {
  669.             try
  670.             {
  671.                 await _l1Cache.RemoveAsync(key);
  672.                 _logger.LogTrace("Removed L1 cache for key: {Key}", key);
  673.                 return true;
  674.             }
  675.             catch (Exception ex)
  676.             {
  677.                 var error = $"L1 remove failed: {ex.Message}";
  678.                 errors.Add(error);
  679.                 _logger.LogWarning(ex, "Failed to remove L1 cache for key: {Key}", key);
  680.                 return false;
  681.             }
  682.         }
  683.         // 本地方法:移除L2缓存
  684.         async Task<bool> RemoveL2CacheAsync()
  685.         {
  686.             try
  687.             {
  688.                 var result = await _l2Cache.RemoveAsync(key);
  689.                 _logger.LogTrace("Removed L2 cache for key: {Key}, success: {Success}", key, result);
  690.                 return result;
  691.             }
  692.             catch (Exception ex)
  693.             {
  694.                 var error = $"L2 remove failed: {ex.Message}";
  695.                 errors.Add(error);
  696.                 _logger.LogWarning(ex, "Failed to remove L2 cache for key: {Key}", key);
  697.                 return false;
  698.             }
  699.         }
  700.     }
  701.     /// <summary>
  702.     /// 根据模式批量移除缓存项
  703.     /// </summary>
  704.     public async Task<CacheOperationResult<long>> RemoveByPatternAsync(string pattern, CacheOperationContext context = null)
  705.     {
  706.         var stopwatch = Stopwatch.StartNew();
  707.         context ??= new CacheOperationContext();
  708.         long totalRemoved = 0;
  709.         var errors = new List<string>();
  710.         try
  711.         {
  712.             // L1缓存模式删除
  713.             if (_options.EnableL1Cache && (context.TargetLevel & CacheLevel.L1) != 0)
  714.             {
  715.                 try
  716.                 {
  717.                     await _l1Cache.RemoveByPatternAsync(pattern);
  718.                     _logger.LogDebug("Removed L1 cache entries by pattern: {Pattern}", pattern);
  719.                 }
  720.                 catch (Exception ex)
  721.                 {
  722.                     errors.Add($"L1 pattern remove failed: {ex.Message}");
  723.                     _logger.LogWarning(ex, "Failed to remove L1 cache by pattern: {Pattern}", pattern);
  724.                 }
  725.             }
  726.             // L2缓存模式删除
  727.             if (_options.EnableL2Cache && (context.TargetLevel & CacheLevel.L2) != 0 && _l2HealthStatus)
  728.             {
  729.                 try
  730.                 {
  731.                     var removedCount = await _l2Cache.RemoveByPatternAsync(pattern);
  732.                     totalRemoved += removedCount;
  733.                     _logger.LogDebug("Removed {Count} L2 cache entries by pattern: {Pattern}", removedCount, pattern);
  734.                 }
  735.                 catch (Exception ex)
  736.                 {
  737.                     errors.Add($"L2 pattern remove failed: {ex.Message}");
  738.                     _logger.LogWarning(ex, "Failed to remove L2 cache by pattern: {Pattern}", pattern);
  739.                 }
  740.             }
  741.             // 发送同步事件
  742.             if (_options.EnableCacheSync)
  743.             {
  744.                 var syncEvent = new CacheSyncEvent
  745.                 {
  746.                     EventType = CacheSyncEventType.RemovePattern,
  747.                     Pattern = pattern,
  748.                     Timestamp = DateTime.UtcNow
  749.                 };
  750.                 _ = Task.Run(async () =>
  751.                 {
  752.                     try
  753.                     {
  754.                         await _syncService.PublishAsync(syncEvent);
  755.                     }
  756.                     catch (Exception ex)
  757.                     {
  758.                         _logger.LogWarning(ex, "Failed to publish sync event for pattern: {Pattern}", pattern);
  759.                     }
  760.                 });
  761.             }
  762.             return new CacheOperationResult<long>
  763.             {
  764.                 Value = totalRemoved,
  765.                 Success = true,
  766.                 Duration = stopwatch.Elapsed,
  767.                 Error = errors.Count > 0 ? string.Join("; ", errors) : null
  768.             };
  769.         }
  770.         catch (Exception ex)
  771.         {
  772.             _logger.LogError(ex, "Error removing cache by pattern: {Pattern}", pattern);
  773.             
  774.             return new CacheOperationResult<long>
  775.             {
  776.                 Success = false,
  777.                 Error = ex.Message,
  778.                 Duration = stopwatch.Elapsed
  779.             };
  780.         }
  781.     }
  782.     /// <summary>
  783.     /// 检查缓存项是否存在
  784.     /// </summary>
  785.     public async Task<CacheOperationResult<bool>> ExistsAsync(string key, CacheLevel level = CacheLevel.All)
  786.     {
  787.         var stopwatch = Stopwatch.StartNew();
  788.         try
  789.         {
  790.             // 检查L1缓存
  791.             if (_options.EnableL1Cache && (level & CacheLevel.L1) != 0)
  792.             {
  793.                 var l1Result = await _l1Cache.GetAsync<object>(key);
  794.                 if (l1Result != null)
  795.                 {
  796.                     return new CacheOperationResult<bool>
  797.                     {
  798.                         Value = true,
  799.                         Success = true,
  800.                         HitLevel = CacheLevel.L1,
  801.                         Duration = stopwatch.Elapsed
  802.                     };
  803.                 }
  804.             }
  805.             // 检查L2缓存
  806.             if (_options.EnableL2Cache && (level & CacheLevel.L2) != 0 && _l2HealthStatus)
  807.             {
  808.                 var l2Exists = await _l2Cache.ExistsAsync(key);
  809.                 if (l2Exists)
  810.                 {
  811.                     return new CacheOperationResult<bool>
  812.                     {
  813.                         Value = true,
  814.                         Success = true,
  815.                         HitLevel = CacheLevel.L2,
  816.                         Duration = stopwatch.Elapsed
  817.                     };
  818.                 }
  819.             }
  820.             return new CacheOperationResult<bool>
  821.             {
  822.                 Value = false,
  823.                 Success = true,
  824.                 HitLevel = CacheLevel.None,
  825.                 Duration = stopwatch.Elapsed
  826.             };
  827.         }
  828.         catch (Exception ex)
  829.         {
  830.             _logger.LogError(ex, "Error checking cache existence for key: {Key}", key);
  831.             
  832.             return new CacheOperationResult<bool>
  833.             {
  834.                 Success = false,
  835.                 Error = ex.Message,
  836.                 Duration = stopwatch.Elapsed
  837.             };
  838.         }
  839.     }
  840.     /// <summary>
  841.     /// 获取统计信息
  842.     /// </summary>
  843.     public async Task<MultiLevelCacheStatistics> GetStatisticsAsync()
  844.     {
  845.         try
  846.         {
  847.             var l1Stats = _l1Cache.GetStatistics();
  848.             var l2Stats = new CacheStatistics(); // Redis缓存统计需要自定义实现
  849.             var totalOperations = Interlocked.Read(ref _totalOperations);
  850.             var totalHits = Interlocked.Read(ref _l1Hits) + Interlocked.Read(ref _l2Hits);
  851.             var totalMisses = Interlocked.Read(ref _totalMisses);
  852.             return new MultiLevelCacheStatistics
  853.             {
  854.                 L1Statistics = l1Stats,
  855.                 L2Statistics = l2Stats,
  856.                 TotalOperations = totalOperations,
  857.                 OverallHitRatio = totalOperations == 0 ? 0 : (double)totalHits / totalOperations,
  858.                 PerformanceMetrics = new Dictionary<string, object>
  859.                 {
  860.                     ["L1HitRatio"] = stats.L1HitRatio,
  861.                     ["L2HitRatio"] = stats.L2HitRatio,
  862.                     ["L2HealthStatus"] = _l2HealthStatus,
  863.                     ["IsDegraded"] = _isDegraded,
  864.                     ["DegradationDuration"] = _isDegraded ? DateTime.UtcNow - _degradationStartTime : TimeSpan.Zero
  865.                 }
  866.             };
  867.         }
  868.         catch (Exception ex)
  869.         {
  870.             _logger.LogError(ex, "Error getting cache statistics");
  871.             return new MultiLevelCacheStatistics();
  872.         }
  873.     }
  874.     /// <summary>
  875.     /// 检查缓存服务健康状态
  876.     /// </summary>
  877.     public async Task<bool> IsHealthyAsync()
  878.     {
  879.         try
  880.         {
  881.             var l1Healthy = true; // 内存缓存通常总是健康的
  882.             var l2Healthy = true;
  883.             var syncHealthy = true;
  884.             // 检查L2缓存健康状态
  885.             if (_options.EnableL2Cache)
  886.             {
  887.                 try
  888.                 {
  889.                     // 简单的ping测试
  890.                     await _l2Cache.SetAsync("health_check", "ok", TimeSpan.FromSeconds(10));
  891.                     l2Healthy = await _l2Cache.ExistsAsync("health_check");
  892.                     await _l2Cache.RemoveAsync("health_check");
  893.                 }
  894.                 catch
  895.                 {
  896.                     l2Healthy = false;
  897.                 }
  898.             }
  899.             // 检查同步服务健康状态
  900.             if (_options.EnableCacheSync)
  901.             {
  902.                 syncHealthy = _syncService.IsHealthy;
  903.             }
  904.             var overallHealthy = l1Healthy && (!_options.EnableL2Cache || l2Healthy) && (!_options.EnableCacheSync || syncHealthy);
  905.             
  906.             // 更新降级状态
  907.             if (!overallHealthy && !_isDegraded)
  908.             {
  909.                 _isDegraded = true;
  910.                 _degradationStartTime = DateTime.UtcNow;
  911.                 _logger.LogWarning("Cache service entered degraded mode");
  912.             }
  913.             else if (overallHealthy && _isDegraded)
  914.             {
  915.                 _isDegraded = false;
  916.                 _logger.LogInformation("Cache service recovered from degraded mode after {Duration}",
  917.                     DateTime.UtcNow - _degradationStartTime);
  918.             }
  919.             return overallHealthy;
  920.         }
  921.         catch (Exception ex)
  922.         {
  923.             _logger.LogError(ex, "Error checking cache health");
  924.             return false;
  925.         }
  926.     }
  927.     /// <summary>
  928.     /// 清空缓存
  929.     /// </summary>
  930.     public async Task ClearAsync(CacheLevel level = CacheLevel.All)
  931.     {
  932.         try
  933.         {
  934.             var tasks = new List<Task>();
  935.             // 清空L1缓存(通过模式删除)
  936.             if (_options.EnableL1Cache && (level & CacheLevel.L1) != 0)
  937.             {
  938.                 tasks.Add(Task.Run(async () =>
  939.                 {
  940.                     try
  941.                     {
  942.                         await _l1Cache.RemoveByPatternAsync("*");
  943.                         _logger.LogInformation("Cleared L1 cache");
  944.                     }
  945.                     catch (Exception ex)
  946.                     {
  947.                         _logger.LogError(ex, "Failed to clear L1 cache");
  948.                     }
  949.                 }));
  950.             }
  951.             // 清空L2缓存
  952.             if (_options.EnableL2Cache && (level & CacheLevel.L2) != 0 && _l2HealthStatus)
  953.             {
  954.                 tasks.Add(Task.Run(async () =>
  955.                 {
  956.                     try
  957.                     {
  958.                         await _l2Cache.RemoveByPatternAsync("*");
  959.                         _logger.LogInformation("Cleared L2 cache");
  960.                     }
  961.                     catch (Exception ex)
  962.                     {
  963.                         _logger.LogError(ex, "Failed to clear L2 cache");
  964.                     }
  965.                 }));
  966.             }
  967.             await Task.WhenAll(tasks);
  968.             // 发送清空同步事件
  969.             if (_options.EnableCacheSync)
  970.             {
  971.                 var syncEvent = new CacheSyncEvent
  972.                 {
  973.                     EventType = CacheSyncEventType.Clear,
  974.                     Timestamp = DateTime.UtcNow
  975.                 };
  976.                 _ = Task.Run(async () =>
  977.                 {
  978.                     try
  979.                     {
  980.                         await _syncService.PublishAsync(syncEvent);
  981.                     }
  982.                     catch (Exception ex)
  983.                     {
  984.                         _logger.LogWarning(ex, "Failed to publish clear sync event");
  985.                     }
  986.                 });
  987.             }
  988.             // 重置统计计数器
  989.             _statisticsTracker.Reset();
  990.             // 清空更新记录
  991.             _recentUpdates.Clear();
  992.         }
  993.         catch (Exception ex)
  994.         {
  995.             _logger.LogError(ex, "Error clearing cache");
  996.             throw;
  997.         }
  998.     }
  999.     #region 私有方法
  1000.     /// <summary>
  1001.     /// 处理接收到的缓存同步事件
  1002.     /// </summary>
  1003.     /// <param name="syncEvent">同步事件</param>
  1004.     private async Task OnCacheSyncEventReceived(CacheSyncEvent syncEvent)
  1005.     {
  1006.         try
  1007.         {
  1008.             _logger.LogDebug("Received sync event: {EventType} for key: {Key}", syncEvent.EventType, syncEvent.Key);
  1009.             // 检查是否为最近的本地更新,避免循环同步
  1010.             if (!string.IsNullOrEmpty(syncEvent.Key) &&
  1011.                 _recentUpdates.TryGet(syncEvent.Key, out var updateTime) &&
  1012.                 (DateTime.UtcNow - updateTime).TotalSeconds < 5)
  1013.             {
  1014.                 _logger.LogTrace("Skipping sync for recent local update: {Key}", syncEvent.Key);
  1015.                 return;
  1016.             }
  1017.             switch (syncEvent.EventType)
  1018.             {
  1019.                 case CacheSyncEventType.Remove:
  1020.                     await _l1Cache.RemoveAsync(syncEvent.Key);
  1021.                     break;
  1022.                 case CacheSyncEventType.RemovePattern:
  1023.                     await _l1Cache.RemoveByPatternAsync(syncEvent.Pattern);
  1024.                     break;
  1025.                 case CacheSyncEventType.Clear:
  1026.                     await _l1Cache.RemoveByPatternAsync("*");
  1027.                     break;
  1028.                 case CacheSyncEventType.Expire:
  1029.                 case CacheSyncEventType.Set:
  1030.                     // 对于设置操作,直接删除L1缓存项,让下次访问时从L2缓存重新加载
  1031.                     await _l1Cache.RemoveAsync(syncEvent.Key);
  1032.                     break;
  1033.             }
  1034.             _logger.LogTrace("Processed sync event: {EventType} for key: {Key}", syncEvent.EventType, syncEvent.Key);
  1035.         }
  1036.         catch (Exception ex)
  1037.         {
  1038.             _logger.LogError(ex, "Error processing sync event: {EventType} for key: {Key}",
  1039.                 syncEvent.EventType, syncEvent.Key);
  1040.         }
  1041.     }
  1042.     /// <summary>
  1043.     /// 执行定期健康检查
  1044.     /// </summary>
  1045.     /// <param name="state">定时器状态</param>
  1046.     private async void PerformHealthCheck(object state)
  1047.     {
  1048.         try
  1049.         {
  1050.             var previousL2Status = _l2HealthStatus;
  1051.             
  1052.             // 更新L2缓存健康状态
  1053.             if (_options.EnableL2Cache)
  1054.             {
  1055.                 try
  1056.                 {
  1057.                     var testKey = $"health_check_{Guid.NewGuid():N}";
  1058.                     await _l2Cache.SetAsync(testKey, "test", TimeSpan.FromSeconds(5));
  1059.                     _l2HealthStatus = await _l2Cache.ExistsAsync(testKey);
  1060.                     await _l2Cache.RemoveAsync(testKey);
  1061.                 }
  1062.                 catch (Exception ex)
  1063.                 {
  1064.                     _l2HealthStatus = false;
  1065.                     _logger.LogWarning(ex, "L2 cache health check failed");
  1066.                 }
  1067.             }
  1068.             // 记录状态变化
  1069.             if (previousL2Status != _l2HealthStatus)
  1070.             {
  1071.                 if (_l2HealthStatus)
  1072.                 {
  1073.                     _logger.LogInformation("L2 cache health recovered");
  1074.                 }
  1075.                 else
  1076.                 {
  1077.                     _logger.LogWarning("L2 cache health degraded");
  1078.                 }
  1079.             }
  1080.             // 清理过期的更新记录
  1081.             var cutoffTime = DateTime.UtcNow.AddMinutes(-5);
  1082.             var expiredKeys = _recentUpdates
  1083.                 .Where(kvp => kvp.Value < cutoffTime)
  1084.                 .Select(kvp => kvp.Key)
  1085.                 .ToList();
  1086.             // LRU缓存已经处理了过期清理,这里不再需要手动操作
  1087.         }
  1088.         catch (Exception ex)
  1089.         {
  1090.             _logger.LogError(ex, "Error in health check");
  1091.         }
  1092.     }
  1093.     #endregion
  1094.     /// <summary>
  1095.     /// 释放资源
  1096.     /// </summary>
  1097.     public void Dispose()
  1098.     {
  1099.         if (!_disposed)
  1100.         {
  1101.             _healthCheckTimer?.Dispose();
  1102.             _syncService?.Dispose();
  1103.             _disposed = true;
  1104.         }
  1105.     }
  1106. }
复制代码
7. 最佳实践和性能优化

7.1 缓存设计最佳实践

7.1.1 缓存键设计原则

分层命名规范
  1. // 推荐的键命名模式
  2. public static class CacheKeyPatterns
  3. {
  4.     // 基础模式:{应用名}:{业务域}:{实体}:{标识符}
  5.     public const string UserProfile = "myapp:user:profile:{0}";
  6.     public const string UserPermissions = "myapp:user:permissions:{0}";
  7.     public const string ProductList = "myapp:product:list:page:{0}:size:{1}";
  8.    
  9.     // 会话相关:{应用名}:{业务域}:session:{会话ID}:{实体}
  10.     public const string UserSession = "myapp:user:session:{0}:settings";
  11.    
  12.     // 临时数据:{应用名}:temp:{业务场景}:{标识符}
  13.     public const string TempData = "myapp:temp:upload:{0}";
  14.    
  15.     // 配置数据:{应用名}:config:{配置类型}
  16.     public const string SystemConfig = "myapp:config:system";
  17.    
  18.     // 统计数据:{应用名}:stats:{时间维度}:{标识符}
  19.     public const string DailyStats = "myapp:stats:daily:{0:yyyyMMdd}";
  20. }
  21. /// <summary>
  22. /// 缓存键构建器
  23. /// </summary>
  24. public class CacheKeyBuilder
  25. {
  26.     private readonly string _applicationName;
  27.     private readonly List<string> _segments;
  28.     public CacheKeyBuilder(string applicationName)
  29.     {
  30.         _applicationName = applicationName ?? throw new ArgumentNullException(nameof(applicationName));
  31.         _segments = new List<string> { _applicationName };
  32.     }
  33.     public CacheKeyBuilder Domain(string domain)
  34.     {
  35.         _segments.Add(domain);
  36.         return this;
  37.     }
  38.     public CacheKeyBuilder Entity(string entity)
  39.     {
  40.         _segments.Add(entity);
  41.         return this;
  42.     }
  43.     public CacheKeyBuilder Id(object id)
  44.     {
  45.         _segments.Add(id?.ToString() ?? "null");
  46.         return this;
  47.     }
  48.     public CacheKeyBuilder Attribute(string attribute)
  49.     {
  50.         _segments.Add(attribute);
  51.         return this;
  52.     }
  53.     public CacheKeyBuilder Session(string sessionId)
  54.     {
  55.         _segments.Add("session");
  56.         _segments.Add(sessionId);
  57.         return this;
  58.     }
  59.     public CacheKeyBuilder WithParameters(params object[] parameters)
  60.     {
  61.         foreach (var param in parameters)
  62.         {
  63.             _segments.Add(param?.ToString() ?? "null");
  64.         }
  65.         return this;
  66.     }
  67.     public string Build()
  68.     {
  69.         return string.Join(":", _segments);
  70.     }
  71.     public override string ToString() => Build();
  72. }
复制代码
7.1.2 过期策略优化

智能过期时间计算
  1. /// <summary>
  2. /// 智能过期策略
  3. /// </summary>
  4. public class SmartExpirationStrategy
  5. {
  6.     private readonly ILogger<SmartExpirationStrategy> _logger;
  7.     private readonly Random _random = new();
  8.     public SmartExpirationStrategy(ILogger<SmartExpirationStrategy> logger)
  9.     {
  10.         _logger = logger;
  11.     }
  12.     /// <summary>
  13.     /// 根据数据类型和访问模式计算过期时间
  14.     /// </summary>
  15.     /// <param name="dataType">数据类型</param>
  16.     /// <param name="accessFrequency">访问频率</param>
  17.     /// <param name="dataVolatility">数据变化频率</param>
  18.     /// <param name="businessCritical">是否业务关键</param>
  19.     /// <returns>推荐的过期时间</returns>
  20.     public TimeSpan CalculateExpiry(
  21.         CacheDataType dataType,
  22.         AccessFrequency accessFrequency,
  23.         DataVolatility dataVolatility,
  24.         bool businessCritical = false)
  25.     {
  26.         // 基础过期时间
  27.         var baseExpiry = dataType switch
  28.         {
  29.             CacheDataType.UserProfile => TimeSpan.FromHours(4),
  30.             CacheDataType.SystemConfiguration => TimeSpan.FromHours(12),
  31.             CacheDataType.ProductCatalog => TimeSpan.FromHours(2),
  32.             CacheDataType.UserPermissions => TimeSpan.FromHours(1),
  33.             CacheDataType.SessionData => TimeSpan.FromMinutes(30),
  34.             CacheDataType.TemporaryData => TimeSpan.FromMinutes(5),
  35.             CacheDataType.StatisticsData => TimeSpan.FromMinutes(15),
  36.             _ => TimeSpan.FromHours(1)
  37.         };
  38.         // 根据访问频率调整
  39.         var frequencyMultiplier = accessFrequency switch
  40.         {
  41.             AccessFrequency.VeryHigh => 2.0,
  42.             AccessFrequency.High => 1.5,
  43.             AccessFrequency.Medium => 1.0,
  44.             AccessFrequency.Low => 0.7,
  45.             AccessFrequency.VeryLow => 0.5,
  46.             _ => 1.0
  47.         };
  48.         // 根据数据变化频率调整
  49.         var volatilityMultiplier = dataVolatility switch
  50.         {
  51.             DataVolatility.VeryHigh => 0.3,
  52.             DataVolatility.High => 0.5,
  53.             DataVolatility.Medium => 0.8,
  54.             DataVolatility.Low => 1.2,
  55.             DataVolatility.VeryLow => 1.5,
  56.             _ => 1.0
  57.         };
  58.         // 业务关键数据缩短过期时间以确保一致性
  59.         var criticalMultiplier = businessCritical ? 0.8 : 1.0;
  60.         // 计算最终过期时间
  61.         var finalExpiry = TimeSpan.FromMilliseconds(
  62.             baseExpiry.TotalMilliseconds *
  63.             frequencyMultiplier *
  64.             volatilityMultiplier *
  65.             criticalMultiplier);
  66.         // 添加随机偏移防止缓存雪崩(±10%)
  67.         var jitterPercentage = _random.NextDouble() * 0.2 - 0.1; // -10% to +10%
  68.         finalExpiry = TimeSpan.FromMilliseconds(
  69.             finalExpiry.TotalMilliseconds * (1 + jitterPercentage));
  70.         // 确保最小和最大边界
  71.         var minExpiry = TimeSpan.FromMinutes(1);
  72.         var maxExpiry = TimeSpan.FromDays(1);
  73.         if (finalExpiry < minExpiry) finalExpiry = minExpiry;
  74.         if (finalExpiry > maxExpiry) finalExpiry = maxExpiry;
  75.         _logger.LogDebug("Calculated expiry for {DataType}: {Expiry} " +
  76.             "(base: {BaseExpiry}, freq: {FreqMultiplier:F1}x, vol: {VolMultiplier:F1}x, critical: {CriticalMultiplier:F1}x)",
  77.             dataType, finalExpiry, baseExpiry, frequencyMultiplier, volatilityMultiplier, criticalMultiplier);
  78.         return finalExpiry;
  79.     }
  80. }
  81. public enum CacheDataType
  82. {
  83.     UserProfile,
  84.     SystemConfiguration,
  85.     ProductCatalog,
  86.     UserPermissions,
  87.     SessionData,
  88.     TemporaryData,
  89.     StatisticsData
  90. }
  91. public enum AccessFrequency
  92. {
  93.     VeryLow,
  94.     Low,
  95.     Medium,
  96.     High,
  97.     VeryHigh
  98. }
  99. public enum DataVolatility
  100. {
  101.     VeryLow,    // 几乎不变化,如系统配置
  102.     Low,        // 很少变化,如用户档案
  103.     Medium,     // 定期变化,如产品信息
  104.     High,       // 频繁变化,如库存数据
  105.     VeryHigh    // 实时变化,如在线用户状态
  106. }
复制代码
7.1.3 缓存预热策略
  1. /// <summary>
  2. /// 缓存预热服务
  3. /// </summary>
  4. public interface ICacheWarmupService
  5. {
  6.     Task WarmupAsync(CancellationToken cancellationToken = default);
  7.     Task WarmupSpecificDataAsync(string dataType, CancellationToken cancellationToken = default);
  8. }
  9. /// <summary>
  10. /// 缓存预热服务实现
  11. /// </summary>
  12. public class CacheWarmupService : ICacheWarmupService
  13. {
  14.     private readonly IMultiLevelCacheManager _cacheManager;
  15.     private readonly IServiceProvider _serviceProvider;
  16.     private readonly ILogger<CacheWarmupService> _logger;
  17.     private readonly CacheWarmupOptions _options;
  18.     public CacheWarmupService(
  19.         IMultiLevelCacheManager cacheManager,
  20.         IServiceProvider serviceProvider,
  21.         ILogger<CacheWarmupService> logger,
  22.         IOptions<CacheWarmupOptions> options)
  23.     {
  24.         _cacheManager = cacheManager;
  25.         _serviceProvider = serviceProvider;
  26.         _logger = logger;
  27.         _options = options.Value;
  28.     }
  29.     /// <summary>
  30.     /// 执行完整的缓存预热
  31.     /// </summary>
  32.     public async Task WarmupAsync(CancellationToken cancellationToken = default)
  33.     {
  34.         _logger.LogInformation("Starting cache warmup process");
  35.         var stopwatch = Stopwatch.StartNew();
  36.         try
  37.         {
  38.             var warmupTasks = new List<Task>
  39.             {
  40.                 WarmupSystemConfigurationAsync(cancellationToken),
  41.                 WarmupHotUserDataAsync(cancellationToken),
  42.                 WarmupProductCatalogAsync(cancellationToken),
  43.                 WarmupFrequentlyAccessedDataAsync(cancellationToken)
  44.             };
  45.             await Task.WhenAll(warmupTasks);
  46.             _logger.LogInformation("Cache warmup completed in {Duration:F2}s", stopwatch.Elapsed.TotalSeconds);
  47.         }
  48.         catch (Exception ex)
  49.         {
  50.             _logger.LogError(ex, "Cache warmup failed after {Duration:F2}s", stopwatch.Elapsed.TotalSeconds);
  51.             throw;
  52.         }
  53.     }
  54.     /// <summary>
  55.     /// 预热系统配置数据
  56.     /// </summary>
  57.     private async Task WarmupSystemConfigurationAsync(CancellationToken cancellationToken)
  58.     {
  59.         try
  60.         {
  61.             _logger.LogDebug("Warming up system configuration");
  62.             using var scope = _serviceProvider.CreateScope();
  63.             var configService = scope.ServiceProvider.GetRequiredService<IConfigurationService>();
  64.             var configKeys = new[]
  65.             {
  66.                 "app_settings",
  67.                 "feature_flags",
  68.                 "business_rules",
  69.                 "system_parameters"
  70.             };
  71.             var tasks = configKeys.Select(async key =>
  72.             {
  73.                 var cacheKey = new CacheKeyBuilder("myapp")
  74.                     .Domain("config")
  75.                     .Entity(key)
  76.                     .Build();
  77.                 await _cacheManager.GetOrSetAsync(
  78.                     cacheKey,
  79.                     async () => await configService.GetConfigurationAsync(key),
  80.                     TimeSpan.FromHours(12));
  81.             });
  82.             await Task.WhenAll(tasks);
  83.             _logger.LogDebug("System configuration warmup completed");
  84.         }
  85.         catch (Exception ex)
  86.         {
  87.             _logger.LogWarning(ex, "Failed to warmup system configuration");
  88.         }
  89.     }
  90.     /// <summary>
  91.     /// 预热热点用户数据
  92.     /// </summary>
  93.     private async Task WarmupHotUserDataAsync(CancellationToken cancellationToken)
  94.     {
  95.         try
  96.         {
  97.             _logger.LogDebug("Warming up hot user data");
  98.             using var scope = _serviceProvider.CreateScope();
  99.             var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
  100.             var analyticsService = scope.ServiceProvider.GetRequiredService<IAnalyticsService>();
  101.             // 获取最近活跃用户列表
  102.             var activeUserIds = await analyticsService.GetRecentlyActiveUsersAsync(
  103.                 TimeSpan.FromDays(7),
  104.                 _options.TopUsersToWarmup);
  105.             var semaphore = new SemaphoreSlim(_options.MaxConcurrency);
  106.             var tasks = activeUserIds.Select(async userId =>
  107.             {
  108.                 await semaphore.WaitAsync(cancellationToken);
  109.                 try
  110.                 {
  111.                     // 预热用户基本信息
  112.                     var userCacheKey = new CacheKeyBuilder("myapp")
  113.                         .Domain("user")
  114.                         .Entity("profile")
  115.                         .Id(userId)
  116.                         .Build();
  117.                     await _cacheManager.GetOrSetAsync(
  118.                         userCacheKey,
  119.                         async () => await userService.GetUserByIdAsync(userId),
  120.                         TimeSpan.FromHours(4));
  121.                     // 预热用户权限
  122.                     var permissionsCacheKey = new CacheKeyBuilder("myapp")
  123.                         .Domain("user")
  124.                         .Entity("permissions")
  125.                         .Id(userId)
  126.                         .Build();
  127.                     await _cacheManager.GetOrSetAsync(
  128.                         permissionsCacheKey,
  129.                         async () => await userService.GetUserPermissionsAsync(userId),
  130.                         TimeSpan.FromHours(2));
  131.                 }
  132.                 finally
  133.                 {
  134.                     semaphore.Release();
  135.                 }
  136.             });
  137.             await Task.WhenAll(tasks);
  138.             _logger.LogDebug("Hot user data warmup completed for {Count} users", activeUserIds.Count);
  139.         }
  140.         catch (Exception ex)
  141.         {
  142.             _logger.LogWarning(ex, "Failed to warmup hot user data");
  143.         }
  144.     }
  145.     /// <summary>
  146.     /// 预热产品目录数据
  147.     /// </summary>
  148.     private async Task WarmupProductCatalogAsync(CancellationToken cancellationToken)
  149.     {
  150.         try
  151.         {
  152.             _logger.LogDebug("Warming up product catalog");
  153.             using var scope = _serviceProvider.CreateScope();
  154.             var productService = scope.ServiceProvider.GetRequiredService<IProductService>();
  155.             // 预热热门产品分类
  156.             var popularCategories = await productService.GetPopularCategoriesAsync(_options.TopCategoriesToWarmup);
  157.             
  158.             var tasks = popularCategories.Select(async category =>
  159.             {
  160.                 var cacheKey = new CacheKeyBuilder("myapp")
  161.                     .Domain("product")
  162.                     .Entity("category")
  163.                     .Id(category.Id)
  164.                     .Build();
  165.                 await _cacheManager.GetOrSetAsync(
  166.                     cacheKey,
  167.                     async () => await productService.GetCategoryProductsAsync(category.Id, 1, 20),
  168.                     TimeSpan.FromHours(2));
  169.             });
  170.             await Task.WhenAll(tasks);
  171.             _logger.LogDebug("Product catalog warmup completed for {Count} categories", popularCategories.Count);
  172.         }
  173.         catch (Exception ex)
  174.         {
  175.             _logger.LogWarning(ex, "Failed to warmup product catalog");
  176.         }
  177.     }
  178.     /// <summary>
  179.     /// 预热频繁访问的数据
  180.     /// </summary>
  181.     private async Task WarmupFrequentlyAccessedDataAsync(CancellationToken cancellationToken)
  182.     {
  183.         try
  184.         {
  185.             _logger.LogDebug("Warming up frequently accessed data");
  186.             // 这里可以根据实际的访问日志或分析数据来确定需要预热的内容
  187.             // 示例:预热首页数据、热门搜索结果等
  188.             var commonQueries = new[]
  189.             {
  190.                 ("homepage_banner", TimeSpan.FromHours(6)),
  191.                 ("popular_products", TimeSpan.FromHours(1)),
  192.                 ("trending_categories", TimeSpan.FromMinutes(30)),
  193.                 ("system_announcements", TimeSpan.FromHours(4))
  194.             };
  195.             using var scope = _serviceProvider.CreateScope();
  196.             var contentService = scope.ServiceProvider.GetRequiredService<IContentService>();
  197.             var tasks = commonQueries.Select(async query =>
  198.             {
  199.                 var (queryType, expiry) = query;
  200.                 var cacheKey = new CacheKeyBuilder("myapp")
  201.                     .Domain("content")
  202.                     .Entity(queryType)
  203.                     .Build();
  204.                 await _cacheManager.GetOrSetAsync(
  205.                     cacheKey,
  206.                     async () => await contentService.GetContentAsync(queryType),
  207.                     expiry);
  208.             });
  209.             await Task.WhenAll(tasks);
  210.             _logger.LogDebug("Frequently accessed data warmup completed");
  211.         }
  212.         catch (Exception ex)
  213.         {
  214.             _logger.LogWarning(ex, "Failed to warmup frequently accessed data");
  215.         }
  216.     }
  217.     /// <summary>
  218.     /// 预热特定类型的数据
  219.     /// </summary>
  220.     public async Task WarmupSpecificDataAsync(string dataType, CancellationToken cancellationToken = default)
  221.     {
  222.         _logger.LogInformation("Starting specific cache warmup for data type: {DataType}", dataType);
  223.         try
  224.         {
  225.             switch (dataType.ToLowerInvariant())
  226.             {
  227.                 case "config":
  228.                 case "configuration":
  229.                     await WarmupSystemConfigurationAsync(cancellationToken);
  230.                     break;
  231.                 case "user":
  232.                 case "users":
  233.                     await WarmupHotUserDataAsync(cancellationToken);
  234.                     break;
  235.                 case "product":
  236.                 case "products":
  237.                     await WarmupProductCatalogAsync(cancellationToken);
  238.                     break;
  239.                 case "content":
  240.                     await WarmupFrequentlyAccessedDataAsync(cancellationToken);
  241.                     break;
  242.                 default:
  243.                     _logger.LogWarning("Unknown data type for warmup: {DataType}", dataType);
  244.                     break;
  245.             }
  246.             _logger.LogInformation("Specific cache warmup completed for data type: {DataType}", dataType);
  247.         }
  248.         catch (Exception ex)
  249.         {
  250.             _logger.LogError(ex, "Specific cache warmup failed for data type: {DataType}", dataType);
  251.             throw;
  252.         }
  253.     }
  254. }
  255. /// <summary>
  256. /// 缓存预热配置选项
  257. /// </summary>
  258. public class CacheWarmupOptions
  259. {
  260.     public int TopUsersToWarmup { get; set; } = 1000;
  261.     public int TopCategoriesToWarmup { get; set; } = 50;
  262.     public int MaxConcurrency { get; set; } = Environment.ProcessorCount * 2;
  263.     public bool EnableScheduledWarmup { get; set; } = true;
  264.     public TimeSpan WarmupInterval { get; set; } = TimeSpan.FromHours(6);
  265.     public List<string> WarmupDataTypes { get; set; } = new() { "config", "users", "products", "content" };
  266. }
复制代码
7.4 安全性和可靠性增强

基于深度技术分析的结果,我们对原有架构进行了重要的安全性和可靠性改进:
7.4.1 增强的异常处理机制

我们引入了分层的异常处理体系,将不同类型的缓存异常进行分类处理:
  1. // 细分异常类型,提供更精确的错误处理
  2. public class CacheConnectionException : CacheException { }
  3. public class CacheSerializationException : CacheException { }
  4. public class CacheTimeoutException : CacheException { }
  5. public class CacheValidationException : CacheException { }
  6. // 在缓存操作中使用分层异常处理
  7. try
  8. {
  9.     var result = await factory();
  10.     return result;
  11. }
  12. catch (CacheConnectionException ex)
  13. {
  14.     _logger.LogWarning(ex, "Cache connection failed, using fallback");
  15.     return await factory(); // 优雅降级
  16. }
  17. catch (CacheSerializationException ex)
  18. {
  19.     _logger.LogError(ex, "Serialization failed");
  20.     throw; // 序列化错误需要立即处理
  21. }
复制代码
7.4.2 线程安全的统计系统

原有的统计计数器存在线程安全问题,我们引入了专门的统计追踪器:
  1. public class CacheStatisticsTracker
  2. {
  3.     private long _totalOperations = 0;
  4.     private long _l1Hits = 0;
  5.     private long _l2Hits = 0;
  6.     private long _totalMisses = 0;
  7.     public void RecordOperation() => Interlocked.Increment(ref _totalOperations);
  8.     public void RecordHit(CacheLevel level) { /* 原子操作 */ }
  9.     public CacheStatisticsSnapshot GetSnapshot() { /* 线程安全的快照 */ }
  10. }
复制代码
7.4.3 缓存数据验证和安全机制

为防止缓存投毒和数据安全问题,我们实现了多层验证机制:
  1. public class DefaultCacheDataValidator : ICacheDataValidator
  2. {
  3.     public bool IsValid<T>(T value)
  4.     {
  5.         // 检查禁止类型
  6.         if (_forbiddenTypes.Contains(value.GetType()))
  7.             return false;
  8.         
  9.         // 检查循环引用
  10.         if (HasCircularReference(value))
  11.             return false;
  12.         
  13.         return true;
  14.     }
  15.    
  16.     public void ValidateKey(string key)
  17.     {
  18.         // 验证key格式和长度
  19.         if (!_keyValidationRegex.IsMatch(key))
  20.             throw new CacheValidationException($"Invalid key: {key}");
  21.     }
  22. }
复制代码
7.4.4 智能序列化性能优化

引入多种序列化器支持,根据数据类型自动选择最佳序列化方案:
  1. public class SmartCacheSerializer : ICacheSerializer
  2. {
  3.     private readonly ICacheSerializer[] _serializers = new[]
  4.     {
  5.         new BinaryCacheSerializer(), // 优先使用高性能二进制序列化
  6.         new JsonCacheSerializer()    // 备选JSON序列化
  7.     };
  8.    
  9.     public byte[] Serialize<T>(T value)
  10.     {
  11.         foreach (var serializer in _serializers)
  12.         {
  13.             if (serializer.SupportsType(typeof(T)))
  14.             {
  15.                 return serializer.Serialize(value);
  16.             }
  17.         }
  18.         throw new CacheSerializationException("No suitable serializer found");
  19.     }
  20. }
复制代码
7.4.5 断路器模式实现

实现断路器模式来处理Redis连接故障,提高系统的整体可靠性:
  1. public class CacheCircuitBreaker
  2. {
  3.     private CircuitBreakerState _state = CircuitBreakerState.Closed;
  4.    
  5.     public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation)
  6.     {
  7.         if (!CanExecute())
  8.         {
  9.             throw new CacheException("Circuit breaker is OPEN");
  10.         }
  11.         
  12.         try
  13.         {
  14.             var result = await operation();
  15.             OnSuccess();
  16.             return result;
  17.         }
  18.         catch (Exception ex)
  19.         {
  20.             OnFailure(ex);
  21.             throw;
  22.         }
  23.     }
  24. }
复制代码
7.4.6 LRU内存管理

为防止内存泄漏,我们用LRU缓存替换了原有的ConcurrentDictionary:
  1. public class LRUCache<TKey, TValue>
  2. {
  3.     private readonly int _maxSize;
  4.     private readonly Dictionary<TKey, LinkedListNode<CacheItem<TKey, TValue>>> _cache;
  5.     private readonly LinkedList<CacheItem<TKey, TValue>> _lruList;
  6.    
  7.     public void Add(TKey key, TValue value)
  8.     {
  9.         // 检查容量限制
  10.         if (_cache.Count >= _maxSize)
  11.         {
  12.             // 移除最久未使用的项
  13.             var lastNode = _lruList.Last;
  14.             _cache.Remove(lastNode.Value.Key);
  15.             _lruList.RemoveLast();
  16.         }
  17.         
  18.         // 添加新项到链表头部
  19.         var newNode = _lruList.AddFirst(new CacheItem<TKey, TValue> { Key = key, Value = value });
  20.         _cache[key] = newNode;
  21.     }
  22. }
复制代码
8.1 学习资源和参考文献

8.1.1 官方文档


  • Microsoft.Extensions.Caching.Memory
  • StackExchange.Redis Documentation
  • Redis Official Documentation
8.1.2 推荐书籍


  • 《高性能MySQL》- 缓存设计理论基础
  • 《Redis设计与实现》- Redis深度解析
  • 《.NET性能优化》- .NET平台性能调优
8.1.3 开源项目参考


  • EasyCaching - .NET缓存框架
  • FusionCache - 高级缓存库
  • CacheManager - 多级缓存管理器
结尾

qq技术交流群:737776595

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册