在今世的 Web 应用中,缓存是提升应用性能的关键组件。尤其是当应用频仍读取数据时,利用缓存可以显著淘汰数据库的负担并提高相应速率。缓存端模式(Cache-Aside Pattern)是一种常用的缓存策略,它可以帮助我们按需加载数据到缓存中。当缓存失效时,应用会从数据存储中加载最新的数据并更新缓存。本文将详细讲解如安在 .NET Core 中实现缓存端模式,利用 Redis 来提升应用性能。
1. 为什么利用缓存端模式?
缓存端模式是指应用程序在访问数据时,起首尝试从缓存中获取数据。如果缓存中没有数据(缓存未命中),则应用程序会从数据存储(如数据库)加载数据,并将其存储到缓存中。缓存的生命周期由应用程序控制,而不是缓存系统主动决定。
与其他缓存策略(如直读和直写策略)差别,缓存端模式的优点在于:
- 按需加载:只有在需要时才将数据加载到缓存中,克制了缓存空间浪费。
- 机动控制缓存生命周期:缓存的过期时间、更新策略等都由应用程序控制,确保数据的时效性。
- 提高性能:频仍读取的数据会被缓存起来,淘汰数据库的访问压力。
2. 实现步调
2.1 安装 Redis 客户端库
在 .NET Core 项目中利用 Redis,我们需要安装 StackExchange.Redis 包,这是一个性能优良且易于利用的 Redis 客户端库。你可以通过以下命令安装:- dotnet add package StackExchange.Redis
复制代码 2.2 配置 Redis 连接字符串
在 appsettings.json 中配置 Redis 连接信息。假设你利用的是本地的 Redis 实例或 Azure Redis 缓存,连接字符串配置如下:- {
- "ConnectionStrings": {
- "RedisConnection": "localhost:6379" // 连接本地 Redis 实例
- }
- }
复制代码 这里,"RedisConnection" 是用于连接 Redis 的连接字符串。
2.3 创建 Redis 服务类
接下来,我们创建一个 RedisCacheService 类,用于管理与 Redis 的连接。为了提高性能,我们将连接利用 Lazy 实现懒加载,确保连接只会在第一次利用时初始化。- using StackExchange.Redis;
- using Microsoft.Extensions.Configuration;
- public class RedisCacheService
- {
- private static Lazy<ConnectionMultiplexer> _lazyConnection;
- private static ConnectionMultiplexer _connection;
- public RedisCacheService(IConfiguration configuration)
- {
- // 获取 Redis 连接字符串
- string redisConnectionString = configuration.GetConnectionString("RedisConnection");
- // 使用 Lazy 确保 Redis 连接只有一个实例,并且是懒加载的
- _lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
- ConnectionMultiplexer.Connect(redisConnectionString));
- }
- // 获取 Redis 数据库实例
- public IDatabase GetDatabase()
- {
- return _lazyConnection.Value.GetDatabase();
- }
- // 获取 Redis 连接实例
- public ConnectionMultiplexer GetConnection()
- {
- return _lazyConnection.Value;
- }
- }
复制代码 此类将 Redis 连接字符串作为参数,并提供一个 GetDatabase 方法来获取 Redis 数据库实例,供后续的缓存操纵利用。
2.4 在 Startup.cs 中注册 Redis 服务
为了在整个应用中共享 Redis 服务,我们需要将 RedisCacheService 注册为单例服务。在 Startup.cs 文件的 ConfigureServices 方法中注册服务:- public void ConfigureServices(IServiceCollection services)
- {
- services.AddSingleton<RedisCacheService>(); // 注册 RedisCacheService 为单例服务
- }
复制代码 2.5 实现缓存端模式
现在,我们可以实现缓存端模式。在缓存端模式中,当应用程序需要数据时,起首检查缓存是否包含该数据。如果缓存中没有数据(缓存未命中),则从数据存储(如数据库)中加载数据,并将其存入缓存中。我们还要为缓存设置过期时间,确保数据的时效性。
以下是实现缓存端模式的代码示例:- using Newtonsoft.Json;
- using StackExchange.Redis;
- using System;
- using System.Threading.Tasks;
- public class MyEntity
- {
- public int Id { get; set; }
- public string Name { get; set; }
- }
- public class MyEntityService
- {
- private readonly RedisCacheService _redisCacheService;
- private readonly TimeSpan _cacheExpiration = TimeSpan.FromMinutes(5);
- public MyEntityService(RedisCacheService redisCacheService)
- {
- _redisCacheService = redisCacheService;
- }
- // 获取实体的异步方法
- public async Task<MyEntity> GetMyEntityAsync(int id)
- {
- var cache = _redisCacheService.GetDatabase();
- var key = $"MyEntity:{id}"; // 用 id 生成唯一的缓存键
- // 尝试从缓存中获取数据
- var cachedData = await cache.StringGetAsync(key);
- if (!string.IsNullOrEmpty(cachedData))
- {
- // 如果缓存中有数据,直接返回缓存的值
- return JsonConvert.DeserializeObject<MyEntity>(cachedData);
- }
- // 如果缓存没有数据,执行数据库查询(此处假设从数据库获取数据)
- MyEntity entityFromDb = await GetEntityFromDbAsync(id);
- // 如果数据库中找到了该数据,缓存并返回
- if (entityFromDb != null)
- {
- // 将从数据库获取的数据存入缓存
- await cache.StringSetAsync(key, JsonConvert.SerializeObject(entityFromDb), _cacheExpiration);
- }
- return entityFromDb;
- }
- // 假设此方法是从数据库中获取数据
- private Task<MyEntity> GetEntityFromDbAsync(int id)
- {
- // 模拟从数据库查询数据
- return Task.FromResult(new MyEntity { Id = id, Name = "Entity " + id });
- }
- }
复制代码 解释:
- 缓存加载:在 GetMyEntityAsync 方法中,起首利用 StringGetAsync 尝试从 Redis 缓存中读取数据。如果缓存中有数据,直接返回缓存的内容。
- 缓存失效:如果缓存未命中,方法会从数据库加载数据,并将其存入 Redis 缓存中,设置缓存的过期时间为 5 分钟。
- 缓存更新:在缓存更新时,应用程序会先从数据库加载数据,然后缓存该数据。如果缓存中已存在数据,旧的缓存将被新的数据覆盖。
2.6 使缓存数据失效
当应用程序更新数据库中的数据时,需要从缓存中删除该数据,克制缓存中存留过时的数据。下面是一个更新实体并使缓存失效的例子:- public async Task UpdateEntityAsync(MyEntity entity)
- {
- // 更新数据库中的实体
- await UpdateEntityInDbAsync(entity);
- // 从缓存中删除该实体
- var cache = _redisCacheService.GetDatabase();
- var key = $"MyEntity:{entity.Id}";
- await cache.KeyDeleteAsync(key); // 删除缓存中的条目
- }
- private Task UpdateEntityInDbAsync(MyEntity entity)
- {
- // 模拟更新数据库中的数据
- return Task.CompletedTask;
- }
复制代码 在更新数据库之后,我们从 Redis 缓存中删除该实体的缓存条目,确保下次从数据库加载时数据是最新的。
3. 性能与优化
在实现缓存端模式时,有一些细节需要特殊留意:
- 缓存过期时间:公道设置缓存过期时间非常紧张。如果缓存过期时间太短,应用程序会频仍地从数据库加载数据,浪费性能;如果过期时间太长,缓存中的数据可能会过时。建议根据数据的访问频率和变化频率来调解过期时间。
- 缓存淘汰策略:Redis 提供了多种缓存淘汰策略(如 LRU - 近来最少利用)。根据实际需求,可以配置 Redis 利用合适的淘汰策略,以确保缓存空间的有效利用。
4. 总结
通过实现缓存端模式,我们能够高效地将缓存与数据存储结合,优化应用性能。在 .NET Core 中,结合利用 Redis 和 StackExchange.Redis 库,我们可以按需加载数据到缓存中,并确保缓存的数据与数据存储中的数据保持同等。缓存端模式非常得当于读取频仍的数据,可以大幅淘汰数据库访问,提高系统的相应速率和可靠性。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |