开发者社区> 格子衫码农> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

关于缓存穿透以及简单的处理方式

简介: 1、什么是缓存穿透         缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
+关注继续查看

1、什么是缓存穿透

        缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

如图1-1为简单的通过缓存提高系统吞吐量的系统,访问请求会先通过去访问缓存,缓存中未找到的时候再去查询数据库,(此处提及一下,优化到极致的mysql的数据库连接为300-700之间,300为机械硬盘数据,700为固态硬盘数据)

        如果这个请求是一个比较消耗时间的sql,比如说电商中的查询总消费额这种,会消耗比较大的数据库资源,这种数据一般会放入缓存中,我们此处可以据一个例子sql:select sum(money) from order where userCode = '123';查询出来的数据,以userCode为key,以结果为value存入到缓存中,这种方法有一定的漏洞,如果我们找到一个根本就不存在的userCode,进行查询,这样的话每次查询都会绕过缓存,直接访问到数据库,只要我这边并发访问量稍微多一点,基本就能把mysql跑崩溃。

img_c370fe6d14cc86c107a3892ab021dfe8.png
图1-1

2、如何处理缓存穿透

        处理缓存穿透的方法有很多,其实无外乎就是对数据进行过滤筛选,把真正有效的数据进行访问,无效数据直接过滤掉。

        1、在某些特定场景下(登录),进行验证码,这种方法并不是很安全,因为目前图像识别技术在很大程度上能够解决验证码的问题,所以仅供简单使用。

        2、布隆过滤器:这个是需要着重说明的一种方法,

       首先我们需要对数据进行过滤,肯定要查询一下这个数据是否存在,比较简单的就是直接查询数据库,"select  userCount from user where userCode = '123';",但是其实这种意义并不大,因为查询的过程其实也是要建立数据库链接的,唯一优化的是查询这种查询语句速度更快,对于并发的数据量处理速度可能会快一点,但是当黑客攻击并发量再高一点的时候,此时这种方式可能也就扛不住了。

        此时我们该怎么处理呢?还是缓存,我们把代表数据标识位的数据放到缓存中,查询数据库之前先去缓存中查询一下是否存在如果数据存在的话,再做后续的操作。这种做法还算是比较有效的,但是唯一的缺点就是用户量比较大的时候讲所有的用户存储在内存中,对内存的负载压力太大,需要比较高的内存,很容易把内存撑爆。

        或者我们可以通过solr等搜索引擎这种方式进行搜索,这种方式后面再说。

        此处我们选用布隆过滤器进行查询,算法的简单图解如下图2-1:


img_ebffa59f7a97a8c05202b07062695694.png
图2-1

        因为我们只需要判断客户端传过来的userCode是否存在就可以,图中的hash1,hash2,hash3分别代表着三种不同的hash算法,你可以认为是md5,sha1,sha256等等,不同的userCode对应着不同的数据位,当需要校验的时候,判断每一种算法的得出来的byte位是否相同,只要一位不同,那么我们可以认为这个userCode不存在,直接返回就不存在就可以,这种方法就可以在很大程度上避免黑客攻击的情况。当然这种方法存在一定的风险,因为无论哪一种hash算法都会有hash碰撞,即使是几种算法在一块,仍会有这种可能(只不过是可能性非常小而已),在此需要根据具体的情况进行分析,而且一般情况下不能从布隆过滤器里面删除数据,还有就是创建布隆过滤器的时候byte数组的长度需要先确定初始化,这个数组长度和hash函数不太好确定。

        关于布隆过滤器的代码,这里可以推荐一款比较好用的java库,Google Guava

在此附上一个例程代码


package com.kevin.demo;

import com.google.common.base.Charsets;

import com.google.common.hash.BloomFilter;

import com.google.common.hash.Funnels;

import java.util.*;

/**

* google guava实现 bloom filter

* bitArray,numHashFunction,funnel,Strategy,put()

* demo实例

* 场景描述:100W字符放入布隆过滤器中,另外随机生成1W字符串,判断他们在100W里面是否存在

*/

public class demo {

private static final int insertions =1000000;//100W

    public static void main(String[] args) {

//创建一个布隆过滤器对象,初始化字符集和100W大小

        BloomFilter bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8),insertions);

        //初始化一个存储String数据的set,初始化大小100W

        Set sets =new HashSet(insertions);

        //初始化一个存储String数据的list,初始化大小100W

        List lists =new ArrayList(insertions);

        //向三个容器中初始化100W个随机数据

        for (int i =0; i

String uuid = UUID.randomUUID().toString();

            bf.put(uuid);

            sets.add(uuid);

            lists.add(uuid);

        }

int wrong =0;//纪录错误次数

        int right =0;//纪录正确次数

// 随机生成1W字符串

        for (int i =0; i <10000; i++) {

String test = i%100==0?lists.get(i/100):UUID.randomUUID().toString();//按照一定比例选择BF中肯定存在的

            if(bf.mightContain(test)){

if(sets.contains(test)){

right++;

                }else {

wrong++;

                }

}

}

        System.out.println("========right======="+right);

        System.out.println("========wrong======="+wrong);

    }

}



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
什么是缓存击穿、缓存穿透、缓存雪崩?如何解决?
什么是缓存击穿、缓存穿透、缓存雪崩?如何解决?
0 0
缓存经典问题:缓存穿透和缓存雪崩
在某些复杂的业务场景下,单纯依靠存储系统的性能提升不够的,典型的场景如下。
0 0
图解缓存击穿、缓存穿透、缓存雪崩的区别
在实际开发中会面临的缓存异常可能会出现三个问题,分别是缓存雪崩、缓存击穿和缓存穿透。这三个问题会导致大量请求从缓存转移到数据库,如果请求的并发量很大的话,就会导致数据库崩溃。那么,我们应该如何来应对呢? 下面就针对每种情况,提供相应的解决方案
0 0
没人告诉过你更复杂的缓存穿透怎么解决
你应该从网上看过太多的文章说缓存穿透怎么解决?无非就是布隆过滤器,缓存空值什么的。 但是,更深入的一个问题,缓存空值有没有问题?如果缓存的空值太多怎么办? 如果用的redis,那么太多的空值会不会打爆你的redis?如果用的本地缓存,会不会打爆你的内存?继而引发的问题就是还是会打爆你的数据库。
0 0
缓存击穿与缓存穿透的区别,如何记忆
缓存击穿与缓存穿透的区别,如何记忆
0 0
什么是redis缓存穿透、缓存击穿、缓存雪崩?如何解决?
缓存穿透:请求数据库中根本就不存在的数据,既然数据库中都没有,缓存中更没有,导致每次请求直接怼到数据库;
0 0
缓存穿透、并发和雪崩那些事
0 题记 缓存穿透、缓存并发和缓存雪崩是常见的由于并发量大而导致的缓存问题,本文讲解其产生原因和解决方案。 缓存穿透通常是由恶意攻击或者无意造成的;缓存并发是由设计不足造成的;缓存雪崩是由缓存同时失效造成的,三种问题都比较典型,也是难以防范和解决的。
1230 0
缓存穿透、缓存并发、缓存失效之思路变迁
我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题: 缓存穿透 缓存并发 缓存失效 一、缓存穿透 Paste_Image.png Paste_Image.png Paste_Image.png 注: 上面三个图会有什么问题呢? 我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。
600 0
+关注
格子衫码农
参与多个项目开发,涵盖电商、物联网等方向,为人谦逊,喜欢跟他们交流新技术发展,对待工作一丝不苟。
文章
问答
文章排行榜
最热
最新
相关电子书
更多
分布式高并发缓存6.0
立即下载
用户态高速块缓存方案
立即下载
低代码开发师(初级)实战教程
立即下载