c#解决内存缓存的缓存雪崩和缓存穿透问题

c#解决内存缓存的缓存雪崩和缓存穿透问题

如何搭建内存缓存这里就不多说了,不会的可以看我上一篇文章
https://blog.csdn.net/Smooth_Sailing_/article/details/130563683

什么是缓存穿透

缓存穿透就是比如如下代码

     string cachekey = "book" + id;//定义id
            book? b = MemoryCache.Get<book?>(cachekey); //去缓存里面查找等于id的数据
            if (b == null)
            {
            //如果没有查到就把数据添加到缓存里面
                b = await Dbcontext.eee(id);

                MemoryCache.Set(cachekey, b);
            }

该代码的作用是通过id去缓存里面找数据,如果等于空就去数据库里面查数据,然后添加到缓存
如果我们传入的是一个数据库里面不存在的id呢,这样会导致循环找不到,数据库里面找不到缓存里面也找不到,如果你的查询是个很消耗数据库性能的查询,那么在有人恶意传不存在的id去循环调用你这个接口,就会造成数据库的性能问题,这就是缓存穿透
解决

   book? b= await  MemoryCache.GetOrCreateAsync("book"+id, async (e) => {
              
                return await Dbcontext.eee(id);
            });

该代码的作用是通过id去缓存里面找数据,如果没有找到就去数据库里面查数据,然后添加到缓存
用GetOrCreateAsync方法执行,GetOrCreateAsync会把null也当成一个值存到缓存里面

什么是缓存雪崩

缓存雪崩就是比如双十一搞活动,设置0点开始抢,我们需要优化数据库性能就会把商品都添加到缓存里面,所以需要设置一个缓存过期时间,比如是5秒的过期时间,我们每隔五秒就会去数据执行一次操作拿到数据,这样就会造成数据的压力很小,一会压力突然达到顶峰然后又降下去,然后又5秒到达顶峰
这就是缓存雪崩

如何解决 那就让这个过期时间设置为一个范围内的随机时间

    book? b= await  MemoryCache.GetOrCreateAsync("book"+id, async (e) => {
    
          e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
          //设置缓存数据绝对过期时间10秒过期
            
            });

上面代码是设置成了固定过期时间为10秒 我们把它设置为范围内的随机时间

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;

namespace 内存缓存.Controllers
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private readonly IMemoryCache MemoryCache;

        public ValuesController(IMemoryCache MemoryCache)
        {
            this.MemoryCache = MemoryCache;
        }

        [HttpGet]
        public object q123qq(int id)
        {

            book? result = Dbcontext.qq(id);
            if (result == null)
            {
                return NotFound();
            }
            else
            {
                return result;
            }
        }
        [HttpGet]
        public async Task<ActionResult<book?>> qqq(int id)
        {
            //string cachekey = "book" + id;
            //book? b = MemoryCache.Get<book?>(cachekey);
            //if (b == null)
            //{
            //    b = await Dbcontext.eee(id);

            //    MemoryCache.Set(cachekey, b);
            //}

            //book? result = Dbcontext.qq(id);
            //if (result == null)
            //{
            //    return NotFound();
            //}
            //else {
            //    return result;
            //}
            //GetOrCreateAsync 是异步调用 先到缓存中查询如果没有查询到就执行方法把数据添加到缓存
            Console.WriteLine($"开始执行GetOrCreateAsync查找id={id}");
            book? b= await  MemoryCache.GetOrCreateAsync("book"+id, async (e) => {
                Console.WriteLine($"没找到id={id}");
                //e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);//设置缓存数据绝对过期时间10秒过期
                //e.SlidingExpiration = TimeSpan.FromSeconds(10);//设置缓存数据滑动过期时间10秒过期
                //e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Random.Shared.Next(10,15));//设值绝对过期时间为10秒到15秒的随机时间
                //滑动过期时间的意思是每访问一次就续命一次,如果在规定的时间内没有访问就过期
                book? q= await Dbcontext.eee(id);
                if (q==null) { Console.WriteLine("没有找到数据"); }
                return q;
            });
            Console.WriteLine($"结果是{b}");
            if (b == null)
            {
                  return  NotFound("找不到数据");
            }
            else
            {
                return  b;
            }
        }
    }
    public class Dbcontext
    {
        public static Task<book?> eee(int id)
        {
            var q = qq(id);
            return Task.FromResult(q);
        }
        public static book? qq(int id)
        {
            switch (id) 
            {
                case 1:
                    return new book(1,"1");
                case 2:
                    return new book(2, "2");
                case 3:
                    return new book(3, "3");
                default: return null;
            }
        }
    }
    public record book(int id,string result);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值