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

相關文章
相關標籤/搜索