zoukankan      html  css  js  c++  java
  • Redis 4.0的布隆过滤器插件

    还没有安装Redis的同学,可以参考我先前的文章安装,传送门《玩转Redis-Redis安装、后台启动、卸载》。Redis 4.0开始以插件形式提供布隆过滤器。

    # docker方式安装

    > docker pull redislabs/rebloom # 拉取镜像
    > docker run -p6379:6379 redislabs/rebloom # 运行容器
    > redis-cli # 连接容器中的 redis 服务

    # linux服务器直接安装

    >git clone git://github.com/RedisLabsModules/rebloom
    >cd rebloom
    >make
    # 当前路径会生成一个rebloom.so文件
    # 在redis的配置中(通常在/etc/redis/redis.conf)增加一行配置 loadmodule /"rebloom.so的绝对路径"/rebloom.so
    # 重启Redis即可

       上述的安装提到需要重启Redis,但是生产环境的Redis可不是你想重启就重启的。有什么方式可以不重启Redis就加载rebloom插件吗,MODULE LOAD命令就派上用场了。

    # 不重启Redis加载rebloom插件

    1、查看redis当前已加载的插件
    > MODULE LOAD /"rebloom.so的绝对路径"/redisbloom.so
    > module list
    1) 1) "name"
    2) "bf"
    3) "ver"
    4) (integer) 999999
    # 看到以上数据则说明redisbloom加载成功了,模块名name为"bf",模块版本号ver为999999。

    # 动态执行模块卸载
    # MODULE UNLOAD 模块名

    # 当然,为了防止Redis重启导致动态加载的模块丢失,我们还是应该在redis.conf 中加上相关配置。

    2.2、布隆过滤器的命令详解及示例
    完整指令说明可前往官网查看:https://oss.redislabs.com/redisbloom/Bloom_Commands/。

    2.2.1、Bloom命令简述
    【核心命令】添加元素:BF.ADD(添加单个)、BF.MADD(添加多个)、BF.INSERT(添加多个);

    【核心命令】检查元素是否存在:BF.EXISTS(查询单个元素)、BF.MEXISTS(查询多个元素)

    命令 功能 参数
    BF.RESERVE 创建一个大小为capacity,错误率为error_rate的空的Bloom BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion] [NONSCALING]
    BF.ADD 向key指定的Bloom中添加一个元素item BF.ADD {key} {item}
    BF.MADD 向key指定的Bloom中添加多个元素 BF.MADD {key} {item} [item…]
    BF.INSERT 向key指定的Bloom中添加多个元素,添加时可以指定大小和错误率,且可以控制在Bloom不存在的时候是否自动创建 BF.INSERT {key} [CAPACITY {cap}] [ERROR {error}] [EXPANSION expansion] [NOCREATE] [NONSCALING] ITEMS {item…}
    BF.EXISTS 检查一个元素是否可能存在于key指定的Bloom中 BF.EXISTS {key} {item}
    BF.MEXISTS 同时检查多个元素是否可能存在于key指定的Bloom中 BF.MEXISTS {key} {item} [item…]
    BF.SCANDUMP 对Bloom进行增量持久化操作 BF.SCANDUMP {key} {iter}
    BF.LOADCHUNK 加载SCANDUMP持久化的Bloom数据 BF.LOADCHUNK {key} {iter} {data}
    BF.INFO 查询key指定的Bloom的信息 BF.INFO {key}
    BF.DEBUG 查看BloomFilter的内部详细信息(如每层的元素个数、错误率等) BF.DEBUG {key}
    2.2.2、BF.RESERVE
    参数
    BF.RESERVE {key} {error_rate} {capacity}
    功能
    创建一个大小为capacity,错误率为error_rate的空的BloomFilter
    时间复杂度
    O(1)
    参数说明
    key:布隆过滤器的key;
    error_rate:期望的错误率(False Positive Rate),该值必须介于0和1之间。该值越小,BloomFilter的内存占用量越大,CPU使用率越高。
    capacity:布隆过滤器的初始容量,即期望添加到布隆过滤器中的元素的个数。当实际添加的元素个数超过该值时,布隆过滤器将进行自动的扩容,该过程会导致性能有所下降,下降的程度是随着元素个数的指数级增长而线性下降。
    可选参数
    expansion:当添加到布隆过滤器中的数据达到初始容量后,布隆过滤器会自动创建一个子过滤器,子过滤器的大小是上一个过滤器大小乘以expansion。expansion的默认值是2,也就是说布隆过滤器扩容默认是2倍扩容。
    NONSCALING:设置此项后,当添加到布隆过滤器中的数据达到初始容量后,不会扩容过滤器,并且会抛出异常((error) ERR non scaling filter is full)。
    返回值
    成功:OK;
    其它情况返回相应的异常信息。
    备注
    BloomFilter的扩容是通过增加BloomFilter的层数来完成的。每增加一层,在查询的时候就可能会遍历多层BloomFilter来完成,每一层的容量都是上一层的两倍(默认)。
    # 公众号@zxiaofan
    # 创建一个容量为5且不允许扩容的过滤器;
    127.0.0.1:6379> bf.reserve bf2 0.1 5 NONSCALING
    OK
    127.0.0.1:6379> bf.madd bf2 1 2 3 4 5
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1
    4) (integer) 1
    5) (integer) 1

    # 添加第6个元素时即提示BloomFilter已满;
    127.0.0.1:6379> bf.madd bf2 6
    1) (error) ERR non scaling filter is full
    127.0.0.1:6379> bf.info bf2
    1) Capacity
    2) (integer) 5
    3) Size
    4) (integer) 155
    5) Number of filters
    6) (integer) 1
    7) Number of items inserted
    8) (integer) 5
    9) Expansion rate
    10) (integer) 2

    2.2.3、BF.ADD
    参数
    BF.ADD {key} {item}
    功能
    向key指定的Bloom中添加一个元素item。
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:布隆过滤器的名字;
    item:待插入过滤器的元素;
    返回值
    元素不存在插入成功:返回1;
    元素可能已经存在:返回0;
    其它情况返回相应的异常信息。
    2.2.3、BF.MADD
    参数
    BF.MADD {key} {item} [item…]
    功能
    向key指定的Bloom中添加多个元素item。
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:布隆过滤器的名字;
    item:待插入过滤器的元素,可插入多个;
    返回值
    成功:返回一个数组,数组的每一个元素可能为1或0,当item一定不存在时数组元素值为1,当item可能已经存在时数组元素值为0。
    其它情况返回相应的异常信息。
    2.2.5、BF.EXISTS
    参数
    BF.EXISTS {key} {item}
    功能
    检查一个元素是否可能存在于key指定的Bloom中
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:布隆过滤器的名字;
    item:待检查的元素;
    返回值
    元素一定不存在:0;
    元素可能存在:1;
    其它情况返回相应的异常信息。
    2.2.6、BF.MEXISTS
    参数
    BF.MEXISTS [item…]
    功能
    检查多个元素是否可能存在于key指定的Bloom中
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:布隆过滤器的名字;
    item:待检查的元素,可设置多个;
    返回值
    成功:返回一个数组,数组的每一个元素可能为1或0,当item一定不存在时数组元素值为0,当item可能已经存在时数组元素值为1。
    其它情况返回相应的异常信息。
    # 公众号@zxiaofan
    # 向BloomFilter添加单个元素
    127.0.0.1:6379> bf.add bf1 itemadd1
    (integer) 1

    # 向BloomFilter批量添加多个元素
    127.0.0.1:6379> bf.madd bf1 itemmadd1 itemmadd2
    1) (integer) 1
    2) (integer) 1
    127.0.0.1:6379> bf.exists itemmadd1
    (error) ERR wrong number of arguments for 'bf.exists' command
    127.0.0.1:6379> bf.exists bf1 itemmadd1
    (integer) 1

    # 批量检查多个元素是否存在于BloomFilter
    127.0.0.1:6379> bf.mexists bf1 itemadd1 itemmadd1 itemmadd2
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1

    2.2.7、BF.INSERT
    参数
    BF.INSERT {key} [CAPACITY {cap}] [ERROR {error}] [EXPANSION expansion] [NOCREATE] [NONSCALING] ITEMS {item…}
    功能
    向key指定的Bloom中添加多个元素,添加时可以指定大小和错误率,且可以控制在Bloom不存在的时候是否自动创建
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:布隆过滤器的名字;
    CAPACITY:[如果过滤器已创建,则此参数将被忽略]。更多的信息参考<BF.RESERVE>;
    ERROR:[如果过滤器已创建,则此参数将被忽略]。更多的信息参考<BF.RESERVE>;
    expansion:布隆过滤器会自动创建一个子过滤器,子过滤器的大小是上一个过滤器大小乘以expansion。expansion的默认值是2,也就是说布隆过滤器扩容默认是2倍扩容。
    NOCREATE:如果设置了该参数,当布隆过滤器不存在时则不会被创建。用于严格区分过滤器的创建和元素插入场景。该参数不能与CAPACITY和ERROR同时设置。
    NONSCALING:设置此项后,当添加到布隆过滤器中的数据达到初始容量后,不会扩容过滤器,并且会抛出异常((error) ERR non scaling filter is full)。
    ITEMS:待插入过滤器的元素列表,该参数必传。
    返回值
    成功:返回一个数组,数组的每一个元素可能为1或0,当item一定不存在时数组元素值为1,当item可能已经存在时数组元素值为0。
    其它情况返回相应的异常信息。
    127.0.0.1:6379> del bfinsert
    (integer) 1

    127.0.0.1:6379> bf.insert bfinsert CAPACITY 5 ERROR 0.1 EXPANSION 2 NONSCALING ITEMS item1 item2
    1) (integer) 1
    2) (integer) 1
    127.0.0.1:6379> bf.exists bfinsert item5
    (integer) 0
    127.0.0.1:6379> bf.insert bfinsert CAPACITY 5 ERROR 0.1 EXPANSION 2 NONSCALING ITEMS item1 item2 item3 item4 item5
    1) (integer) 0
    2) (integer) 0
    3) (integer) 1
    4) (integer) 1
    5) (integer) 0
    127.0.0.1:6379> bf.add bfinsert item5
    (integer) 0
    127.0.0.1:6379> bf.info bfinsert
    1) Capacity
    2) (integer) 5
    3) Size
    4) (integer) 155
    5) Number of filters
    6) (integer) 1
    7) Number of items inserted
    8) (integer) 4
    9) Expansion rate
    10) (integer) 2
    127.0.0.1:6379> bf.add bfinsert item6
    (integer) 1
    127.0.0.1:6379> bf.add bfinsert item5
    (integer) 0
    127.0.0.1:6379> bf.exists bfinsert item5
    (integer) 1

    # 这里有个比较有意思的现象,item5未显示添加成功,但是后续却显示exists
    # 这说明发生了hash冲突,误判就是这样产生的。
    2.2.8、BF.SCANDUMP
    参数
    BF.SCANDUMP {key} {iter}
    功能
    对Bloom进行增量持久化操作(增量保存);
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:布隆过滤器的名字;
    iter:首次调用传值0,或者上次调用此命令返回的结果值;
    返回值
    返回连续的(iter, data)对,直到(0,NULL),表示DUMP完成。
    备注
    127.0.0.1:6378> bf.madd bfdump d1 d2 d3 d4 d5 d6 d7
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1
    4) (integer) 1
    5) (integer) 1
    6) (integer) 1
    7) (integer) 1
    127.0.0.1:6378> bf.scandump bfdump 0
    1) (integer) 1
    2) "ax00x00x00x00x00x00x00x01x00x00x00x05x00x00x00x02x00x00x00x8ax00x00x00x00x00x00x00Px04x00x00x00x00x00x00ax00x00x00x00x00x00x00{x14xaeGxe1zt?xe9x86/xb25x0e&@x00x00x00dx00x00x00x00x00x00x00x00"
    127.0.0.1:6378> bf.scandump bfdump 1
    1) (integer) 139
    2) "x80x00 x00$x00 x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x82$x04x00@x00x00x00x00x00x00x00x00x00x00x00x02x04x00x00x00x00x00x00x04x01@xa0x00@x00x00x00x00x00x10@x00x02"x00 x00x00x04x00x00x00x00x00 x00x80x00x00"x04x04x04x00x00x00x00x00x00x00x00x00x00x80x00x00x00x00x00 x80$x00 x00x00 x0c$x00x00x00`x00x00x00x00x00x00x00x00x80x02 x04x00x00x00x00x00"
    127.0.0.1:6378> bf.scandump bfdump 139
    1) (integer) 0
    2) ""
    2.2.9、BF.LOADCHUNK
    参数
    BF.LOADCHUNK {key} {iter} {data}
    功能
    加载SCANDUMP持久化的Bloom数据;
    时间复杂度
    O(log N),N是过滤器的层数。
    参数说明
    key:目标布隆过滤器的名字;
    iter:SCANDUMP返回的迭代器的值,和data一一对应;
    data:SCANDUMP返回的数据块(data chunk);
    返回值
    成功则返回OK。
    # Python 伪代码
    # 来源于:https://oss.redislabs.com/redisbloom/Bloom_Commands/

    chunks = []
    iter = 0
    # SCANDUMP
    while True:
    iter, data = BF.SCANDUMP(key, iter)
    if iter == 0:
    break
    else:
    chunks.append([iter, data])

    # LOADCHUNK
    for chunk in chunks:
    iter, data = chunk
    BF.LOADCHUNK(key, iter, data)
    2.2.10、BF.INFO
    参数
    BF.INFO {key}
    功能
    返回BloomFilter的相关信息;
    时间复杂度
    O(1);
    参数说明
    key:目标布隆过滤器的名字;
    返回值
    Capacity:预设容量;
    Size:实际占用情况,但如何计算待进一步确认;
    Number of filters:过滤器层数;
    Number of items inserted:已经实际插入的元素数量;
    Expansion rate:子过滤器扩容系数(默认2);
    127.0.0.1:6379> bf.info bf2
    1) Capacity
    2) (integer) 5
    3) Size
    4) (integer) 155
    5) Number of filters
    6) (integer) 1
    7) Number of items inserted
    8) (integer) 5
    9) Expansion rate
    10) (integer) 2
    2.2.11、BF.DEBUG
    参数
    BF.DEBUG {key}
    功能
    查看BloomFilter的内部详细信息(如每层的元素个数、错误率等);
    时间复杂度
    O(log N),N是过滤器的层数;
    参数说明
    key:目标布隆过滤器的名字;
    返回值
    size:BloomFilter中已插入的元素数量;
    每层BloomFilter的详细信息
    bytes:占用字节数量;
    bits:占用bit位数量,bits = bytes * 8;
    hashes:该层hash函数数量;
    hashwidth:hash函数宽度;
    capacity:该层容量(第一层为BloomFilter初始化时设置的容量,第2层容量 = 第一层容量 * expansion,以此类推);
    size:该层中已插入的元素数量(各层size之和等于BloomFilter中已插入的元素数量size);
    ratio:该层错误率(第一层的错误率 = BloomFilter初始化时设置的错误率 * 0.5,第二层为第一层的0.5倍,以此类推,ratio与expansion无关);
    # 公众号 @zxiaofan
    # 创建一个容量为5的BloomFilter,其key为“bfexp”;
    127.0.0.1:6379> bf.reserve bfexp 0.1 5
    OK

    # 查看BloomFilter的内部信息,此时BloomFilter的层数为1
    127.0.0.1:6379> bf.debug bfexp
    1) "size:0"
    2) "bytes:4 bits:32 hashes:5 hash64 capacity:5 size:0 ratio:0.05"

    127.0.0.1:6379> bf.madd bfexp 1 2 3 4 5
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1
    4) (integer) 1
    5) (integer) 1
    127.0.0.1:6379> bf.debug bfexp
    1) "size:5"
    2) "bytes:4 bits:32 hashes:5 hash64 capacity:5 size:5 ratio:0.05"

    127.0.0.1:6379> bf.madd bfexp 11 12 13 14 15
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1
    4) (integer) 0
    5) (integer) 1

    # 添加10个元素后,此时BloomFilter的层数变为2;
    # BloomFilter的元素数量为2层过滤器之和(5+4=9),添加“14”时实际因为hash冲突没添加成功;
    127.0.0.1:6379> bf.debug bfexp
    1) "size:9"
    2) "bytes:4 bits:32 hashes:5 hash64 capacity:5 size:5 ratio:0.05"
    3) "bytes:10 bits:80 hashes:6 hash64 capacity:10 size:4 ratio:0.025"

    127.0.0.1:6379> bf.madd bfexp 21 22 23
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1
    127.0.0.1:6379> bf.debug bfexp
    1) "size:12"
    2) "bytes:4 bits:32 hashes:5 hash64 capacity:5 size:5 ratio:0.05"
    3) "bytes:10 bits:80 hashes:6 hash64 capacity:10 size:7 ratio:0.025"
    127.0.0.1:6379> bf.madd bfexp 24 25
    1) (integer) 1
    2) (integer) 1
    127.0.0.1:6379> bf.debug bfexp
    1) "size:14"
    2) "bytes:4 bits:32 hashes:5 hash64 capacity:5 size:5 ratio:0.05"
    3) "bytes:10 bits:80 hashes:6 hash64 capacity:10 size:9 ratio:0.025"
    127.0.0.1:6379> bf.madd bfexp 31 32 33 34 35
    1) (integer) 1
    2) (integer) 1
    3) (integer) 1
    4) (integer) 1
    5) (integer) 1

    # 添加20个元素后,此时BloomFilter的层数变为3;
    127.0.0.1:6379> bf.debug bfexp
    1) "size:19"
    2) "bytes:4 bits:32 hashes:5 hash64 capacity:5 size:5 ratio:0.05"
    3) "bytes:10 bits:80 hashes:6 hash64 capacity:10 size:10 ratio:0.025"
    4) "bytes:23 bits:184 hashes:7 hash64 capacity:20 size:4 ratio:0.0125"

    原文链接:https://blog.csdn.net/u010887744/article/details/108700911

  • 相关阅读:
    【洛谷P3628】特别行动队
    【洛谷P3233】世界树
    【BZOJ1597】土地购买
    【洛谷P4068】数字配对
    【洛谷P3899】谈笑风生
    【BZOJ2726】任务安排
    【洛谷P6186】[NOI Online 提高组] 冒泡排序
    【洛谷P3369】【模板】普通平衡树
    【UOJ#8】Quine
    标准 插入flash
  • 原文地址:https://www.cnblogs.com/duanxz/p/14700288.html
Copyright © 2011-2022 走看看