• 缓存学习总结3(服务器内存缓存)推荐使用


    内存缓存就是一种把缓存数据放到应用程序内存中的机制,内存缓存中保存的是一系列的键值对,就像Dictionary类型一样,每个不同的缓存内容有不同的“缓存键”,每个缓存键对应一个“缓存值”。

    我们可以设置缓存的键值对,也可以根据缓存键取出缓存中保存的缓存值。

    内存缓存的数据保存在当前运行网站程序的内存中,是和进程相关的。

    对于ASP.NET Core MVC项目,框架会自动地注入内存缓存服务,而对于ASP.NET Core WebApi等没有自动注入内存缓存服务的项目,我们需要手动将内存缓存相关服务注册到依赖注入容器中。

    下面以ASP.NET Core WebApi项目为例,演示内存缓存的使用方法。

    内存缓存的使用

    1.创建ASP.NET Core WebApi项目

    2.项目添加nuget包的引用

    Microsoft.Extensions.Caching.Memory

    3.在Startup.cs中对MemoryCache服务注册到依赖注入容器中

    4. 创建控制器CacheTestController

    在构造方法中,对MemoryCache服务进行注入

    控制器中新建两个action:

    一个是常规的没有缓存功能,直接获取数据并返回的方法(Test);

    另一个是有缓存功能的方法(CacheTest),如果要查询的数据在缓存中存在,则直接返回,如果不存在则将数据查询后存入缓存并返回;

    控制器完成代码:

    1. using Microsoft.AspNetCore.Mvc;
    2. using Microsoft.Extensions.Caching.Memory;
    3. using System;
    4. namespace NetCoreWebApi.Controllers
    5. {
    6. [Route("api/[controller]/[action]")]
    7. [ApiController]
    8. public class CacheTestController : ControllerBase
    9. {
    10. private readonly IMemoryCache _memoryCache;
    11. public CacheTestController(IMemoryCache memoryCache)
    12. {
    13. _memoryCache = memoryCache;
    14. }
    15. ///
    16. /// 没有缓存功能的获取数据方法
    17. ///
    18. ///
    19. ///
    20. [HttpGet]
    21. public IActionResult Test(int bookId)
    22. {
    23. Console.WriteLine();
    24. Console.WriteLine($"开始执行Test方法,bookId={bookId}");
    25. return DataClass.GetData(bookId);
    26. }
    27. ///
    28. /// 有缓存功能的获取数据方法
    29. ///
    30. ///
    31. ///
    32. [HttpGet]
    33. public IActionResult CacheTest(int bookId)
    34. {
    35. Console.WriteLine();
    36. Console.WriteLine($"开始执行CacheTest方法,bookId={bookId}");
    37. var items = _memoryCache.GetOrCreate("Book" + bookId, (e) =>
    38. {
    39. return DataClass.GetData(bookId);
    40. });
    41. Console.WriteLine("把数据返回");
    42. return items;
    43. }
    44. }
    45. }

    DataClass类,模拟从数据库查询数据的操作:

    1. using Microsoft.AspNetCore.Mvc;
    2. using System;
    3. namespace NetCoreWebApi
    4. {
    5. public class DataClass
    6. {
    7. public static JsonResult GetData(int bookId)
    8. {
    9. Console.WriteLine("数据库被访问");
    10. //模拟从数据库查询数据
    11. return new JsonResult(new
    12. {
    13. bookId = bookId,
    14. bookName = BookName(bookId)
    15. });
    16. }
    17. public static string BookName(int bookId)
    18. {
    19. switch (bookId)
    20. {
    21. case 1:
    22. return "书籍1";
    23. case 2:
    24. return "书籍2";
    25. case 3:
    26. return "书籍3";
    27. default:
    28. return "没有查询到书籍名称";
    29. }
    30. }
    31. }
    32. }

    5.在页面对webapi接口进行调用

    调用没有缓存的方法,入参为1,调用两次,两次都查询了数据库。

    调用带有缓存的方法,入参为1,调用两次,只有第一次查询数据库,后面再调用就不会查询数据库,因为缓存中有值,直接从缓存把数据返回。

    这时候如果把入参改为2,又会去数据库中查询,因为缓存中只有1的记录,没有2的记录。 

    根据上面的方式,设置了缓存后,数据是不会自动过期的,除非重启服务器。

    但是在实际的应用中,数据是可能会被改变的。那么就有两种解决方法:

    1.在数据改变时,调用Remove或者Set来删除或者修改缓存(优点:及时)。

    2.设置过期时间,数据在一段时间内是被缓存的,到期时数据会失效,再次访问,数据又会被缓存起来,也可以保证数据的时效性。

    下面介绍方法2,设置数据的缓存过期时间。

    缓存过期时间策略

    1.绝对过期时间

    ICacheEntry的AbsoluteExpirationRelativeToNow属性,用来设置缓存项的绝对过期时间。

     调用结果:

     绝对过期就是在一段时间内缓存数据一直有效,过来这个时间段,缓存就失效。

    2.滑动过期时间

    只要在缓存没过期的时候被访问,缓存有效期自动更新为设置的时间长度。

    例如,缓存的滑动过期时间为10秒钟,在第9秒时被访问,那么缓存的有效期又更新为10秒,只要缓存一直被访问,那就永不过期;超过10秒仍未被访问,那么缓存就失效了。

    ICacheEntry的SlidingExpiration属性,用来设置缓存的滑动过期时间。

      调用结果:

     

    缓存穿透问题

    缓存穿透问题指的是访问的资源不存在,数据为null,导致所有访问都会去查询数据库,从而增加数据库压力的问题。

    下面这种写法会引起缓存穿透:

     因为当数据库中不存在查询的数据时,变量b为null,再次访问,又会去访问数据库 。

    使用GetOrCreate的写法对数据进行缓存,不会导致缓存穿透,因为查询结果虽然为null,但也会被放入缓存中。

     

    缓存雪崩问题

    缓存项集中过期,引起请求在一段时间内同时访问数据库,导致数据库压力增大,这样的现象称为缓存雪崩。

    解决缓存雪崩问题,可以在缓存的过期时间之上,增加一个随机的过期时间,避免在同一时间内大量缓存项同时失效。

     

  • 相关阅读:
    lvs负载均衡、LVS集群部署
    图论基础学习笔记
    使用Python绘制CPI和PPI曲线
    Vulnstack----5、ATT&CK红队评估实战靶场五
    Keil 无法烧写程序
    【java】基本数据类型、包装类、string之间的转换
    C++语法——make_heap、push_heap、pop_heap、sort_heap使用介绍
    前端工程搭建:
    使用Python进行广告点击率预测
    元数据介绍
  • 原文地址:https://blog.csdn.net/liangmengbk/article/details/126568278