☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
redis 初學

🔌 在 ASP.NET Core 中使用 Redis

📌 安裝 NuGet 套件

# StackExchange.Redis — 最常用的 .NET Redis 客戶端
dotnet add package StackExchange.Redis

# Microsoft 官方的分散式快取支援
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis

📌 ConnectionMultiplexer 連線管理

ConnectionMultiplexer 是 StackExchange.Redis 的核心類別,負責管理與 Redis 的連線。

using StackExchange.Redis;

// ❌ 錯誤:每次都建立新連線(非常昂貴!)
public Product GetProduct(int id)
{
    var redis = ConnectionMultiplexer.Connect("localhost:6379");
    var db = redis.GetDatabase();
    // ...
}

// ✅ 正確:ConnectionMultiplexer 應該是 Singleton
public class RedisConnection
{
    private static readonly Lazy<ConnectionMultiplexer> _instance =
        new(() => ConnectionMultiplexer.Connect("localhost:6379"));

    public static ConnectionMultiplexer Instance => _instance.Value;
}

在 DI 容器中註冊

// Program.cs
builder.Services.AddSingleton<IConnectionMultiplexer>(
    ConnectionMultiplexer.Connect(
        builder.Configuration.GetConnectionString("Redis")!));

📌 IDatabase 基本操作

public class RedisCacheService
{
    private readonly IDatabase _db;

    public RedisCacheService(IConnectionMultiplexer redis)
    {
        _db = redis.GetDatabase();
    }

    // 存入快取
    public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
    {
        var json = JsonSerializer.Serialize(value);
        await _db.StringSetAsync(key, json, expiry);
    }

    // 從快取取得
    public async Task<T?> GetAsync<T>(string key)
    {
        var value = await _db.StringGetAsync(key);
        if (value.IsNullOrEmpty) return default;
        return JsonSerializer.Deserialize<T>(value!);
    }

    // 刪除快取
    public async Task RemoveAsync(string key)
    {
        await _db.KeyDeleteAsync(key);
    }

    // 檢查是否存在
    public async Task<bool> ExistsAsync(string key)
    {
        return await _db.KeyExistsAsync(key);
    }
}

📌 使用 IDistributedCache 介面

ASP.NET Core 提供了 IDistributedCache 抽象介面,可以輕鬆切換快取實作:

// Program.cs — 註冊 Redis 分散式快取
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration
        .GetConnectionString("Redis");
    options.InstanceName = "DevLearn:";
});
// 使用 IDistributedCache
public class ProductService
{
    private readonly IDistributedCache _cache;
    private readonly AppDbContext _db;

    public ProductService(IDistributedCache cache, AppDbContext db)
    {
        _cache = cache;
        _db = db;
    }

    public async Task<Product?> GetProductAsync(int id)
    {
        var cacheKey = $"product:{id}";

        // 1. 嘗試從快取取得
        var cached = await _cache.GetStringAsync(cacheKey);
        if (cached != null)
            return JsonSerializer.Deserialize<Product>(cached);

        // 2. 快取沒有,查資料庫
        var product = await _db.Products.FindAsync(id);
        if (product == null) return null;

        // 3. 放入快取
        var options = new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
            SlidingExpiration = TimeSpan.FromMinutes(2)
        };
        await _cache.SetStringAsync(cacheKey,
            JsonSerializer.Serialize(product), options);

        return product;
    }
}

📌 appsettings.json 連線設定

{
  "ConnectionStrings": {
    "Redis": "localhost:6379,abortConnect=false,connectTimeout=5000"
  }
}

常用連線參數

參數 說明 預設值
abortConnect 連線失敗是否拋例外 true
connectTimeout 連線逾時(ms) 5000
password 密碼
ssl 是否用 SSL false
defaultDatabase 預設資料庫索引 0
asyncTimeout 非同步操作逾時 5000

📌 完整範例:Product API + Redis 快取

// Controllers/ProductsController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly AppDbContext _db;
    private readonly IDistributedCache _cache;
    private readonly ILogger<ProductsController> _logger;

    public ProductsController(
        AppDbContext db,
        IDistributedCache cache,
        ILogger<ProductsController> logger)
    {
        _db = db;
        _cache = cache;
        _logger = logger;
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetProduct(int id)
    {
        var cacheKey = $"product:{id}";

        // 嘗試快取
        var cached = await _cache.GetStringAsync(cacheKey);
        if (cached != null)
        {
            _logger.LogInformation("Cache HIT for product {Id}", id);
            return Ok(JsonSerializer.Deserialize<Product>(cached));
        }

        _logger.LogInformation("Cache MISS for product {Id}", id);

        // 查 DB
        var product = await _db.Products.FindAsync(id);
        if (product == null) return NotFound();

        // 寫入快取(5 分鐘過期)
        await _cache.SetStringAsync(cacheKey,
            JsonSerializer.Serialize(product),
            new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
            });

        return Ok(product);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateProduct(int id, Product updated)
    {
        var product = await _db.Products.FindAsync(id);
        if (product == null) return NotFound();

        product.Name = updated.Name;
        product.Price = updated.Price;
        await _db.SaveChangesAsync();

        // 更新後清除快取
        await _cache.RemoveAsync($"product:{id}");
        _logger.LogInformation("Cache INVALIDATED for product {Id}", id);

        return Ok(product);
    }
}

🔑 重點整理

  1. StackExchange.Redis 是 .NET 最常用的 Redis 客戶端
  2. ConnectionMultiplexer 必須是 Singleton,避免重複建立連線
  3. IDistributedCache 是 ASP.NET Core 的標準快取介面
  4. 連線字串放在 appsettings.json,透過 DI 注入使用
  5. 更新資料後,記得 清除對應的快取

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊