筆記目錄

Skip to content

在 ASP.NET 使用 Redis 實作分散式快取

TLDR

  • Windows 環境不建議使用微軟封存的 Redis 版本,建議使用 WSL 2、Docker 或 Memurai。
  • 使用 Docker 部署 Redis 時,若遇到連線被拒,需調整 redis.conf 中的 bindprotected-mode 設定。
  • 單機環境建議優先使用 IMemoryCache,效能優於分散式快取。
  • IDistributedCache 原生僅支援 string 存取,建議針對專案需求自行擴充 API。
  • 使用 IDistributedCache 時,若資料可能異動,務必搭配 AbsoluteExpirationIChangeToken 策略。

在 Windows 上安裝 Redis 的建議方案

由於 Redis 原生並未支援 Windows,在 Windows 環境開發時,請避免使用已停止維護的微軟封存版本。建議採取以下替代方案:

  • WSL 2:官方推薦的 Linux 相容層安裝方式。
  • Memurai:兼容 Redis 6.2 的 Windows 原生分支,適合開發與測試環境。
  • Docker:透過官方 Image 部署,適合跨平台一致性需求。

使用 Docker 安裝 Redis 的注意事項

什麼情況下會遇到:當使用 Docker 部署 Redis 且外部應用程式無法連線至 Container 時。

若需自訂設定,請掛載 redis.conf 並透過 command 指定。若遇到連線被拒(Connection refused),請檢查並修改 redis.conf

  • bind 127.0.0.1 -::1 註解掉。
  • protected-mode yes 改為 protected-mode no

TIP

bind 參數限制了允許連線的 IP,若設定為 127.0.0.1,則僅限本機連線。protected-mode 若設為 yes,則必須設定 bindrequirepass 密碼驗證。

在 ASP.NET Core 使用 MemoryCache

什麼情況下會遇到:當應用程式僅部署於單一伺服器,且對效能有極高要求時。

IMemoryCache 提供兩種過期策略:

  • Absolute:絕對到期時間,時間一到即刪除。
  • Sliding:滑動到期時間,若持續被讀取則會延長存活時間。

WARNING

若快取資料有異動可能,建議搭配 AbsoluteExpirationIChangeToken 以確保資料一致性。

在 ASP.NET Core 使用 Redis 實作分散式快取

什麼情況下會遇到:當應用程式部署於多台伺服器(分散式架構),需要共享快取狀態時。

透過 Microsoft.Extensions.Caching.StackExchangeRedis 套件,可將 IDistributedCache 注入至專案中:

csharp
builder.Services.AddStackExchangeRedisCache(options => {
    options.Configuration = builder.Configuration.GetConnectionString("Redis");
    options.InstanceName = "SampleInstance";
});

WARNING

若 App Server 僅有一台,使用 IMemoryCache 效能優於 IDistributedCache,因為後者涉及遠端網路存取。此外,IDistributedCache 原生僅支援 string 存取,建議針對複雜物件自行擴充 API。

在 ASP.NET Framework 使用 Redis

什麼情況下會遇到:維護舊版 .NET Framework (如 4.8) 專案時。

可直接使用 StackExchange.Redis 套件,並建議透過單例模式(Singleton)管理 ConnectionMultiplexer

csharp
public sealed class RedisConnection {
    private static readonly Lazy<RedisConnection> lazy = new Lazy<RedisConnection>(() => new RedisConnection());

    private RedisConnection() {
        ConnectionMultiplexer = ConnectionMultiplexer.Connect("127.0.0.1:6379");
    }

    public static RedisConnection Instance => lazy.Value;
    public ConnectionMultiplexer ConnectionMultiplexer { get; }
}

使用方式:

csharp
IDatabase db = RedisConnection.Instance.ConnectionMultiplexer.GetDatabase(0);
string cachedValue = await db.StringGetAsync("CacheKey");

異動歷程

  • 2022-11-02 初版文件建立。