缓存穿透了怎么办?
缓存穿透了怎么办?
对应缓存来说,命中率是它的生命线。
在缓存命中率低的情况下,大量查询请求会穿透缓存到数据库,因为数据库对于并发的承受能力有限,一旦数据库承受不了大量查询任务,就会导致查询变慢,导致大量的请求阻塞在数据库查询上,造成应用服务器的连接和线程资源被占满,最终导致系统崩溃。
什么是缓存穿透
缓存穿透,其实是指从缓存中没有找到数据,不得已查询数据库的情况。
少量的缓存穿透没问题,主要由如下几点原因:
- 一方面,缓存系统在容量上有限,不可能所有的数据都存储在缓存中
- 另外一方面,互联网系统遵守 8/2 法则,也叫 帕雷托法则,最重要的事情只占 20%, 数据库访问,经常访问 20% 的热点数据,还有 80% 不会被经常访问。
什么样的缓存穿透对象系统有害
少量的缓存穿透是不可避免的,但是大量的请求穿透请求到后端系统,会造成系统后端崩溃。
如何解决缓存穿透
假设有这样一种场景:通过userid 查询用户信息,缓存读写策略是先查缓存,后查数据库。如果数据并不存在,在缓存和数据库中都没查询到数据,因此不会回种数据,这样下次请求到来,还是会先查缓存后查数据库,这种场景下,请求就穿透到了数据库。
回种空值
最大的问题在于数据库中不存在用户的数据,这样无理查询多少次,数据库中用于都不会存在这个用户的数据,一直会出现缓存穿透,因此,可以当数据从数据库查询为空或者发生异常时,在缓存中回种一个空值,给空值设置一个较短的过期时间,让短时间内能够快速过期淘汰。
Object nullValue = new Object();
try {
Object valueFromDB= getFromDB(uid);//从数据库中查询数据
if(valueFromDB = null){
cache.set(uid, nullValue,10);//如果从数据库中查询到空值,就把空值写入
} else {
cache.set(uid, value FromDB, 1000);
}catch(Exception e){
cache.set(uid, nullValue, 10);
}
回种空值虽然能够阻挡大量的穿透请求,但是如果有大量的空值缓存,也就会浪费存储空间,就浪费缓存的存储空间。甚至会剔除掉另外一些已经把缓存的用户信息反而会造成命中率下降。
布隆过滤器
布隆过滤器可以用来判断一个元素是否存在一个集合中,这个算法由 二进制和 Hash 算法组成,它的基本思路:
我们把集合中的每一个值提供的 Hash 算法算出对应的 Hash 值,然后对Hash 值对数组长度取模后得到需要计入数组的索引值,并将数组这个位置的值从0改成1,再判断一个元素是否存在这个集合中,只需要将这个元素按照相同的算法计算出索引值。如果这个位置为1,就认为这个元素在集合中,否则不在集合中。
布隆过滤器
新建的用户需要写入数据库中,还更新布隆过滤器数组相应位置的值,当查询一个用户是否存在时,可以先查询布隆过滤器是否存在,如果不存在就直接返回,不需要查询数据库,这样的话可以极大的减少缓存穿透。
布隆过滤器有什么问题呢?我们下期聊!
- SQL Server安全(3/11):主体和安全对象(Principals and Securables)
- 在SQL Server里如何进行页级别的恢复
- 你可能不知道的字符比较中的“秘密”
- c++实现简单计算器
- re模块(正则表达式)
- Python学习——collections系列
- 为stackGan一个工程创建一个虚拟环境,python 2.7 tensorflow0.12-tensorflow 1.01
- linux 普通操作,查看资源使用情况
- Python 函数使用记录,join函数和os.path.join用法
- 01.SQLServer性能优化之----强大的文件组----分盘存储
- stackGan实验
- pyTorch基础入门练习
- 昨天遇到的几个常用函数
- 【深入浅出】一篇超棒的机器学习入门文章
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法