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

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跑崩溃。

图1-1

2、如何处理缓存穿透

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

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

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

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

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

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

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


图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);

    }

}



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 缓存是分布式系统中的重要组件,主要解决高并发,大数据场景下,热点数据访问的性能问题。提供高性能的数据快速访问。 一...
    AI乔治阅读 3,040评论 0 92
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,650评论 24 1,002
  • 李跳水是只河马。 我知道你一定会说,什么嘛!骗谁呢,图上这只分明是只没尾巴的大尾巴狼! 但李跳水真的是只河马。 它...
    吴也白阅读 337评论 17 14
  • 秋已过,秋风似乎吹的愈加凛冽,已经有些霜雪的味道,浸在这种西北彻骨的“金风”里,容易把人的神经泡得麻木,而其它的事...
    露枫阅读 253评论 0 2