五维思考

学习要加,骄傲要减,机会要乘,懒惰要除。 http://www.5dthink.cn

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

缓存是一种开发时常用的性能优化手段,.Net自带内存缓存(MemoryCache)可以很方便的使用,下面列出简单用法。

首先通过NuGet添加 Microsoft.Extensions.Hosting、Microsoft.Extensions.Caching.Memory 这两个包。

添加命令:

Install-Package Microsoft.Extensions.Caching.Memory
Install-Package Microsoft.Extensions.Hosting

向缓存中添加数据:

memoryCache.Set(dog.Name, dog, options);

从缓存获取数据(可以直接使用泛型方法指定返回类型):

memoryCache.Get<Dog>(key);

添加时可以使用 await memoryCache.GetOrCreateAsync()方法完成,该方法可以在缓存中没有数据时另外处理获取数据的方式,并将结果添加进缓存中。

一、示例代码

internal class CacheDemo
{
    //该集合当做数据源
    static IEnumerable<Dog> dogs;
    //全局容器
    static IHost host;
    public static async Task DemoMain()
    {
        //向容器添加缓存服务
        host = Host.CreateDefaultBuilder()
            .ConfigureServices(services => services.AddMemoryCache())
            .Build();

        //向数据源填充数据
        dogs = GetDogs().ToList();
        //缓存配置
        MemoryCacheEntryOptions cacheOptions = new()
        {
            //设置缓存10秒过期
            AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10)
        };

        //循环查询缓存中是否有对应数据
        foreach (Dog dog in GetDogs())
        {
            var dogResult = await GetDogAsync(dog.Name);
            Console.WriteLine($"查询结果1:{dogResult}");
        }

        var dogResult2 = GetCacheData("泰迪");
        Console.WriteLine($"查询结果2:{dogResult2}");
        Console.WriteLine("等待11秒缓存过期后再获取");
        await Task.Delay(11000);
        var dogResult3 = GetCacheData("泰迪");
        Console.WriteLine($"查询结果3:{dogResult3}");
        //向缓存中添加泰迪
        SetCacheData(new Dog("泰迪", 1), cacheOptions);
        var dogResult4 = GetCacheData("泰迪");
        Console.WriteLine($"查询结果4:{dogResult4}");
        var dogResult5 = GetCacheData("吉娃娃");
        Console.WriteLine($"查询结果5:{dogResult5}");
    }
    
    /// <summary>
    /// 从缓存中获取数据
    /// 如果没有则从数据源获取并添加至缓存
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    private static async Task<Dog> GetDogAsync(string name)
    {
        //从容器中获取缓存服务
        IMemoryCache memoryCache = host.Services.GetRequiredService<IMemoryCache>();
        //查询缓存数据,没有则从数据源查询并添加至缓存
        var dogResult = await memoryCache.GetOrCreateAsync(name, t =>
        {
            t.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
            Console.WriteLine($"缓存中没有{name},查询集合数据!");
            Dog dog1 = dogs.SingleOrDefault(d => d.Name.Equals(name));
            return Task.FromResult(dog1);
        });
        return dogResult;
    }
    
    /// <summary>
    /// 向缓存中添加数据
    /// </summary>
    /// <param name="dog"></param>
    /// <param name="options"></param>
    private static void SetCacheData(Dog dog, MemoryCacheEntryOptions options)
    {
        //从容器中获取缓存服务
        IMemoryCache memoryCache = host.Services.GetRequiredService<IMemoryCache>();
        memoryCache.Set(dog.Name, dog, options);
    }
    
    /// <summary>
    /// 缓存中获取数据
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    private static Dog GetCacheData(string key)
    {
        //从容器中获取缓存服务
        IMemoryCache memoryCache = host.Services.GetRequiredService<IMemoryCache>();
        return memoryCache.Get<Dog>(key);
    }

    /// <summary>
    /// 获取所有可爱的狗
    /// </summary>
    /// <returns></returns>
    private static IEnumerable<Dog> GetDogs()
    {
        yield return new Dog("泰迪", 1);
        yield return new Dog("吉娃娃", 2);
        yield return new Dog("哈士奇", 3);
        yield return new Dog("罗威纳", 4);
    }
}
/// <summary>
/// 狗类
/// </summary>
/// <param name="Name"></param>
/// <param name="Id"></param>
internal record Dog(string Name, int Id);

输出结果:

缓存中没有泰迪,查询集合数据!
查询结果1:Dog { Name = 泰迪, Id=1 }
缓存中没有吉娃娃,查询集合数据!
香询结果1:Dog { Name = 告娃娃, Id=2 }
缓存中没有哈士奇,查询集合数据!
查询结果1:Dog { Name = 哈士奇, Id=3 }
缓存中没有罗威纳,查询集合数据!
香询结果1:Dog { Name = 罗威纳, Id=4 }
查询结果2:Dog { Name = 泰迪, Id=1 }
等待11秒缓存过期后再获取
查询结果3:
查询结果4:Dog { Name = 泰迪, Id=1 }
查询结果5:

二、常见问题

1、缓存雪崩

是指同一时间大量缓存失效, 导致大量请求发向后端服务。向缓存添加数据时,时间可以设置一定范围的随机时间,这是一种避免出现缓存雪崩的简单方法。

2、缓存击穿

是指热点缓存失效,导致查询该热点数据的请求大量查询后端服务。如果业务场景允许,可以每次延长缓存时间或者设置为不过期。也可以使用单独的任务来维护热点数据缓存。

3、缓存穿透

是指大量不存在的数据请求(比如恶意请求)进行查询,此时缓存和后端服务中都没有这些数据,浪费大量资源。这个时候使用布隆过滤器是个很好的选择。

posted on 2022-05-23 15:48  五维思考  阅读(285)  评论(0编辑  收藏  举报

QQ群:1. 全栈码农【346906288】2. VBA/VSTO【2660245】