Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

ASP.NET Core 및 Azure Redis Cache를 사용하여 캐시 배제 패턴 구현

소프트웨어 개발 주기에서는 애플리케이션 성능에 중점을 두는 경우가 많습니다. 성능을 향상시키는 방법에는 여러 가지가 있으며 최신 클라우드 애플리케이션에서 성능을 향상시키기 위해 가장 일반적으로 사용되는 패턴 중 하나는 캐시 배제 패턴입니다. 이번 포스팅에서는 캐시 배제 패턴과 ASP.NET Core를 이용한 구현에 대해 간략하게 설명하겠습니다.

소개

이 패턴은 매우 간단하며 유일한 목적은 요청 시 데이터 소스에서 캐시로 데이터를 로드하는 것입니다. 이는 캐시에 있는 데이터와 기본 데이터 소스 간의 일관성을 유지하는 데 도움이 됩니다.

다음은 패턴의 특징입니다.

  • 애플리케이션에 데이터가 필요할 때 먼저 캐시를 조사합니다.
  • 데이터가 캐시에 있는 경우 애플리케이션은 캐시의 데이터를 사용합니다.
  • 그렇지 않으면 데이터 소스에서 데이터가 검색됩니다.

아래는 도식적인 그림입니다

ASP.NET Core 및 Azure Redis Cache를 사용하여 캐시 배제 패턴 구현

캐시 객체는 애플리케이션에 의해 값이 변경되면 무효화되어야 합니다.

ASP.NET Core 및 Azure Redis Cache를 사용하여 캐시 배제 패턴 구현

캐시를 무효화하는 순서가 중요합니다. 캐시에서 항목을 제거하기 전에 데이터 소스를 업데이트하세요. 먼저 캐시에서 항목을 제거한 경우 데이터 저장소가 업데이트되기 전에 클라이언트가 항목을 가져올 가능성이 있습니다. 그러면 데이터 저장소와 캐시 사이에 데이터 불일치가 발생하게 됩니다.

언제 이 패턴을 사용하나요?

  • 이 패턴을 사용하면 요청 시 데이터를 로드할 수 있으며 리소스 수요를 예측할 수 없을 때 사용할 수 있습니다.
  • 읽기 및 연속 쓰기 작업을 제공하지 않는 캐시

참고

  • 읽기: 이는 데이터베이스와 나란히 위치하는 캐시이며, 캐시 누락이 발생할 경우 데이터베이스에서 데이터를 로드하고 캐시를 채울 수 있습니다.
  • 연속 기입: 캐시는 데이터베이스와 나란히 위치하며 데이터는 항상 캐시를 통해 기본 데이터베이스로 이동합니다.

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; } 
} 

이제 Startup 클래스의 ConfigureServices 메서드에 EF Core 및 Redis 캐시의 종속성을 등록해 보겠습니다.

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를 사용한 기본 구현을 설명했습니다. 캐싱을 즐겨보세요!

기사가 마음에 드셨으면 좋겠습니다. 기사가 흥미로웠다면 좋아요를 누르고 공유해 주세요.