net 缓存 学习

分类

缓存类型
类/接口存储位置适用场景并发行为过期策略优点缺点
内存缓存MemoryCache, IMemoryCache本地内存单机应用、Web API使用锁机制实现线程安全支持绝对过期和滑动过期快速访问
简单易用
支持过期策略
不支持分布式
应用重启数据丢失
分布式缓存IDistributedCache外部服务(如 Redis、SQL)微服务、集群部署、云原生应用取决于实现(如 Redis 支持高并发访问)支持绝对过期和滑动过期支持跨服务器共享
可持久化
可横向扩展
访问速度略慢于内存
需要额外配置和依赖
响应缓存[ResponseCache]、中间件内存或代理缓存静态页面、API 响应缓存由 HTTP 服务器或代理处理通过属性或 HTTP 头指定缓存时长降低服务器负载
提高响应速度
缓存粒度较粗
不适合频繁变化的数据
输出缓存OutputCache 中间件内存ASP.NET Core Web 应用使用锁机制实现线程安全支持标签、策略、依赖等高级缓存控制支持标签、策略、依赖
更灵活的缓存控制
仅适用于 Web 场景
需要 .NET 8+
自定义缓存自定义类或第三方库任意特殊业务需求取决于具体实现可自定义过期逻辑灵活可控
可结合业务逻辑
实现复杂度高
维护成本大

 内存缓存

内存缓存是将数据存储在应用程序的本地内存中,以便快速访问,避免频繁访问数据库或外部服务。它适用于单机应用或不需要跨服务器共享缓存的场景。

        Asp.net core 实例

        注册缓存服务

        在 Program.cs 或 Startup.cs 中

        builder.Services.AddMemoryCache();

        控制器中使用缓存
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;

[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{
    private readonly IMemoryCache _cache;

    public UserController(IMemoryCache cache)
    {
        _cache = cache;
    }

    [HttpGet("{id}")]
    public IActionResult GetUser(int id)
    {
        string cacheKey = $"User_{id}";
        if (!_cache.TryGetValue(cacheKey, out string userData))
        {
            // 模拟从数据库获取数据
            userData = $"用户{id} 的数据";

            // 设置缓存选项
            var cacheEntryOptions = new MemoryCacheEntryOptions()
                .SetSlidingExpiration(TimeSpan.FromMinutes(5)) // 滑动过期
                .SetAbsoluteExpiration(TimeSpan.FromMinutes(30)); // 绝对过期

            // 写入缓存
            _cache.Set(cacheKey, userData, cacheEntryOptions);
        }

        return Ok(userData);
    }
}
  • TryGetValue:尝试从缓存中获取数据
  • Set:如果缓存中没有,就设置缓存
  • SlidingExpiration:如果在 5 分钟内没有访问,则过期
  • AbsoluteExpiration:无论访问与否,30 分钟后强制过期

 控制台应用示例

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;

class Program
{
    static MemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
    static string cacheKey = "currentTime";

    static void Main(string[] args)
    {
        Console.WriteLine("开始并发缓存测试...");

        // 启动多个并发任务
        Parallel.For(0, 10, i =>
        {
            Task.Run(() => AccessCache(i));
        });

        Console.WriteLine("按任意键退出...");
        Console.ReadKey();
    }

    static void AccessCache(int threadId)
    {
        if (!_cache.TryGetValue(cacheKey, out string cachedTime))
        {
            lock (_cache) // 保证写入线程安全
            {
                if (!_cache.TryGetValue(cacheKey, out cachedTime))
                {
                    cachedTime = DateTime.Now.ToString("HH:mm:ss.fff");

                    var options = new MemoryCacheEntryOptions()
                        .SetSlidingExpiration(TimeSpan.FromSeconds(10))
                        .SetAbsoluteExpiration(TimeSpan.FromMinutes(1));

                    _cache.Set(cacheKey, cachedTime, options);
                    Console.WriteLine($"线程 {threadId}: 缓存未命中,写入时间 {cachedTime}");
                }
            }
        }
        else
        {
            Console.WriteLine($"线程 {threadId}: 缓存命中,读取时间 {cachedTime}");
        }
    }
}

 分布式缓存

 分布式缓存(Distributed Cache) 是一种将缓存数据存储在外部服务(如 Redis、SQL Server 等)中的机制,适用于多服务器部署、微服务架构或云原生应用。它通过实现 IDistributedCache 接口来提供统一的缓存访问方式。

实现方式NuGet 包名特点
RedisMicrosoft.Extensions.Caching.StackExchangeRedis高性能、支持持久化、适合大规模分布式系统
SQL ServerMicrosoft.Extensions.Caching.SqlServer易于集成、适合已有数据库环境
NCacheAlachisoft.NCache.OpenSource.SDK企业级缓存解决方案
Memcached第三方库,如 EnyimMemcachedCore轻量级、适合简单分布式缓存场景

 Asp.net core 实例

 配置服务

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379"; // Redis 连接字符串
    options.InstanceName = "SampleInstance";
});
使用缓存(在控制器或服务中)
using Microsoft.Extensions.Caching.Distributed;

public class MyService
{
    private readonly IDistributedCache _cache;

    public MyService(IDistributedCache cache)
    {
        _cache = cache;
    }

    public async Task<string> GetDataAsync()
    {
        string cacheKey = "myData";
        // 从缓存中获取数据
        string cachedData = await _cache.GetStringAsync(cacheKey);

        if (cachedData == null)
        {
            cachedData = $"数据生成时间:{DateTime.Now}";
            var options = new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
            };
            // 写入数据
            await _cache.SetStringAsync(cacheKey, cachedData, options);
        }

        return cachedData;
    }
}

问题和方案

问题描述方案
一致性问题多个节点同时读写缓存,可能导致数据不一致(如缓存穿透、缓存雪崩)使用消息队列、事件驱动架构、延迟双删策略
网络延迟相比本地内存缓存,访问分布式缓存需要网络通信,增加响应时间
缓存雪崩大量缓存同时过期,导致瞬间大量请求打到数据库,可能引发系统崩溃设置缓存过期时间随机化、使用多级缓存、限流
缓存穿透请求的数据在缓存和数据库中都不存在,导致每次都访问数据库使用布隆过滤器、缓存空值
缓存击穿热点数据在过期瞬间被大量请求同时访问,导致数据库压力激增使用互斥锁(如 Redis 的分布式锁)防止并发访问热点数据
可用性依赖分布式缓存服务(如 Redis)宕机或网络中断会影响整个系统的性能或可用性使用主从复制、哨兵模式、集群部署等高可用架构
数据同步复杂缓存与数据库之间的数据同步机制复杂,尤其是写操作后的失效策略
安全性问题分布式缓存暴露在网络中,可能面临未授权访问、数据泄露等风险

响应缓存

响应缓存(Response Caching) 是一种用于缓存 HTTP 响应的机制,目的是减少服务器负载、提高响应速度,尤其适用于静态内容或变化不频繁的 API 响应。

特性描述
缓存位置通常在客户端、代理服务器或中间件中缓存
控制方式通过 HTTP 头(如 Cache-Control)或 [ResponseCache] 特性控制
适用场景静态页面、公共 API、无需频繁更新的数据
不适用场景用户特定数据、频繁变化的内容、需要身份验证的请求

 ASP.NET Core 实例

 配置中间件

builder.Services.AddResponseCaching();

var app = builder.Build();
app.UseResponseCaching();
控制器中使用 [ResponseCache] 特性
[ApiController]
[Route("[controller]")]
public class WeatherController : ControllerBase
{
    [HttpGet]
    //Duration 缓存持续时间(秒)
    //Location 缓存位置(客户端、服务器、任意)
    //NoStore  是否禁止缓存(设置为 true 表示不缓存)
    [ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, NoStore = false)]
    public IActionResult GetWeather()
    {
        var result = new
        {
            Time = DateTime.Now.ToString("HH:mm:ss"),
            Temp = new Random().Next(15, 30)
        };

        return Ok(result);
    }
}

  • 响应缓存只缓存 GET 请求
  • 不缓存带有 Authorization 头的请求,除非显式允许。
  • 如果你需要更复杂的缓存策略(如标签、依赖、条件缓存),建议使用 Output Caching

 输出缓存

输出缓存(Output Caching) 是对传统响应缓存的增强,提供了更强大、更灵活的缓存控制能力,适用于 ASP.NET Core Web 应用。它可以缓存整个 HTTP 响应,并支持标签、策略、条件缓存等高级功能。

特性响应缓存 ([ResponseCache])输出缓存 (OutputCache)
缓存粒度控制器级别路由级别、标签级别
缓存位置客户端/代理服务器端(内存)
支持策略控制✅(基于策略)
支持标签清除
支持条件缓存✅(如基于查询参数)
.NET 版本要求.NET Core 2.0+.NET 8+

  .NET 8 实例

        启用中间件(Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOutputCache(); // 注册服务

var app = builder.Build();
app.UseOutputCache(); // 启用中间件
缓存一个 GET 路由

app.MapGet("/time", () =>
{
    return Results.Ok(new { Time = DateTime.Now.ToString("HH:mm:ss") });
})
.CacheOutput(p => p.Expire(TimeSpan.FromSeconds(30)));
//这个接口的响应将在服务器端缓存 30 秒,期间所有请求返回相同内容。
使用标签清除缓存
app.MapPost("/clear-cache", (IOutputCacheStore cache) =>
{
    return cache.EvictByTagAsync("time-tag");
});

app.MapGet("/time-tagged", () =>
{
    return Results.Ok(new { Time = DateTime.Now.ToString("HH:mm:ss") });
})
.CacheOutput(p => p.Expire(TimeSpan.FromSeconds(60)).Tag("time-tag"));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值