ASP.NET Core與Redis建置一個簡易分散式快取

?本文主要介紹了快取的概念,以及如何在伺服器記憶體中儲存內容。今天的目標是利用IDistributedCache來做一些分散式快取,這樣我們就可以橫向擴展我們的web應用程式。

在本教學中,我將使用Redis作為快取。Redis是一個可靠的快速記憶體快取,可以儲存多種型別的物件。Redis正在被Twitter, Github, Instagram, Stackoverflow等巨頭使用。

你可以在https://github.com/sahan91/DistributedCacheAspNetCoreRedis找到范常式式碼。

這是我們實現後的一個快照。

  • 使用者請求一個User物件。
  • App server檢查快取中是否已經有使用者,如果存在則回傳物件。
  • App server透過HTTP呼叫來搜尋使用者串列。
  • Users service將使用者串列回傳給App server。
  • App server將使用者串列發送到分散式(Redis)快取。
  • App server獲得快取的版本,直到它過期(TTL)。
  • 使用者取得快取的User物件。

我們稱其為分散式快取的主要原因是,它位於應用伺服器之外(與傳統的記憶體快取相反),如果需要的話,我們可以靈活地水平擴展它(在雲中操作時)。來看看在企業應用程式中是如何有用的。

IDistributedCache介面為我們提供了一組操作快取的方法。這裡總結了幾種不同的方法。

建置一個範例應用程式

我們將用ASP.NET Core 5建立一個Web MVC應用程式。

1
dotnet new mvc -n DistributedCachedotnet new slndotnet sln add DistributedCache

讓我們繼續從NuGet新增Redis客戶端包。

1
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --version 5.0.1

建立一個Redis docker容器

假設已經在你的機器上安裝了Docker。這是很方便的,你可以在任何想要開發的時候啟動自己的Redis容器。

1
docker run --name redis-cache -p 5002:6379 -d redis

使用官方的Redis對映,建立一個名為redis-cache的容器,並將容器的6379連接埠繫結到主機的5002連接埠。如果你在本地沒有Redis的對映,它會從DockerHub取得它。接下來讓我們驗證docker例項是否啟動並執行。

1
docker ps -a

現在我們已經有了Redis容器並執行,接下來配置我們的web應用程式。

應用程式配置

因為我們已經新增了所需的NuGet包,我們只需要在應用的DI容器中註冊,並告訴它在哪裡可以找到我們的Redis例項。

1
2
3
services.AddStackExchangeRedisCache(options =>{
    options.Configuration = Configuration.GetSection("Redis")["ConnectionString"];
});

當我們在服務物件上呼叫AddStackExchangeRedisCache時,它會在底層透過IDistributedCache介面註冊一個RedisCache類的單例。

1
services.Add(ServiceDescriptor.Singleton<IDistributedCache, RedisCache>());

因為我們已經在5002連接埠上啟動並執行了Docker例項,所以我們可以在配置中設定它。

1
"Redis": {  "ConnectionString": "localhost:5002"}

實現

這個功能很簡單,下面是我們要做的:

  • 取得快取的使用者(如果有的話)並顯示其電郵地址
  • 用於呼叫HTTP快取使用者串列的按鈕
  • 清除快取的按鈕

UI將類似於以下。

讓我們看看程式的入口,HomeController類。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public async Task<IActionResult> Index(){
    var users = (await _cacheService.GetCachedUser())?.FirstOrDefault();
    return View(users);
}
?
public async Task<IActionResult> CacheUserAsync(){
    var users = await _usersService.GetUsersAsync();
    var cacheEntry = users.First();
    return View(nameof(Index), cacheEntry);
}
?
public IActionResult CacheRemoveAsync(){
    _cacheService.ClearCache();
    return RedirectToAction(nameof(Index));
}

這裡的程式碼很容易解釋,我們在Index、CacheUserAsync和cacheeremoveasync中實現了之前的3個內容。

跳過所有其他管道程式碼,並展示我們如何使用Redis快取取得和設定值。真正神奇的事情發生在ICacheProvider類中。

在GetFromCache方法中,我們使用給定的鍵(在本例中為_Users)呼叫GetStringAsync。值得注意的是,在將它回傳給呼叫者之前,我們需要將它反序列化為我們想要的型別。類似地,序列化我們的使用者串列,並將它作為字串儲存在Redis快取中的_Users鍵下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class CacheProvider : ICacheProvider{
    private readonly IDistributedCache _cache;
?
    public CacheProvider(IDistributedCache cache)
    {
        _cache = cache;
    }
   
    public async Task<T> GetFromCache<T>(string key) where T : class
    {
        var cachedResponse = await _cache.GetStringAsync(key);
        return cachedResponse == null ? null : JsonSerializer.Deserialize<T>(cachedResponse);
    }
?
    public async Task SetCache<T>(string key, T value, DistributedCacheEntryOptions options) where T : class
    {
        var response = JsonSerializer.Serialize(value);
        await _cache.SetStringAsync(key, response , options);
    }
?
    public async Task ClearCache(string key)
    {
        await _cache.RemoveAsync(key);
    }
}

我們可以連接到容器,開啟redis-cli檢視裡面有什麼。

1
docker exec -it redis-cache redis-cli

進入後,可以發出hgetall _Users命令來檢查快取中有哪些內容。

結論

在本文中,我們將使用ASP.NET Core提供的IDistributedCache介面,使用Redis作為後台儲存。這種方法可以用來利用Azure Redis快取等雲服務,用於回應快取、會話儲存等。

原文連結:https://sahansera.dev/distributed-caching-aspnet-core-redis/