Redis缓存与内存缓存可配置切换实现方案咨询
实现可配置切换Redis/内存缓存的方案建议
1. 定义统一缓存接口
先脱离Redis和内存缓存的原有接口,自定义一套覆盖核心操作的统一缓存接口,比如命名为ICacheService,把你需要的存、取、删、过期设置等操作抽象进来:
public interface ICacheService { Task<T?> GetAsync<T>(string key); Task SetAsync<T>(string key, T value, TimeSpan? expiration = null); Task RemoveAsync(string key); Task<bool> ExistsAsync(string key); }
通过这个统一接口,就能避免被IMemoryCache或IRedisService的原生差异绑定,实现底层逻辑的解耦。
2. 分别实现两种缓存服务
内存缓存实现(适配IMemoryCache)
把IMemoryCache的同步API适配为统一接口的异步风格,保证接口调用一致性:
public class MemoryCacheService : ICacheService { private readonly IMemoryCache _memoryCache; public MemoryCacheService(IMemoryCache memoryCache) { _memoryCache = memoryCache; } public Task<T?> GetAsync<T>(string key) { var result = _memoryCache.TryGetValue(key, out T? value) ? value : default; return Task.FromResult(result); } public Task SetAsync<T>(string key, T value, TimeSpan? expiration = null) { var options = new MemoryCacheEntryOptions(); if (expiration.HasValue) { options.AbsoluteExpirationRelativeToNow = expiration; } _memoryCache.Set(key, value, options); return Task.CompletedTask; } public Task RemoveAsync(string key) { _memoryCache.Remove(key); return Task.CompletedTask; } public Task<bool> ExistsAsync(string key) { var exists = _memoryCache.TryGetValue(key, out _); return Task.FromResult(exists); } }
Redis缓存实现(适配IRedisService)
基于你现有的IRedisService,将其操作适配到统一接口,处理序列化等Redis特有的逻辑:
public class RedisCacheService : ICacheService { private readonly IRedisService _redisService; public RedisCacheService(IRedisService redisService) { _redisService = redisService; } public async Task<T?> GetAsync<T>(string key) { var value = await _redisService.GetStringAsync(key); return value == null ? default : JsonSerializer.Deserialize<T>(value); } public async Task SetAsync<T>(string key, T value, TimeSpan? expiration = null) { var jsonValue = JsonSerializer.Serialize(value); if (expiration.HasValue) { await _redisService.SetStringAsync(key, jsonValue, expiration.Value); } else { await _redisService.SetStringAsync(key, jsonValue); } } public Task RemoveAsync(string key) { return _redisService.DeleteKeyAsync(key); } public async Task<bool> ExistsAsync(string key) { return await _redisService.KeyExistsAsync(key); } }
3. 通过配置实现启动时注入切换
第一步:在Appsettings.json添加缓存配置
{ "CacheSettings": { "CacheType": "Redis", // 可选值:Redis / Memory "RedisConnectionString": "your-redis-connection-string" } }
第二步:在Program.cs中根据配置注入对应服务
先定义配置实体类:
public class CacheSettings { public string CacheType { get; set; } = "Memory"; public string RedisConnectionString { get; set; } = string.Empty; }
再在服务注入环节判断配置:
// 读取缓存配置 var cacheSettings = builder.Configuration.GetSection("CacheSettings").Get<CacheSettings>(); // 根据配置注入对应服务 if (cacheSettings.CacheType.Equals("Redis", StringComparison.OrdinalIgnoreCase)) { // 注入你的Redis服务实现 builder.Services.AddSingleton<IRedisService, YourRedisServiceImpl>(); // 注入Redis版统一缓存服务 builder.Services.AddSingleton<ICacheService, RedisCacheService>(); } else { // 注入内存缓存基础服务 builder.Services.AddMemoryCache(); // 注入内存版统一缓存服务 builder.Services.AddSingleton<ICacheService, MemoryCacheService>(); }
4. 业务代码仅依赖统一接口
所有业务类只注入ICacheService,完全不用关心底层是Redis还是内存缓存:
public class SomeBusinessService { private readonly ICacheService _cacheService; public SomeBusinessService(ICacheService cacheService) { _cacheService = cacheService; } public async Task DoBusinessLogic() { var data = await _cacheService.GetAsync<BusinessData>("cache-key:business-data"); if (data == null) { // 从数据库获取数据 data = await FetchDataFromDb(); // 存入缓存,设置30分钟过期 await _cacheService.SetAsync("cache-key:business-data", data, TimeSpan.FromMinutes(30)); } // 后续业务逻辑处理 } }
5. 兼容两种缓存的逻辑差异
Redis和内存缓存的特性差异(比如Redis是分布式、内存缓存是进程内),可以在各自的实现类中做适配:
- 序列化:Redis需要将对象序列化为字符串,内存缓存可直接存对象(也可以统一序列化,看需求)
- 异步适配:内存缓存API多为同步,统一包装成异步返回
Task.CompletedTask即可 - 过期策略:两者都支持绝对过期,通过接口参数传递,底层各自实现对应配置
这样切换时,业务代码无需修改,也不会抛出异常——所有差异都被封装在底层实现中,上层调用完全统一。
6. 可选:实现热切换(无需重启服务)
如果需要不重启服务随时切换缓存类型,可以结合配置中心或定时读取配置文件,通过一个CacheServiceProvider类持有当前缓存实例,监听配置变化时替换实例。业务代码注入CacheServiceProvider获取当前服务即可,不过这种方式复杂度较高,若没有刚需,启动时切换的方案完全够用。
内容的提问来源于stack exchange,提问作者Shoaib Ismail
相关产品推荐
相关产品推荐

