Redis07:布隆过滤器RedisBloom

1、布隆过滤器概念

1、布隆过滤器的由来

比如有如下几个需求:

有10亿个号码,现在又来了10万个号码,要快速准确判断这10万个号码是否在10亿个号码库中?

  • 解决办法一:将10亿个号码存入数据库中,进行数据库查询,准确性有了,但是速度会比较慢。

  • 解决办法二:将10亿号码放入内存中,比如Redis缓存中,这里我们算一下占用内存大小:10亿*8字节=8GB,通过内存查询,准确性和速度都有了,但是大约8gb的内存空间,挺浪费内存空间的。

那么对于类似这种,大数据量集合,如何准确快速的判断某个数据是否在大数据量集合中,并且不占用内存,布隆过滤器应运而生了。

2、布隆过滤器引发问题

缓存穿透:

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库

客户端从redis缓存中没有获取到数据,转身到了mysql中

缓存击穿:

key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

缓存雪崩:

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

缓存访问的过程如下:

(1)应用访问缓存,假如数据存在,则直接返回数据

在这里插入图片描述

(2)数据在redis不存在,则去访问数据库,数据库查询到了直接返回应用,同时把结果写回redis

在这里插入图片描述

(3)数据在redis不存在,数据库也不存在,返回空,一般来说空值是不会写入redis的,如果反复请求同一条数据,那么则会发生缓存穿透。

在这里插入图片描述
当然解决方案是可以为这个key设置一个空值,同时写入redis,下次请求的时候就不会访问数据库,但是如果每次请求的是不同的key,同时这个key在数据库中也是不存在的,那这样依然会发生缓存穿透。

3、布隆算法原理

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

布隆过滤器的思想是:创建一个超长的位阵列(Bit Array),默认所有bit位都为0,当有元素添加时,将元素通过不同的哈希算法获得一组下标,将位阵列中对应的下标改为1。判断元素是否存在时,只需要判断对应的bit位是否为1即可。

布隆过滤器的使用

用Google的guava包已经有了布隆过滤器算法的实现,注意的是布隆过滤器有一定的误判率,不可能达到100%的精准,首先初始化项目的时候从数据库查询出来所有的key值,然后放到布隆过滤器中

  1. 当应用访问的时候,先去布隆过滤器中判断kedy值,如果发觉没有key值不存在,直接返回
  2. 如果key值在布隆过滤器存在,则去访问redis,由于是有误判率的,所以redis也有可能不存在
  3. 那么这时候就去访问数据库,数据库不存在,那就直接返回空就行

如果误判率为3%,当有100万个请求同时过来的时候,布隆过滤器已经挡住了97万个请求,剩下3万个请求假如是误判的,这时候再访问数据库可以通过加锁的方式实现,只有竞争到锁了就去访问数据库,这样就完全可以解决缓存穿透问题

布隆过滤器的应用

比如说输入用户名的时候,可以马上检测出该用户名是否存在,黑名单机制,单词错误检测等

小结

如果布隆过滤器判断元素存在,则不一定存在,如果判断元素不存在,则一定不存在

2、案例演示

1、访问redis官网

redis英文官网才有moudle,点击module
redis官网:https://redis.io/modules
在这里插入图片描述

2、跳转到布隆过滤器的github网站

在这里插入图片描述

3、下载redis_bloom

[root@iZ2ze5v2vdwv6veyksylhxZ /]# cd /usr/local/ #切换目录
[root@iZ2ze5v2vdwv6veyksylhxZ local]# ls
aegis                        bin   games    lib      libiconv  nginx    share    yum-3.2.28
apache-tomcat-7.0.61         curl  include  lib64    man       openssl  src      yum-3.2.28.tar.gz
apache-tomcat-7.0.61.tar.gz  etc   jdk      libexec  mysql     sbin     tengine
[root@iZ2ze5v2vdwv6veyksylhxZ local]# mkdir redis_bloom #创建目录
[root@iZ2ze5v2vdwv6veyksylhxZ local]# ls 
aegis                        bin   games    lib      libiconv  nginx        sbin   tengine
apache-tomcat-7.0.61         curl  include  lib64    man       openssl      share  yum-3.2.28
apache-tomcat-7.0.61.tar.gz  etc   jdk      libexec  mysql     redis_bloom  src    yum-3.2.28.tar.gz
[root@iZ2ze5v2vdwv6veyksylhxZ local]# cd redis_bloom/
[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# ls
#wget 是一个从网络上自动下载文件的自由工具,支持通过 HTTP、HTTPS、FTP 三个最常见的 TCP/IP协议 下载,并可以使用 HTTP 代理
[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# wget https://github.com/RedisBloom/RedisBloom/archive/master.zip  #下载布隆过滤器
--2021-02-21 13:06:02--  https://github.com/RedisBloom/RedisBloom/archive/master.zip
Resolving github.com (github.com)... 52.74.223.119
Connecting to github.com (github.com)|52.74.223.119|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/RedisBloom/RedisBloom/zip/master [following]
--2021-02-21 13:06:06--  https://codeload.github.com/RedisBloom/RedisBloom/zip/master
Resolving codeload.github.com (codeload.github.com)... 54.251.140.56
Connecting to codeload.github.com (codeload.github.com)|54.251.140.56|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘master.zip’

    [             <=>                                               ] 114,160     35.7KB/s   in 3.1s   

2021-02-21 13:06:13 (35.7 KB/s) - ‘master.zip’ saved [114160]

[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# ls
master.zip
[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# 

4、下载unzip解压zip文件

[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# yum install unzip
Loaded plugins: fastestmirror, product-id, search-disabled-repos, subscription-manager

This system is not registered with an entitlement server. You can use subscription-manager to register.

Determining fastest mirrors
 * base: mirrors.cloud.aliyuncs.com
 * centos-sclo-rh: mirrors.huaweicloud.com
 * centos-sclo-sclo: mirrors.huaweicloud.com
 * extras: mirrors.cloud.aliyuncs.com
 * updates: mirrors.cloud.aliyuncs.com
base                                                                             | 3.6 kB  00:00:00     
centos-sclo-rh                                                                   | 3.0 kB  00:00:00     
centos-sclo-sclo                                                                 | 3.0 kB  00:00:00     
epel                                                                             | 4.7 kB  00:00:00     
extras                                                                           | 2.9 kB  00:00:00     
updates                                                                          | 2.9 kB  00:00:00     
(1/4): extras/7/x86_64/primary_db                                                | 224 kB  00:00:00     
(2/4): epel/x86_64/updateinfo                                                    | 1.0 MB  00:00:00     
(3/4): epel/x86_64/primary_db                                                    | 6.9 MB  00:00:00     
(4/4): updates/7/x86_64/primary_db                                               | 5.6 MB  00:00:00     
Package unzip-6.0-21.el7.x86_64 already installed and latest version
Nothing to do
[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# 

5、解压zip文件

[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# unzip master.zip  #解压文件
Archive:  master.zip
...
[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]# make
[root@iZ2ze5v2vdwv6veyksylhxZ redis_bloom]#cp bloom.so /usr/local/  #复制到目录/usr/local下

6、服务端启动布隆过滤器

[root@iZ2ze5v2vdwv6veyksylhxZ local]# redis-server --loadmodule /usr/local/redisbloom.so 
9577:C 21 Feb 2021 15:42:04.223 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
9577:C 21 Feb 2021 15:42:04.223 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=9577, just started
9577:C 21 Feb 2021 15:42:04.223 # Configuration loaded
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.0.9 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 9577
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

9577:M 21 Feb 2021 15:42:04.224 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
9577:M 21 Feb 2021 15:42:04.224 # Server initialized
9577:M 21 Feb 2021 15:42:04.224 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
9577:M 21 Feb 2021 15:42:04.224 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
9577:M 21 Feb 2021 15:42:04.224 * Module 'bf' loaded from /usr/local/redisbloom.so
9577:M 21 Feb 2021 15:42:04.225 * Ready to accept connections

7、客户端连接

Welcome to Alibaba Cloud Elastic Compute Service !

[root@iZ2ze5v2vdwv6veyksylhxZ ~]# cd /usr/local/bin/
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# ls
6379,log        cloud-init      easy_install      jsonschema        pcregrep         redis-sentinel
6380.log        cloud-init-per  easy_install-3.6  libmcrypt-config  pcretest         redis-server
6381.log        dump6379.rdb    easy_install-3.8  mcrypt            redis-benchmark
appendonly.aof  dump6380.rdb    jsondiff          mdecrypt          redis-check-aof
chardetect      dump6381.rdb    jsonpatch         muzhen_config     redis-check-rdb
cloud-id        dump.rdb        jsonpointer       pcre-config       redis-cli
[root@iZ2ze5v2vdwv6veyksylhxZ bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> BF.ADD k1 v1  #布隆过滤器在bitmap中添加元素
(integer) 1
127.0.0.1:6379> BF.EXISTS k1 v1 
(integer) 1   #返回值为1,代表元素有可能存在
127.0.0.1:6379> BF.EXISTS k1 v2
(integer) 0   #返回值为0,代表元素一定不存在
127.0.0.1:6379> 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值