缓存穿透和缓存雪崩

缓存穿透和缓存雪崩


缓存穿透

  • 概念

    所谓缓存穿透就是说在缓存中不存在,然后直接在数据库中查询的现象,图例如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ih0ayfgO-1578143845324)(D:\学习总结\redis\缓存穿透.png)]

  • 场景

    一般来说,缓存穿透的场景发生在故意攻击的场景下;比如说,本来查询意见商品的序号是正数,但是请求方总是请求大量的负数过来,导致缓存无效,全部流量都打在了数据库中,如果某一时刻流量过大,则会导致数据库崩溃;

  • 解决方案

    • 方案一:布隆过滤器
      • 布隆过滤器会判断某个元素是否在某个几个中,相关的知识点会专门去介绍。
    • 方案二:缓存空值
      • 可以把一些不符合要求的数据的key值设置为NULL,这样就不会一直去查数据库了但是需要设置过期时间;

    最好就是在redis前面加一个布隆过滤器,这样很降低缓存穿透的概率;

  • 伪代码

    ////方案一
    //伪码
    string penetrate1(int ID,string str)
    {
        
        //使用布隆过滤器,后续专门写一篇博客
        if(存在)
        {
            redis操作
        }
        else
        {
            return NULL;
        }
        
    }
    ////方案二
    //伪码
    string penetrate1(int ID,string str)
    {
        //假设可以就是ID
        int CacheTime = 30;
        string CacheValue;
        char cmd[128];
        char sql[128];
        memset(cmd,0,sizeof(cmd));
        memset(sql,0,sizeof(sql));
        sprintf(cmd,"get %d",ID);
        redisReply* replay = (redisReply*)redisCommand(conn,cmd);
        if(replay->type == REDIS_REPLY_ERROR)
        {
            //查询数据库
            mysql_query(&mysql,sql);
            MYSQL_RES *result= mysql_store_result(&mysql);
            int row = mysql_num_rows(result);
            //查询为空
            if(row < 0)
            {
                //设置默认值
                memset(cmd,0,sizeof(cmd));
                sprintf(cmd,"set %d ''",ID);
                redisReply* replay = (redisReply*)redisCommand(conn,cmd);
            }
            //数据库数据同步到redis中
            //set XX XX
            redisReply* replay = (redisReply*)redisCommand(conn,cmd);
            //返回数据
            return 结果;
        }
        else
        {
            return replay->str;
        }
        
        
    
    }   
    

缓存雪崩

  • 概念
    所谓缓存雪崩就是在某一个时刻,缓存集大量失效。所有流量直接打到数据库上,对数据库造成巨大压力;

在这里插入图片描述

  • 场景

    基本我们能想到的场景就是一些电商抢购的现象,一般就是比如12点开始,在1点的时候大量同时失效,这个时候就会造成缓存雪崩的现象;

  • 解决方案

    • 方案一:加锁/队列

      • 加锁/队列;这样虽然能降低数据库压力,但是同时,响应也很慢
    • 方案二:缓存标记

      • 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存
    • 方案三:缓存过期时间错开

      • 设置缓存时间错开,可以在设置过期时间的时候,加一个一定范围内的随机值来错开

想了解学习更多C++后台服务器方面的知识,请关注:
微信公众号:C++后台服务器开发


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章