You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core多项目共享缓存失效问题解决方案咨询

解决跨服务缓存同步问题的方案

方案一:使用分布式缓存(推荐Redis)

这是最直接成熟的方案,将Web API和MVC的本地内存缓存替换为共享的Redis分布式缓存,从根源解决缓存不同步问题。

  • 改造步骤:
    1. 安装NuGet包:在Web API、MVC和DataAccess项目中安装Microsoft.Extensions.Caching.StackExchangeRedis
    2. 配置Redis连接:在两个项目的appsettings.json中添加连接字符串
      "Redis": {
        "ConnectionString": "localhost:6379"
      }
      
    3. 替换缓存服务注册:将原有的AddMemoryCache和自定义CacheService单例注册,改为注册Redis分布式缓存;若自定义CacheService依赖IMemoryCache,则替换为依赖IDistributedCache
      // 在Web API和MVC的Program.cs中
      builder.Services.AddStackExchangeRedisCache(options =>
      {
          options.Configuration = builder.Configuration["Redis:ConnectionString"];
      });
      builder.Services.AddSingleton<ICacheService, CacheService>();
      
    4. 调整缓存操作逻辑:由于分布式缓存存储字节数组,需在CacheService中添加序列化/反序列化处理(示例用System.Text.Json)
      public async Task SetCacheAsync<T>(string key, T value, TimeSpan expiration)
      {
          var json = JsonSerializer.Serialize(value);
          await _distributedCache.SetStringAsync(key, json, new DistributedCacheEntryOptions
          {
              AbsoluteExpirationRelativeToNow = expiration
          });
      }
      
      public async Task<T?> GetCacheAsync<T>(string key)
      {
          var json = await _distributedCache.GetStringAsync(key);
          return json == null ? default : JsonSerializer.Deserialize<T>(json);
      }
      
      public async Task RemoveCacheAsync(string key)
      {
          await _distributedCache.RemoveAsync(key);
      }
      
    改造后,Web API和MVC操作的是同一个Redis实例,缓存失效操作会自动同步。

方案二:基于HTTP通知的缓存同步

若暂时不想引入第三方缓存服务,可通过Web API主动通知MVC刷新缓存,适合小型项目场景。

  • 实现思路:
    1. 在MVC项目中添加内部缓存失效接口,仅允许Web API访问:
      [ApiController]
      [Route("internal/cache")]
      [Authorize(Policy = "AllowWebApiOnly")] // 需配置IP或密钥验证策略
      public class CacheInvalidationController : ControllerBase
      {
          private readonly IMemoryCache _memoryCache;
          private readonly ICacheService _cacheService;
      
          public CacheInvalidationController(IMemoryCache memoryCache, ICacheService cacheService)
          {
              _memoryCache = memoryCache;
              _cacheService = cacheService;
          }
      
          [HttpPost("clear")]
          public IActionResult ClearCache([FromBody] string cacheKey)
          {
              _memoryCache.Remove(cacheKey);
              _cacheService.RemoveCache(cacheKey);
              return Ok();
          }
      }
      
    2. 在Web API触发缓存失效的逻辑中,调用MVC的上述接口:
      private async Task NotifyMvcCacheInvalidation(string cacheKey)
      {
          using var httpClient = new HttpClient();
          var mvcBaseUrl = _configuration["MvcBaseUrl"]; // 从配置读取MVC地址
          await httpClient.PostAsJsonAsync($"{mvcBaseUrl}/internal/cache/clear", cacheKey);
      }
      
  • 缺点:依赖服务间网络连通性,若MVC重启或网络故障会导致缓存不同步,需额外维护权限验证逻辑。

方案三:使用消息队列(如RabbitMQ)

通过消息队列广播缓存失效事件,解耦Web API和MVC的依赖,适合稍大规模项目。

  • 实现步骤:
    1. 安装RabbitMQ客户端NuGet包RabbitMQ.Client
    2. Web API中发送缓存失效消息:
      public void PublishCacheInvalidation(string cacheKey)
      {
          var factory = new ConnectionFactory() { HostName = "localhost" };
          using var connection = factory.CreateConnection();
          using var channel = connection.CreateModel();
          channel.QueueDeclare(queue: "cache-invalidation", durable: false, exclusive: false, autoDelete: false, arguments: null);
          var body = Encoding.UTF8.GetBytes(cacheKey);
          channel.BasicPublish(exchange: "", routingKey: "cache-invalidation", basicProperties: null, body: body);
      }
      
    3. MVC中添加后台服务订阅消息队列,收到消息后清理缓存:
      public class CacheInvalidationService : BackgroundService
      {
          private readonly IMemoryCache _memoryCache;
          private readonly ICacheService _cacheService;
      
          public CacheInvalidationService(IMemoryCache memoryCache, ICacheService cacheService)
          {
              _memoryCache = memoryCache;
              _cacheService = cacheService;
          }
      
          protected override async Task ExecuteAsync(CancellationToken stoppingToken)
          {
              var factory = new ConnectionFactory() { HostName = "localhost" };
              using var connection = factory.CreateConnection();
              using var channel = connection.CreateModel();
              channel.QueueDeclare(queue: "cache-invalidation", durable: false, exclusive: false, autoDelete: false, arguments: null);
              var consumer = new EventingBasicConsumer(channel);
              consumer.Received += (_, ea) =>
              {
                  var cacheKey = Encoding.UTF8.GetString(ea.Body.ToArray());
                  _memoryCache.Remove(cacheKey);
                  _cacheService.RemoveCache(cacheKey);
              };
              channel.BasicConsume(queue: "cache-invalidation", autoAck: true, consumer: consumer);
              await Task.Delay(Timeout.Infinite, stoppingToken);
          }
      }
      
    4. 在MVC的Program.cs中注册后台服务:
      builder.Services.AddHostedService<CacheInvalidationService>();
      
  • 优点:解耦服务依赖,消息可持久化;缺点是需额外部署维护消息队列服务,复杂度高于Redis方案。

方案选择建议

  • 毕业设计优先推荐Redis方案:实现简单,符合实际开发主流技术,能体现技术能力;
  • 若不想引入第三方服务,可尝试HTTP通知方案,但需注意权限和可靠性;
  • 消息队列方案适合规模较大的项目,毕设时间充足可尝试,但会增加部署复杂度。

内容的提问来源于stack exchange,提问作者Erik Nikoyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 03:42:50