Redis Module 实现布隆过滤器

Redis Module

Redis module 是Redis 4.0 之后支持的新的特性,这里不少国外牛逼的大学和机构提供了不少牛逼的Module 只要编译引入到Redis 中就能轻松的实现咱们某些需求的功能。在Redis 官方Module 中有一些咱们常见的一些模块,咱们在这里就作一个简单的使用。java

我的推荐能够尝试的git

  • neural-redis 主要是神经网络的机器学,集成到redis 能够作一些机器训练感兴趣的能够尝试
  • RedisSearch 主要支持一些富文本的的搜索
  • RedisBloom 支持分布式环境下的Bloom 过滤器

布隆过滤器

好比咱们存放某些数据的id属性,id属性经过K个Hash 函数,计算到bit(位数组)上面,把它们变成1。检索时,咱们只要看看这些点是否是都是1就(大约)知道集合中有没有它了:若是这些点有任何一个0,则被检元素必定不在;若是都是1,则被检元素极可能在。这就是布隆过滤器的基本思想。这个通常可使用在新闻推荐和缓存穿透的处理上面,效果很好。github

优势和缺点

优势

空间效率和查询时间都远远超过通常的算法,布隆过滤器存储空间和插入 / 查询时间都是常数O(k)。 另外, 散列函数相互之间没有关系,方便由硬件并行实现。 布隆过滤器不须要存储元素自己,在某些对保密要求很是严格的场合有优点。面试

缺点

  • 为何效率会那么高,是由于布隆过滤器牺牲了准备性和删除操做,布隆过滤器存在必定的误判几率。 好比咱们查询某个key ,经过K个hash 函数对应的位数组上面映射的都是1 ,但其实咱们的数据存储并无这个数据,因此存在必定误判。若是咱们用来作一个ip 黑名单的添加,可能就会存在必定的误判率。
  • 删除问题,咱们若是把数组某个位置设置为 1 或者是 0 ,那么识别会影响其它数据的判断,

实现

而对于咱们java 实现的bloom过滤器能够经过谷歌提供的guava ,可是咱们如今的系统大部分都是分布式系统,那么这种方式就不太合适,咱们可能会想把数据存放到一个分布式环境下的内存中,天然就会想到redis ,那么redis的那帮大神们天然确定也会想到,因此就有不少开源组织和我的研发了基于redis 的布隆过滤器。 那么首先介绍使用Redis Module 集成进RedisBloom。redis

  1. 下载官方的git 仓库文件 github.com/RedisBloom/…
  2. 好比在Linux 服务器上面能够直接经过git 拉取源码 git github.com/RedisBloom/…
  3. 进入下载好的目录 执行make 命令进行编译成so 库

  1. 接下来就很简单了,直接在redis.conf 配置文件里面,而后重启服务器
    loadmodule /opt/redis/redis-cluster/redisbloom.so
  2. 重启服务,进入 client 查看集成进来的module

相关bf 命令能够去https://github.com/RedisBloom/RedisBloom 查看

那么对与官网提供的其它模块的集成模式基本和RedisBloom同样,有兴趣的能够去尝试下,这样面试的时候能够提一下本身研究过这块,相信面试官会喜欢这样的面试人员。算法

那么若是用java 调用RedisBloom 先给你们看一下官网的实现方式。数组

// 核心仍是经过jedis客户端的方式,这种方式仍是笔者看它源码改写后的,官方提供的不支持redis 密码验证
pom 文件
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.0.0</version>
</dependency>

<dependency>
    <groupId>com.redislabs</groupId>
    <artifactId>jrebloom</artifactId>
    <version>2.0.0-SNAPSHOT</version>
</dependency>
<repositories>
    <repository>
        <id>snapshots-repo</id>
        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    </repository>
</repositories>

代码实现

public class RedisBloom {
    public static void main(String[] args) {
        JedisPoolConfig conf = new JedisPoolConfig();
        conf.setMaxTotal(100);
        conf.setTestOnBorrow(false);
        conf.setTestOnReturn(false);
        conf.setTestOnCreate(false);
        conf.setTestWhileIdle(false);
        conf.setMinEvictableIdleTimeMillis(60000L);
        conf.setTimeBetweenEvictionRunsMillis(30000L);
        conf.setNumTestsPerEvictionRun(-1);
        conf.setFairness(true);
        JedisPool jedisPool = new JedisPool(conf,"192.168.13.131",6379,30000,"123456");
        Client client = new Client(jedisPool);

        boolean exists = client.exists("newFilter", "foo55");
        System.out.println(exists);
        client.add("newFilter","123");
        client.add("newFilter","456");
        client.add("newFilter","789");
        client.close();
    }
}
复制代码

上面的这种实现方式比较复杂,下面给你们介绍一款redis 比较牛皮的客户端工具,可能你们据说过 Redission 框架,可能你们了解的是它实现分布式锁忒简单,这个框架提供了不少强大的功能, 好比分布式锁、令牌桶限流、分布式布隆过滤器,那么咱们就来爽一波缓存

<!-- 引入redisson -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.11.5</version>
        </dependency>
   
 
 编写 ReissonConfig
   /**
 * @Description
 * @Author gavin
 * @Since 1.0
 * @Date 2019/10/27
 */
@Configuration
public class RedissonConfig  {

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://192.168.13.132:6379")
        return Redisson.create(config);
    }
}
   
复制代码
// 分布式信号实现秒杀库存  利用ab 测试工具能够测试
    @GetMapping("/kill2")
    public void kill2(){
        RSemaphore semaphore = redissonClient.getSemaphore("number");
        // 默认抢到会减小一个
        boolean tryAcquire = semaphore.tryAcquire();
        if(tryAcquire){
            Integer number = redisUtil.get("number", Integer.class);
            if(number > 0){
                System.out.println("当前库存还剩:"+number+" 用户抢购成功");
            }
        }
    }
// 分布式环境下布隆过滤器的实现,很是的简单    
 @Test
 public void testBloomFilter() {
        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("newFilter2");
        // 初始化布隆过滤器,预计统计元素数量为55000000,指望偏差率为0.03
        bloomFilter.tryInit(55000000L, 0.03);
        bloomFilter.add("lisi");
        bloomFilter.add("wangwu");
        boolean foo = bloomFilter.contains("lisi343");
        System.out.println(foo);
    }
    
//  限流

  public void testRateLimiter() {
        RRateLimiter rateLimiter = redissonClient.getRateLimiter("myRateLimiter");
        // 初始化
        // 最大流速 = 每1秒钟产生10个令牌
        boolean trySetRate = rateLimiter.trySetRate(RateType.OVERALL, 10, 1, RateIntervalUnit.SECONDS);
        if(rateLimiter.tryAcquire()){
            System.out.println("我获取到了信息哈");
        }else{
            System.out.println("对不起你被限流了哈");
        }
    }
复制代码

欧克欧克😀 大概这里都介绍完毕了,若是你们想研究更多Redisson 的强大功能,这里给一个传送地址 github.com/redisson/re… 绝壁不会让你失望bash

相关文章
相关标签/搜索