在.NET Core Web Api中使用redis

1. 引入 Redis 依赖

在 Water.Api 项目中安装 Redis 客户端包:右键项目 → 管理 NuGet 包 → 安装 StackExchange.Redis(主流 Redis 客户端)。

2. 配置 Redis 连接在

appsettings.json 中添加 Redis 连接字符串:

cs 复制代码
{
  "ConnectionStrings": {
    "DefaultConnection": "数据库连接字符串",
    "Redis": "localhost:6379,password=你的密码,defaultDatabase=0" // Redis 连接串 没有设置密码就删除password选项
  }
}

3. 注册 Redis 服务(Program.cs)

cs 复制代码
using StackExchange.Redis;

// 注册 Redis 连接
builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
{
    var configuration = builder.Configuration.GetConnectionString("Redis");
    return ConnectionMultiplexer.Connect(configuration);
});

4:改造业务层(添加缓存逻辑)在

WaterInfoService 中注入 Redis 并实现 "先查缓存、再查数据库、后写缓存" 的逻辑:

cs 复制代码
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:处理缓存失效(可选,数据更新时清理缓存)

当商品数据发生变更(新增、修改、删除)时,需主动删除对应缓存,示例(假设存在修改方法):

cs 复制代码
// 在 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;
}
相关推荐
栗子~~7 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
Xin_ye1008610 小时前
C# 零基础到精通教程 - 第七章:面向对象编程(入门)——类与对象
开发语言·c#
rockey62710 小时前
AScript异步执行与await关键字
c#·.net·script·eval·expression·异步执行·动态脚本
Mr. zhihao10 小时前
深入解析redis基本数据结构
数据结构·数据库·redis
程序leo源12 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#
柿柿快乐13 小时前
Redis 入门第一课:全局命令、内部编码与单线程模型
redis·学习·缓存·基础教学
Tirzano14 小时前
超大型组和用户缓存redis
redis·缓存·哈希算法
阿维的博客日记15 小时前
zset实现延迟队列
redis·zset
无小道15 小时前
Redis——string类型相关指令
redis·指令·string
月巴月巴白勺合鸟月半16 小时前
质本洁来还洁去,强于污淖陷文本
c#