文章目录
前言
在 ASP.NET Core 中,分布式缓存是一种将缓存数据存储在多个应用服务器共享的外部服务中的机制。它适用于分布式系统、集群部署或需要跨多个实例共享缓存数据的场景。
一、分布式缓存的核心概念
作用:
- 提升性能(减少数据库压力)
- 支持跨多个应用实例共享缓存数据
- 确保缓存一致性(尤其在负载均衡环境中)
- 支持高可用性和容错
与内存缓存的区别:
- 内存缓存 (IMemoryCache) 数据存储在应用进程内存中,无法跨实例共享。
- 分布式缓存 (IDistributedCache) 数据存储在外部服务(如 Redis、SQL Server、Memcached),可跨实例共享。缓存值的类型为byte[],需要自己进行类型转换,也提供了一些按照string类型存取缓存值的扩展方法。
二、ASP.NET Core 中的 IDistributedCache
- ASP.NET Core 提供 IDistributedCache 接口,抽象了分布式缓存的操作:
public interface IDistributedCache { byte[]? Get(string key); Task<byte[]?> GetAsync(string key, CancellationToken token = default); void Set(string key, byte[] value, DistributedCacheEntryOptions options); Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default); void Refresh(string key); Task RefreshAsync(string key, CancellationToken token = default); void Remove(string key); Task RemoveAsync(string key, CancellationToken token = default); }
三、常用分布式缓存实现
- 缓存服务器说明
- 1、SQL Server做缓存服务性能并不好。
- 2、Memcached是缓存专用,性能非常高,但是对于集群、高可用等方面比较弱,而且有“缓存键的最大长度为250字节”等限制。使用需要安装EnyimMemcachedCore第三方Nuget包。
- 3、Redis不局限于缓存,Redis做缓存服务器比Memcached性能稍差,但是Redis的高可用、集群等方面非常强大,适合在数据量大、高可用性等场景下使用。
1)Redis(最常用)
优势:高性能、低延迟、支持数据持久化。
配置步骤:
- 安装 NuGet 包:
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis
- 在 Program.cs 中注册服务:
builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = "localhost:6379"; // Redis 服务地址 options.InstanceName = "MyApp_"; // 可选,用于键前缀,避免混乱 });
- 安装 NuGet 包:
2)SQL Server
- 适用场景:需要利用现有 SQL Server 数据库作为缓存存储。
- 配置步骤:
安装 NuGet 包:
Install-Package Microsoft.Extensions.Caching.SqlServer
创建缓存表(使用 sql-cache 工具):
dotnet sql-cache create @"Data Source=.;Initial Catalog=CacheDb; Integrated Security=True;" dbo CacheTable
注册服务:
builder.Services.AddDistributedSqlServerCache(options => { options.ConnectionString = "Data Source=.;Initial Catalog=CacheDb;Integrated Security=True;"; options.SchemaName = "dbo"; options.TableName = "CacheTable"; });
3)NCache(企业级方案)
- 优势:高性能、支持内存镜像、数据分区。
- 配置步骤:
- 安装 NuGet 包:
Install-Package Alachisoft.NCache.OpenSource.SDK
- 注册服务:
builder.Services.AddNCacheDistributedCache(configuration => { configuration.CacheName = "myCache"; configuration.EnableLogs = true; });
- 安装 NuGet 包:
四、基本操作示例
- 示例
public class CacheService { private readonly IDistributedCache _cache; public CacheService(IDistributedCache cache) { _cache = cache; } public async Task<string> GetDataAsync(string key) { var data = await _cache.GetAsync(key); return data == null ? null : Encoding.UTF8.GetString(data); } public async Task SetDataAsync(string key, string value, TimeSpan? expiry = null) { var options = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = expiry ?? TimeSpan.FromMinutes(10) }; await _cache.SetAsync(key, Encoding.UTF8.GetBytes(value), options); } public async Task RemoveDataAsync(string key) { await _cache.RemoveAsync(key); } }
五、最佳实践
-
- 缓存内容选择:
- 缓存频繁读取但较少变更的数据(如配置、热点数据)。
- 避免缓存大型对象或敏感数据。
-
- 过期策略:
- 滑动过期(Sliding Expiration):适合活跃数据。
- 绝对过期(Absolute Expiration):确保数据定期刷新。
options.SlidingExpiration = TimeSpan.FromMinutes(5); options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
-
- 序列化:
- 使用高效的序列化方式(如 JSON、MessagePack 或 Protobuf)。
- 示例(使用 System.Text.Json):
var data = JsonSerializer.SerializeToUtf8Bytes(myObject); await _cache.SetAsync(key, data, options);
-
- 缓存雪崩预防:
- 为不同的键设置随机的过期时间偏移量。
- 使用锁机制防止并发更新(如 SemaphoreSlim)。
-
- 高可用性:
- 对 Redis 等缓存服务配置主从复制和哨兵模式。
- 启用持久化以防止数据丢失。
-
- 监控与诊断:
- 使用 Application Insights 或 Prometheus 监控缓存命中率。
- 记录缓存操作耗时和异常。
六、常见问题与解决方案
-
- 缓存穿透(查询不存在的数据):
- 方案:使用布隆过滤器(Bloom Filter)或缓存空值。
-
- 缓存雪崩(大量键同时过期):
- 方案:设置随机过期时间,使用后台任务预加载数据。
-
- 数据一致性:
- 方案:通过发布/订阅模式(如 Redis Pub/Sub)通知其他实例更新缓存。
-
- 性能问题:
- 方案:优化序列化/反序列化,使用二进制格式(如 MessagePack)。
总结
分布式缓存在 ASP.NET Core 中是实现高性能、可扩展应用的关键组件。选择合适的缓存提供程序(如 Redis),结合合理的过期策略和序列化方式,可以显著提升系统性能。在设计和实现时,需特别注意缓存一致性、雪崩和穿透等问题,通过监控和诊断工具持续优化缓存策略。