Redis系列之布隆过滤器

本文讲解redis中海量数据去重利器布隆过滤器Bloom Filter,强烈建议先全文大概浏览一遍在进行操作,里面笔者遇到的坑大都记录了

1. windows安装make命令

如果想获取make编译好的redisbloom.so,在公众号算法小生中输入bloom即可

如果遇到没有文件扩展“.js”的脚本引擎错误,则进入到注册表,定位计算机\HKEY_CLASSES_ROOT.js,将.js中默认值改为为JSFile即可,我的电脑是WebStorm2021惹的祸

# 安装版本为3.8,OK
C:\Users\Administrator>make -v
GNU Make 3.82.90
2. 安装redis bloom2.4.2

进入解压后文件夹,执行make命令生成redisbloom.so文件

$ make
Makefile:20: deps/readies/mk/main: No such file or directory
Makefile:197: /defs: No such file or directory
Makefile:224: /rules: No such file or directory
make: *** No rule to make target '/rules'.  Stop.

到github上找到deps/readies下载下来依赖的文件https://github.com/RedisLabsModules/readies/archive/refs/heads/master.zip解压到缺失目录中,对于t-digest-c也是同样,其实也可以根据git submodule update --init --recursive切换下载对应版本也可以,不过github很慢

# 再次执行命令,查看对应位置代码,发现我们make版本太低,至少为4,好吧,老老实实安装linux版本make4.4版本吧,windows没找到
$ make
deps/readies/mk/main:6: *** GNU Make version is too old. Aborting..  Stop.
  • 以下步骤为linux安装make4.4版本
make -v
wget http://ftp.gnu.org/gnu/make/make-4.4.tar.gz
tar -zxvf make-4.4.tar.gz
cd make-4.4
./configure
make install
which make
/usr/local/bin/make -v
cd /usr/bin
mv make make3.8
ln -s /usr/local/bin/make ./make
make -v
[root@iZuf6fjdhecwn46n83l0hqZ bin]# make -v
GNU Make 4.4
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
wget https://github.com/RedisBloom/RedisBloom/archive/refs/tags/v2.4.2.tar.gz
tar -zxvf v2.4.2.tar.gz
cd RedisBloom-2.4.2/
cd deps/readies/
wget https://github.com/RedisLabsModules/readies/archive/refs/heads/master.zip
unzip master.zip
mv readies-master/* .
rm -rf master.zip readies-master/
cd ../..
# centos7安装gcc
yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake

还有可能遇到cmake版本问题,自行升级吧

// 对于该错误,试过网上几个版本不可以,最后直接改源码,在make就通过了
/root/RedisBloom-2.4.2/deps/t-digest-c/src/tdigest.c:291:5: error:for’ loop initial declarations are only allowed in C99 mode
     for (int it = 0; it < n - 1; it++) {
     ^
  • 成品redisbloom.so
[root@iZuf6fjdhecwn46n83l0hqZ RedisBloom-2.4.2]# make
Building /root/RedisBloom-2.4.2/bin/linux-x64-release/t-digest-c/src/libtdigest_static.a ...
Building /root/RedisBloom-2.4.2/bin/linux-x64-release/t-digest-c/libtdigest_static.a ...
Scanning dependencies of target tdigest_static
[ 50%] Building C object src/CMakeFiles/tdigest_static.dir/tdigest.c.o
[100%] Linking C static library libtdigest_static.a
[100%] Built target tdigest_static
Compiling deps/bloom/bloom.c...
Compiling deps/murmur2/MurmurHash2.c...
Compiling deps/rmutil/util.c...
Compiling src/rebloom.c...
Compiling src/sb.c...
Compiling src/cf.c...
Compiling src/rm_topk.c...
Compiling src/rm_tdigest.c...
Compiling src/topk.c...
Compiling src/rm_cms.c...
Compiling src/cms.c...
Linking /root/RedisBloom-2.4.2/bin/linux-x64-release/redisbloom.so...
3. 修改docker-compose.yml文件及redis.conf
version: '3'
services:
  redis:
    network_mode: bridge
    container_name: redis
    image: redis:7.0.5-alpine3.16
    ports:
      - 6379:6379
    command: redis-server /usr/local/redis/conf/redis.conf
    volumes:
      - ./data:/data
      - ./conf/redis.conf:/usr/local/redis/conf/redis.conf
      - ./module/redisbloom.so:/usr/local/redis/module/redisbloom.so
    sysctls: 
      - net.core.somaxconn=1024
    privileged: true
    environment:
      - TZ=Asia/Shanghai
      - LANG=en_US.UTF-8

# redis.conf中加载布隆过滤器
loadmodule /usr/local/redis/module/redisbloom.so

很抱歉,到此为止无法加载redisbloom.so,缺少依赖,懒的在镜像中下载了,还是老老实实在刚刚的linux上下载linux,配置redis.conf,加载布隆过滤器吧,真是个悲伤的故事

4. linux中安装redis7及加载模块
wget https://github.com/redis/redis/archive/7.0.5.tar.gz
tar -zxvf redis-7.0.5.tar.gz
cd redis-7.0.5
make
make install
# 修改redis.conf新增loadmodule /usr/local/redis/module/redisbloom.so后启动
./src/redis-server redis.conf
5. 重启redis并运行基本命令
# 添加
127.0.0.1:6379> bf.add url shenjian.online
(integer) 0
# 判断是否存在
127.0.0.1:6379> bf.exists url shenjian.online
(integer) 1
127.0.0.1:6379> bf.exists url fangjia.com
(integer) 0
5. 原理介绍

布隆过滤器(Bloom Filter)是一个高空间利用率的概率性数据结构,由二进制向量(即位数组)和一系列随机映射函数(即哈希函数)两部分组成。
布隆过滤器使用exists()来判断某个元素是否存在于自身结构中。当布隆过滤器判定某个值存在时,其实这个值只是有可能存在;当它说某个值不存在时,那这个值肯定不存在,这个误判概率大约在 1% 左右。

  • 添加元素原理
    布隆过滤器主要由位数组和一系列 hash 函数构成,其中位数组的初始状态都为 0。

2

当使用布隆过滤器添加 key 时,会使用不同的 hash 函数对 key 存储的元素值进行哈希计算,从而会得到多个哈希值。根据哈希值计算出一个整数索引值,将该索引值与位数组长度做取余运算,最终得到一个位数组位置,并将该位置的值变为 1。每个 hash 函数都会计算出一个不同的位置,然后把数组中与之对应的位置变为 1。通过上述过程就完成了元素添加(add)操作。

  • 判定元素是否存在原理
    当我们需要判断一个元素是否存时,其流程如下:首先对给定元素再次执行哈希计算,得到与添加元素时相同的位数组位置,判断所得位置是否都为 1,如果其中有一个为 0,那么说明元素不存在,若都为 1,则说明元素有可能存在。
  • 为什么是可能“存在”
    那些被置为 1 的位置也可能是由于其他元素的操作而改变的。比如,元素1 和 元素2,这两个元素同时将一个位置变为了 1(图1所示)。在这种情况下,我们就不能判定“元素 1”一定存在,这是布隆过滤器存在误判的根本原因。
Redis 中实现布隆过滤器可以通过多种方式完成,主要包括使用 Redis 的位图(Bitmap)功能或借助 RedisBloom 模块。以下是详细的实现步骤和方法: ### 使用 Redis 的位图(Bitmap)手动实现布隆过滤器 1. **初始化布隆过滤器** 选择一个足够大的位数组,并通过多个哈希函数映射到不同的索引位置。通常可以使用多个哈希函数生成多个索引,以减少哈希冲突的概率。 2. **添加元素** 当向布隆过滤器中添加一个元素时,使用多个哈希函数对该元素进行哈希运算,得到多个索引值。然后将这些索引位置的位设置为 `1`。例如,使用 Java 和 RedisTemplate 设置位图中的某个位置为 `1`: ```java redisTemplate.opsForValue().setBit(redisKey, index, Boolean.TRUE); ``` 这里 `redisKey` 是布隆过滤器Redis 中的键名,`index` 是通过哈希计算得到的位数组索引。 3. **查询元素是否存在** 查询时,同样使用相同的哈希函数计算出多个索引值,并检查这些索引位置的位是否都为 `1`。如果其中任意一个位置的位为 `0`,则可以确定该元素一定不存在;如果所有位置的位都为 `1`,则该元素可能存在(存在误判的可能性)。 ```java boolean exists = redisTemplate.opsForValue().getBit(redisKey, index); ``` 4. **哈希函数的选择** 为了降低哈希冲突的概率,推荐使用低碰撞的哈希算法,如 MurmurHash3。Java 中可以通过 `Math.abs(key.hashCode())` 来获取哈希值,并结合 `Math.pow(2, 32)` 来限制索引范围。 ### 使用 RedisBloom 模块实现布隆过滤器 RedisBloom 是 Redis 的一个模块,专门用于实现布隆过滤器和其他概率数据结构。它提供了更高效的实现和更简单的接口。 1. **安装 RedisBloom 模块** 首先需要安装 RedisBloom 模块。可以通过 Redis 的模块加载机制将 RedisBloom 加载到 Redis 实例中。 2. **创建布隆过滤器** 使用 `BF.RESERVE` 命令创建一个新的布隆过滤器,指定误判率和预期插入的元素数量: ```bash BF.RESERVE my_filter 0.01 1000 ``` 这里 `my_filter` 是布隆过滤器的名称,`0.01` 是期望的误判率,`1000` 是预期插入的元素数量。 3. **添加元素** 使用 `BF.ADD` 命令将元素添加到布隆过滤器中: ```bash BF.ADD my_filter "user123" ``` 4. **查询元素是否存在** 使用 `BF.EXISTS` 命令检查某个元素是否存在于布隆过滤器中: ```bash BF.EXISTS my_filter "user123" ``` 返回值为 `1` 表示元素可能存在,返回值为 `0` 表示元素一定不存在。 ### 注意事项 - **误判率控制**:布隆过滤器的误判率与位数组的大小和哈希函数的数量有关。增加位数组的大小或使用更多的哈希函数可以降低误判率,但会占用更多的内存。 - **哈希冲突**:为了避免哈希冲突,建议使用低碰撞的哈希算法,如 MurmurHash3。 - **持久化**:为了防止数据丢失,可以配置 Redis 的持久化策略(如 RDB 或 AOF)。 - **集群部署**:RedisBloom 支持集群模式,手动实现布隆过滤器时需要自行处理分片问题。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小生Đ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值