ASP.NET Core と Azure Redis Cache を使用したキャッシュ アサイド パターンの実装
ソフトウェア開発サイクルでは、多くの場合、アプリケーションのパフォーマンスに焦点が当てられます。パフォーマンスを向上させる方法は数多くありますが、最新のクラウド アプリケーションでパフォーマンスを向上させるために最も一般的に使用されるパターンの 1 つは、キャッシュ アサイド パターンです。この投稿では、キャッシュ アサイド パターンと ASP.NET Core を使用したその実装について簡単に説明します。
はじめに
このパターンは非常に単純で、その唯一の目的は、オンデマンドでデータをデータ ソースからキャッシュにロードすることです。これは、キャッシュ内のデータとその基礎となるデータ ソース間の一貫性を維持するのに役立ちます。
パターンの特徴は次のとおりです。
- アプリケーションはデータが必要な場合、まずキャッシュを調べます。
- データがキャッシュに存在する場合、アプリケーションはキャッシュのデータを使用します。
- それ以外の場合、データはデータ ソースから取得されます。
以下は図解です

キャッシュ オブジェクトは、アプリケーションによる値の変更時に無効化する必要があります。

キャッシュを無効にする順序は重要です。キャッシュから項目を削除する前に、データ ソースを更新してください。最初にキャッシュから項目を削除した場合、データ ストアが更新される前にクライアントが項目をフェッチする可能性があります。その結果、データ ストアとキャッシュの間でデータの不整合が発生します。
このパターンをいつ使用するか?
- このパターンにより、オンデマンドでデータを読み込むことができ、リソースの需要が予測できない場合に使用できます
- リードスルーおよびライトスルー操作を提供しないキャッシュ。
注
- お読みください: これはデータベースと連携して配置されるキャッシュであり、キャッシュミスが発生した場合には、データベースからデータをロードしてキャッシュにデータを追加できます。
- ライトスルー: キャッシュはデータベースと連携して配置され、データは常にキャッシュを経由してメイン データベースに送信されます。
Azure リソースを作成する
上に示したように、データベース (Azure SQL Server) とキャッシュ (Azure Redis Cache) が必要です。都合の良いデータベースとキャッシュを選択できます。
$resourceGroup="<Resource Group>"
$location="<location>"
$redisCacheName="<Redis cache name>"
$sqlServerName="<Azure SQL Server Name>"
$sqlDBName="<Azure SQL DB Name>"
$adminName="<admin name of SQL server>"
$adminPassword="<admin password of SQL Server>"
# Creating a resource group
az group create --name $resourceGroup --location $location
# Create Redis Cache with SKU as Basic
az redis create --name $redisCacheName --resource-group $resourceGroup --location $location --sku Basic --vm-size c0
# Create SQL Server
az sql server create -l $location -g $resourceGroup -n $sqlServerName -u $adminName -p $adminPassword
# Create SQL database with SKU as Basic
az sql db create -g $resourceGroup -s $sqlServerName -n $sqlDBName --service-objective Basic
実装
ASP.NET Core Web API プロジェクトを作成し、Redis キャッシュと Entity Framework Core に必要な Nuget パッケージを追加することで実装を始めましょう。
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
まず、国モデル クラスを作成しましょう。
public class Country
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
次に、EF Core と Redis キャッシュの依存関係を Startup クラスの ConfigureServices メソッドに登録しましょう。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<CountryContext>(optionsAction =>
optionsAction.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddStackExchangeRedisCache(setupAction =>
{
setupAction.Configuration = Configuration.GetConnectionString("RedisConnectionString");
});
}
ここで、Redis Cache と SQL Database の接続文字列に対応するように appsettings.json ファイルを変更します。
"ConnectionStrings": {
"RedisConnectionString": "<Redis Cache ConnectionString>",
"DefaultConnection": "<SQL Server Connection string>"
}
DbContext クラスを追加しましょう。
public class CountryContext : DbContext
{
public DbSet<Country> Countries { get; set; }
public CountryContext(DbContextOptions dbContextOptions) : base(dbContextOptions)
{
}
}
GetCountries メソッドは、キーを使用してキャッシュから項目を取得しようとします。一致するものが見つかった場合は、それが返されます。それ以外の場合、データはデータベースから取得され、キャッシュに設定されます。キャッシュされたアイテムは 5 分後に期限切れになるように設定されています。
[Route("api/[controller]")]
[ApiController]
public class CountryController : ControllerBase
{
private readonly IDistributedCache cache;
private readonly CountryContext countryContext;
public CountryController(IDistributedCache cache, CountryContext countryContext)
{
this.cache = cache;
this.countryContext = countryContext;
}
// GET: api/<CountryController>
[HttpGet]
public async Task<IEnumerable<Country>> GetCountries()
{
var countriesCache = await cache.GetStringAsync("countries");
var value = (countriesCache == null) ? default : JsonConvert.DeserializeObject<IEnumerable<Country>>(countriesCache);
if (value == null)
{
var countries = countryContext.Countries.ToList();
if (countries != null && countries.Any())
{
await cache.SetStringAsync("Countries", JsonConvert.SerializeObject(countries), new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
return countries;
}
}
return value;
}
}
AddCountries メソッドは、データベースへのデータの追加/更新時にキャッシュを無効にする方法を示しています。
// POST api/<CountryController>
[HttpPost]
public async Task<ActionResult<string>> AddCountries([FromBody] Country country, CancellationToken cancellationToken)
{
if (country == null)
return BadRequest("country is null");
await countryContext.AddAsync(country);
await countryContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
await cache.RemoveAsync("countries", cancellationToken).ConfigureAwait(false);
return Ok("cache has been invalidated");
}
結論
この記事では、キャッシュ アサイド パターンと、ASP.NET Core と Azure Redis Cache を使用したその主な実装について説明しました。キャッシュを楽しんでください!
記事を気に入っていただければ幸いです。記事が興味深いと思われた場合は、「いいね」を押して共有してください。
-
アイテムをあるリストから別のリストにポップ&プッシュする方法-Redis RPOPLPUSH | BRPOPLPUSH
このチュートリアルでは、あるキーに保存されているリスト値の最後の要素を削除して返す方法と、redisデータストアの別のキーに保存されているリスト値の最初の位置に同じ要素を挿入する方法について学習します。このために、Redis RPOPLPUSHを使用します およびBRPOPLPUSH コマンド。 RPOPLPUSHコマンド このコマンドは、ソースキーに格納されているリスト値の末尾(end)から要素を削除して返し、宛先キーに格納されているリスト値の先頭(start)に同じ要素を挿入するために使用されます。ソースキーが存在しない場合は、nil値が返され、操作は実行されません。宛先キーが存在し
-
RediSearch 2.0を使用すると、インタラクティブな検索エクスペリエンスを備えた最新のアプリを構築できます
本日、RediSearch 2.0の一般提供を発表し、その強力なクエリ、インデックス作成、および全文検索エンジンをすべてのRedisユーザーに提供できることを嬉しく思います。 2020年9月以降の公開プレビューでは、RediSearch 2.0は、最新のアプリケーションの作成から全文検索、リアルタイム分析に至るまで、無数のユースケースでRediSearch2.0に依存する顧客のリストをすでに獲得しています。 RediSearch 2.0は、RediSearch 1.6の2倍以上の速度を実現するまったく新しいアーキテクチャを導入し、RediSearchはRedisのアクティブ-アクティブ地理的分