在.NET Core Web Api中使用redis
1. 引入 Redis 依赖
在 Water.Api 项目中安装 Redis 客户端包:右键项目 → 管理 NuGet 包 → 安装 StackExchange.Redis(主流 Redis 客户端)。
2. 配置 Redis 连接在
appsettings.json 中添加 Redis 连接字符串:
{"ConnectionStrings": {"DefaultConnection": "数据库连接字符串","Redis": "localhost:6379,password=你的密码,defaultDatabase=0" // Redis 连接串 没有设置密码就删除password选项}
}
3. 注册 Redis 服务(Program.cs)
using StackExchange.Redis;// 注册 Redis 连接
builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
{var configuration = builder.Configuration.GetConnectionString("Redis");return ConnectionMultiplexer.Connect(configuration);
});4:改造业务层(添加缓存逻辑)在
WaterInfoService 中注入 Redis 并实现 “先查缓存、再查数据库、后写缓存” 的逻辑:
using AutoMapper;
using StackExchange.Redis;
using System.Text.Json;
using Water.Application.Contracts.WaterInfo;
using Water.Application.Contracts.WaterInfo.Dtos;
using Water.Application.Contracts.WaterInfo.Vos;
using Water.Domain.Repositories;
using Microsoft.Extensions.Logging;namespace Water.Application.WaterInfo.Services;public class WaterInfoService : IWaterInfoService
{private readonly IWaterInfoRepository _waterInfoRepository;private readonly IMapper _mapper;private readonly IDatabase _redisDb;private readonly ILogger<WaterInfoService> _logger;private const string CachePrefix = "water:info:list:";private const int CacheExpirySeconds = 300; // 缓存过期时间(5分钟)public WaterInfoService(IWaterInfoRepository waterInfoRepository, IMapper mapper,IConnectionMultiplexer redisMultiplexer,ILogger<WaterInfoService> logger){_waterInfoRepository = waterInfoRepository;_mapper = mapper;_redisDb = redisMultiplexer.GetDatabase();_logger = logger;}public async Task<List<WaterInfoListVo>> GetWaterInfoListAsync(WaterInfoQueryDto waterInfoQueryDto){string cacheKey;// 生成缓存键(区分“全部商品”和“按分类查询”)if (waterInfoQueryDto.CategoryId.HasValue){cacheKey = $"{CachePrefix}category:{waterInfoQueryDto.CategoryId.Value}";}else{cacheKey = $"{CachePrefix}all";}try{// 尝试从 Redis 读取缓存var cachedData = await _redisDb.StringGetAsync(cacheKey);if (!cachedData.IsNull){return JsonSerializer.Deserialize<List<WaterInfoListVo>>(cachedData)!;}}catch (Exception ex){_logger.LogError(ex, "Redis 查询失败,降级到数据库查询");// 异常时继续执行数据库查询逻辑}// 缓存不存在,查询数据库var domainEntities = await _waterInfoRepository.GetWaterInfoListAsync(categoryId: waterInfoQueryDto.CategoryId,name: waterInfoQueryDto.Name);var voList = _mapper.Map<List<WaterInfoListVo>>(domainEntities);// 仅当未传“商品名称”时,才写入缓存(模糊查询不缓存)if (string.IsNullOrEmpty(waterInfoQueryDto.Name)){await _redisDb.StringSetAsync(key: cacheKey,value: JsonSerializer.Serialize(voList),expiry: TimeSpan.FromSeconds(CacheExpirySeconds));}return voList;}
}
5:处理缓存失效(可选,数据更新时清理缓存)
当商品数据发生变更(新增、修改、删除)时,需主动删除对应缓存,示例(假设存在修改方法):
// 在 WaterInfoService 中新增修改方法(示例)
public async Task<bool> UpdateWaterInfoAsync(WaterInfoUpdateDto updateDto)
{// 1. 执行数据库修改逻辑(略)var isSuccess = await _waterInfoRepository.UpdateAsync(updateDto);// 2. 删除缓存(确保下次查询获取最新数据)var cacheKeys = new List<string> { $"{CachePrefix}all" }; // 先删除“全部商品”缓存if (updateDto.CategoryId.HasValue){cacheKeys.Add($"{CachePrefix}category:{updateDto.CategoryId.Value}"); // 再删除“对应分类”缓存}foreach (var key in cacheKeys){await _redisDb.KeyDeleteAsync(key);}return isSuccess;
}