.Net Core缓存及问题规避

目录

一、什么是缓存

二、客户端响应缓存

三、服务器端响应缓存

四、内存缓存

五、缓存穿透问题的规避

六、缓存雪崩问题的规避 

七、缓存数据混乱的规避

八、分布式缓存

 九、缓存方式的选择


一、什么是缓存

       缓存是系统优化中简单又以有效的工具,只要简单几行代码或者几个简单的配置,我们就可以利用缓存让系统的性能得到极大的提升。缓存是一个用来保存数据的区域,从缓存区域中度读取数据的速度比数据源读取数据的速度快很多。在从数据源获取数据之后,我们可以把数据保存在缓存中。下次再需要获取同样数据的时候,我们可以直接从缓存中获取之前保存的数据,而不需要再去数据源获取数据。

由于从缓存中读取数据的速度比从数据源中读取数据的速度更快,因此使用缓存能提高系统数据的获取速度。如果从缓存中获取了要获取的数据,就叫做“缓存命中”;多次请求中,命中的请求占全部请求的百分比叫做“命中率”;如果数据源中的数据保存到缓存后,发生了变换,就会导致“缓存数据不一致”。

二、客户端响应缓存

        RFC 7234是HTTP中对缓存进行控制的规范,其中重要的是cache-control响应报文头。假如浏览器向服务器请求/Person/1这个路径,如果服务器给浏览器端的响应报文头中cache-control的值为max-age=60,则表示服务器指示浏览器端“可以缓存这个响应内容60s”。在60s内,如果用户要求浏览器再次向/Person/1发送请求的话,浏览器就可以直接使用保存的缓存内容,而不是向服务器再次发出请求。

        在 ASP.NET Core 中,我们一一般不需要手动控制响应报文头中的cache-control,只要给需要进行缓存控制的控制器的操作大 方法添加ResponseCacheAttribute这个 Attribute即可,ASP.NET 
Core 会根据 ResponseCacheAttribu ite 的设置来生成合适的 cache-control响应报文头。

三、服务器端响应缓存

          如果我们在ASPNET Core 中安装了“响应缓存中间件”,ASP.NET Core 不仅会继续根据[ResponseCache]设置来生成 cache-control 响应报文头以设置客户端缓存,还会在服务器端也按照[ResponseCache]的设置来对响应进行服务器端缓存。如果有启用“响应缓存中间件”,那么当 A、B、C这3个浏览器分别向/Test1/Now 路径发送请求的时候,服务器端的 Now 方法会执行 3 次:如果启用了“响应缓存中间件”,当A、B、C这个浏览器分别向/Test1/Now 路径发送请求的时候,只要后面两次请求的时间在 60s 内,服务器端的 Now 方法只会执行1次,后两次请求虽然也会到达服务器,但是服务器会把第 1次响应的缓存内容直接返回,而不会执行 Now 方法。很显然,使用响应缓存中间件在服务器端实现响应缓存有两个好处:第一,提升没有实现缓存机制的客户端获取数据的速度,因为虽然请求仍然到达了服务器,但服器端缓存直接返回了缓存的响应,避免了从执行速度缓慢的数据源获取数据的性能问题;第二,对于实现了缓存机制的客户端也能降低服务器端的压力,因为如果没有启用响应缓存中间件,那么如果在短时间内服务器端收到了来自一万个不同客户端到/TestI/Now 的请求,那么 Now 方法仍然会行一万次,因为客户端的缓存是由每个客户端自己管理的:如果启用了响应缓存中间件,Now方法只会执行一次,这降低了服务器端的压力。
启用响应缓存中间件的步骤很简单,除了给控制器中需要进行缓存控制的操作方法标注[ResponseCache]之外,我们只要在ASP.NET Core项目的Program.cs的app.MapControllers之前加上app.UseResponseCaching即可。

四、内存缓存

       除了响应缓存中间件这样自动化的服务器端缓存机制之外,ASP.NET Core还提供了允许开发人员手动进行缓存管理的机制,内存缓存就是一种把缓存数据放到应用程序内存中的机制,内存缓存中保存的是一系列的键值对,就像 Dictionary 类型一样,每个不同的缓存内容有不同的“缓存键”,每个缓存键对应一个“缓存值”。我们可以设置缓存的键值对,也可以根据缓存键取出缓存中保存的缓存值。内存缓存的数据保存在当前运行的网站程序的内存中,是和进程相关的。因为在 Web服务器中,多个不同网站是运行在不同的进程中的,所以不同网站的内存缓存是不会互相干扰的而且网站重启后,内存缓存中的所有数据也就都被清空了。对于ASP.NET Core MVC 项目,框架会自动地注入内存缓存服务:对于ASP.NET Core WebAPI等没有自动注入内存缓存服务的项目,我们需要在 Program.cs 的 builder.Build 之前添builder.Services.AddMemoryCache 来把内存缓存相关服务注册到依赖注入容器中。

IMemoryCache接口中的一些方法

 

五、缓存穿透问题的规避

在使用内存缓存的时候,如果处理不当,我们容易遇到“缓存穿透”的问题。在IMemoryCache接口中有一个Get方法,它根据缓存键key查找缓存值,如果找不到缓存项,则方法会返回null等默认值,使用缓存的方法

 

六、缓存雪崩问题的规避 

在使用缓存的时候,有事会有在很短时间内,程旭把一大批数据从数据源加入缓存的情况。比如为了提升网站的运行速度,我们会对数据进行“预热”,也就是在网站启动的时候把一部分数据从数据库中读取出来并加入缓存。如果这些数据设置的过期时间都相同,到了过期时间的时候,缓存项会集中过期,因此优惠导致大量的数据库请求,这样数据库服务器就会出现周期性的压力,这种陡增的压力甚至会把数据库服务器“压垮”(崩溃),当数据库服务器从崩溃中恢复后,这些压力有过来了,从而造成数据库服务器反复崩溃,恢复,这就是数据库服务器的“雪崩”。

解决方法就是写缓存时,在基础过期时间之上,再加一个随机的过期时间这样缓存项的过期时间就会均匀地分布在一个时间段内。

七、缓存数据混乱的规避

在使用服务器端缓存的时候,如果处理不到程序,有可能造成缓存数据混乱等严重的问题。

 

       上面的代码使用“UserInfo”作为缓存键。当A 用户访问代码 7-33 所示的接口的时候,第5行代码查询到了A 用户的个人信息,然后数据被写入到缓存中;当B 用户也来访问这个接口的时候,由于缓存中已经存在缓存键为“Usernfo”的缓存内容,因此网站就直接把缓存中的数据返回给 B用户了,但是缓存中的用户信息是A用户的,这就造成了 B用户看到A用户信息的数据泄露问题。解决这种问题的核心就是要合理设置缓存的 ID。很显然,在代码中用缓存键“UserInfo”加上当前用户的ID就可以避免这个问题,也就是用 UserInfotuserld作为缓存键。

八、分布式缓存

       由于内存缓存把混的数据保存在web应用的内存中,因此数据的读写速度是非常快的,但是在分布式系统中这些缓存数据是不能共享的,因此集群中的每个节点中的web应用都要加载一份数据到自己的内存缓存中。

在NuGet安装Redis,然后注册Redis缓存

 然后要编写代码来通过IDistributedCache读写Redis中的缓存数据

 

 九、缓存方式的选择

.NET 中的缓存分为客户端响应缓存、服务器端响应缓存、内存缓存、分布式缓存等。缓存可以极大地提升系统的性能,在进行系统设计的时候,根据系统的特点选择合适的缓存方式。客户端响应缓存能够充分利用客户端的缓存机制,它不仅可以降低服务器端的压力,也能然提升客户端的操作响应速度并且降低客户端的网络流量。但是需要合理设置缓存相关参数,以避免客户端无法及时刷新到最新数据的问题。服务器端响应缓存能够乎不需要编写额外的代码就轻松地降低服务器的压力。但是由于服务器端响应缓存的启用条件比较苛刻,因此要根据项目的情况决定是否使用它。内存缓存能够降低数据库以及后端服务器的压力,而且内存缓存的存取速度非常快; 分式缓存能够让集群中的多台服务器共享同一份缓存,从而降低数据源的压力。如果集群节点的数量不多,并且数据库服务器的压力不大的话,推荐读者使用内存缓存,毕竟内存的读写速度比网络快很多;如果集群节点太多造成数据库服务器的压力很大的话,可以采用分布式缓存。无论是使用内存缓存还是分布式缓存,我们都要合理地设计缓存键,以免出现数据混乱。这些缓存方式并不是互斥的,我们在项目中可以组合使用它们。比如对于论坛系统,论坛首页中的版块信息变动不频繁,我们可以为版块信息的客户端响应缓存设置 24h 的过期时间;对于所有的帖子详情信息,我们同时启用内存缓存和分布式缓存,当加载帖子详情页面的数据的时候,我们先到内存缓存中查找,内存缓存中找不到再到分布式缓存中查找,这样就既可以利用内存缓存读取速度快的优点,也能利用分布式缓存的优点。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咬口大葱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值