Redis穿透的解决方法—布隆过滤器

redis概述:
Redis是一个开源的Key-Value存储系统,其中Value支持String、list、set、hash、zset五种数据结构,这些数据都支持push/pop、add/remove、取交集并集、排序等丰富的操作,并且这些操作都是原子性的 。
与同为NoSQL型缓存数据库的memcached类似,Redis的数据都存在内存中,数据的运算都在内存中进行,不会发生IO,这也是Redis为什么这么快的一个原因;区别是Redis具备持久化方式,会周期性的把更新的数据写入磁盘(RDB)或者把修改操作追加写入记录文件中(AOF) 。
也就是说,Redis的数据存放在内存中,但Redis也支持持久化将数据存入磁盘或文件 。
Redis是单线程的,但是多任务并发时可以开启多个Redis,并且Redis支持主从同步,避免了宕机带来的影响,以及写时同步技术实现了数据读写分离(主机负责写入、从机负责读取) 。

ps:Redis的特点是单线程+多路IO复用
 
Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面 。但同时,它也带来了一些问题 。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解 。如果对数据的一致性要求很高,那么就不能使用缓存 。
另外的一些典型问题就是,缓存穿透、缓存雪崩和缓存击穿 。目前,业界也都有比较流行的解决方案 。本篇文章,来给大家讲解一下Redis穿透的解决方法—布隆过滤器
缓存穿透
缓存穿透,是指查询一个数据库一定不存在的数据 。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存 。如果数据库查询对象为空,则不放进缓存 。
Redis穿透的解决方法—布隆过滤器

文章插图
 
代码流程
  1. 参数传入对象主键ID
  2. 根据key从缓存中获取对象
  3. 如果对象不为空,直接返回
  4. 如果对象为空,进行数据库查询
  5. 如果从数据库查询出的对象不为空,则放入缓存(设定过期时间)
想象一下这个情况,如果传入的参数为-1,会是怎么样?这个-1,就是一定不存在的对象 。就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存 。假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库 。即便是采用UUID,也是很容易找到一个不存在的KEY,进行攻击 。
布隆过滤器(Bloom Filter)
它实际上是一个很长的二进制向量和一系列随机映射函数 。布隆过滤器可以用于检索一个元素是否在一个集合中 。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难 。
Redis穿透的解决方法—布隆过滤器

文章插图
 
布隆过滤器解决方法:
将数据库中所有的查询条件,放入布隆过滤器中,
当一个查询请求过来时,先经过布隆过滤器进行查,如果判断请求查询值存在,则继续查;如果判断请求查询不存在,直接丢弃 。
布隆过滤器原理
原理就是一个对一个key进行k个hash算法获取k个值,在比特数组中将这k个值散列后设定为1,然后查的时候如果特定的这几个位置都为1,那么布隆过滤器判断该key存在 。
布隆过滤器可能会误判,如果它说不存在那肯定不存在,如果它说存在,那数据有可能实际不存在;
Redis的bitmap只支持2^32大小,对应到内存也就是512MB,误判率万分之一,可以放下2亿左右的数据,性能高,空间占用率及小,省去了大量无效的数据库连接 。
【Redis穿透的解决方法—布隆过滤器】因此我们可以通过布隆过滤器,将Redis缓存穿透控制在一个可容范围内 。
 
Redis穿透的解决方法—布隆过滤器

文章插图
 




    推荐阅读