解决Redis缓存穿透的利器之布隆过滤器

编程界的小学生

  • 一、有什么用
  • 二、是什么
  • 三、原理
  • 四、问题
  • 五、具体实现
    • 1、三种方式
    • 2、个人推荐
    • 3、redis-server集成布隆过滤器步骤
  • 六、总结
  • 七、个人公众号

一、有什么用

用来修复缓存穿透的利器。什么是缓存穿透?
面试必考的缓存穿透、雪崩、击穿

二、是什么

其实就是利用bitmap来解决缓存穿透的一种技术手段。

三、原理

  • 容器启动从数据库里读出全部商品,通过hash计算得到一个下标作为bitmap的位,将其置为1。
  • 用户搜商品的时候先经过hash计算得到位下标,然后去布隆过滤器里查看这个位下标的值是不是1,是1代表有商品,再去mysql查。若是0则直接返回没商品即可。(位的运算极其的快,性能消耗几乎忽略不计)
  • 可能多个商品通过hash计算得到的值一样,这就发生了hash碰撞,这也意味着布隆过滤器不是100%靠谱,可能漏掉某些商品,所以具体应用场景还得看业务需求是否允许。所以即使高并发场景也足够了。
    解决Redis缓存穿透的利器之布隆过滤器_第1张图片

这里是进行了三次不同的hash算法来减少hash碰撞的几率。

四、问题

  • 如何让碰撞几率更小?

可以让一个商品经过N次不同的hash方法计算,然后搜索商品的时候看N次hash值在bitmap里是不是都是1,有一个不是1就返回没有商品。几乎能保证99%+不碰撞。

  • 如果黑客攻击你,就是钻了个空子,搜了个ooxx,经过三次hash计算得到的位下标在bitmap里都是1,结果去查了db,db查完没有这商品。然后就一直利用ooxx刷你怎么破

你可以再加一层过滤,bitmap里都是1,mysql里没有的商品放到redis里,每次搜商品先去redis里查下是否存在,若存在则直接返回没有这个商品。

五、具体实现

1、三种方式

  • 客户端实现布隆算法以及自己存储bitmap

就是完全不借助redis,用自己的jvm内存来存储这块bitmap。
优点:算法自定义,定义几次算法都自己说了算。
缺点:占用内存过大的话会产生性能问题

  • 客户端实现布隆算法,然后数据存储交给redis,因为redis也是支持bitmap的

优点:算法自定义,定义几次算法都自己说了算。
缺点:占用内存过大的话会产生性能问题

  • 客户端啥也不管,redis实现布隆过滤器算法以及bitmap存储

这种需要redis server集成redisbloom.so模块
优点:省事,客户端啥也不用管
缺点:内置的布隆过滤器算法我们不知道,而且不能自定义不同算法

解决Redis缓存穿透的利器之布隆过滤器_第2张图片

2、个人推荐

个人推荐第2种方式,因为第一种方式的话所占用的内存是jvm内存,而第2种的话完美的将这块内存交给了缓存服务。第3种的话具体的布隆算法我们不知情,而且需要redis额外集成。第2种我们还以随意自定义hash算法,定义几个都是我们说了算。

3、redis-server集成布隆过滤器步骤

(1)https://redis.io/modules 找到RedisBloom
(2)点小房子,会打开这个网站https://github.com/RedisBloom/RedisBloom
(3)下载wget https://github.com/RedisBloom/RedisBloom/archive/master.zip
(4)执行如下命令

# 解压缩刚才的RedisBloom
unzip master.zip
cd master
# 编译安装
make
# make完生成redisbloom.so,拷贝到redis的安装目录(redis安装时make install的目录)
cp redisbloom.so /home/main/redis/redis5
# 修改redis配置文件,让其集成redisbloom.so
vim /etc/redis/redis_6379
# 集成redisbloom.so
loadmodule /home/main/redis/redis5/redisbloom.so
# 启动redis-server
redis-server  /etc/redis/redis_6379
# 客户端连接
redis-cli -p 6379 

# 会多出bf.命令,可以输入bf.然后按tab键查看有没有
# 比如我们bf.add ooxx abc,相当于给abc这个商品计算了一个位下标,且设置值为1
bf.add ooxx abc
# 这里就是客户端搜锁abc,我们这边判断是否存在这么一个商品,返回1就是存在
bf.exits ooxx abc
1
# 不存在sdfsdf,会返回0。这时候我们可以把sdfsdf单独存到redis,代表黑名单商品,搜索进来发现是这个直接返回没找到
bf.exits ooxx sdfsdf
0

六、总结

  • 面试必考的缓存穿透、雪崩、击穿
  • 原理
  • 问题
  • 具体实现

七、个人公众号

微信公众号【Java码农社区】
在这里插入图片描述

你可能感兴趣的:(redis,算法,redis,java,python,数据库)