ASP.NET Core 和 Azure Redis 缓存的缓存模式

作者 : 慕源网 本文共3826个字,预计阅读时间需要10分钟 发布时间: 2022-01-24 共591人阅读

在软件开发周期中,通常关注的是应用程序的性能。有很多方法可以提高性能,而在现代云应用程序中提高性能的最常用的模式之一是 Cache-aside 模式。在这篇文章中,我将简要介绍 Cache-aside 模式及其使用 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

首先,让我们创建一个Country模型类

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

现在修改 appsettings.json 文件以容纳 Redis 缓存和 SQL 数据库的连接字符串

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

结论

在本文中,我描述了 Cache-Aside 模式,它是使用 ASP.NET Core 和 Azure Redis 缓存的主要实现。快乐缓存

我希望你喜欢这篇文章。如果您觉得这篇文章很有趣,请点赞并分享。


慕源网 » ASP.NET Core 和 Azure Redis 缓存的缓存模式

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录