如何为ASP.NET Core 3.1应用扩展LazyCache以集成Redis缓存?
替换LazyCache底层为Redis的实现示例
1. 安装必要NuGet包
Install-Package LazyCache Install-Package Microsoft.Extensions.Caching.StackExchangeRedis Install-Package Newtonsoft.Json # 用于对象序列化,可根据项目替换为System.Text.Json
2. 配置Redis连接及服务注入
在Startup.cs的ConfigureServices方法中添加Redis缓存配置,并注册自定义的LazyCache实现:
public void ConfigureServices(IServiceCollection services) { // 配置Redis分布式缓存 services.AddStackExchangeRedisCache(options => { options.Configuration = Configuration.GetConnectionString("Redis"); options.InstanceName = "YourAppInstance:"; // 用于区分不同应用的缓存键 }); // 注册基于Redis的LazyCache实现 services.AddSingleton<IAppCache, RedisBackedAppCache>(); // 注册你的自定义缓存提供者,内部复用LazyCache能力 services.AddSingleton<ICacheProvider, LazyCacheBasedCacheProvider>(); // 其他Web API服务配置 services.AddControllers(); }
3. 实现基于Redis的LazyCache底层
创建RedisBackedAppCache类,继承LazyCache的AppCache并替换底层缓存逻辑为Redis:
using LazyCache; using Microsoft.Extensions.Caching.Distributed; using Newtonsoft.Json; using System; using System.Threading.Tasks; public class RedisBackedAppCache : AppCache { private readonly IDistributedCache _distributedCache; public RedisBackedAppCache(IDistributedCache distributedCache) { _distributedCache = distributedCache ?? throw new ArgumentNullException(nameof(distributedCache)); } // 重写异步获取/添加缓存方法 public override async Task<T> GetOrAddAsync<T>(string key, Func<Task<T>> addItemFactory, DateTimeOffset absoluteExpiration) { var cachedJson = await _distributedCache.GetStringAsync(key); if (!string.IsNullOrEmpty(cachedJson)) { return JsonConvert.DeserializeObject<T>(cachedJson); } // 缓存不存在时调用工厂方法获取数据 var data = await addItemFactory(); var serializedData = JsonConvert.SerializeObject(data); await _distributedCache.SetStringAsync(key, serializedData, new DistributedCacheEntryOptions { AbsoluteExpiration = absoluteExpiration }); return data; } // 重写同步获取方法 public override T Get<T>(string key) { var cachedJson = _distributedCache.GetString(key); return string.IsNullOrEmpty(cachedJson) ? default : JsonConvert.DeserializeObject<T>(cachedJson); } // 重写缓存移除方法 public override void Remove(string key) { _distributedCache.Remove(key); } // 可根据业务需求重写其他方法(如滑动过期、同步GetOrAdd等) }
4. 适配原有自定义ICacheProvider
保留原有ICacheProvider接口,实现基于LazyCache的实现类,确保业务代码无需修改:
// 原有自定义缓存接口(保持不变) public interface ICacheProvider { Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> dataRetriever, TimeSpan expiration); T GetOrSet<T>(string cacheKey, Func<T> dataRetriever, TimeSpan expiration); void Remove(string cacheKey); T Get<T>(string cacheKey); } // 基于LazyCache的实现类 public class LazyCacheBasedCacheProvider : ICacheProvider { private readonly IAppCache _appCache; public LazyCacheBasedCacheProvider(IAppCache appCache) { _appCache = appCache; } public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> dataRetriever, TimeSpan expiration) { return await _appCache.GetOrAddAsync(cacheKey, dataRetriever, DateTimeOffset.Now.Add(expiration)); } public T GetOrSet<T>(string cacheKey, Func<T> dataRetriever, TimeSpan expiration) { return _appCache.GetOrAdd(cacheKey, dataRetriever, DateTimeOffset.Now.Add(expiration)); } public void Remove(string cacheKey) { _appCache.Remove(cacheKey); } public T Get<T>(string cacheKey) { return _appCache.Get<T>(cacheKey); } }
5. 配置Redis连接字符串
在appsettings.json中添加Redis连接信息:
{ "ConnectionStrings": { "Redis": "your-redis-connection-string-here" } }
注意事项
- 序列化方式可根据项目需求替换为
System.Text.Json,只需修改序列化/反序列化代码即可 - 若需要滑动过期策略,可在
DistributedCacheEntryOptions中配置SlidingExpiration参数 - 可根据业务需求完善
RedisBackedAppCache中的其他方法,如处理缓存不存在时的默认值等
内容的提问来源于stack exchange,提问作者santosh kumar patro
相关产品推荐
相关产品推荐

