成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

基于Redis的BloomFilter實(shí)現(xiàn)

phodal / 823人閱讀

摘要:再來看怎么結(jié)合一起使用根據(jù)給定的布隆過濾器添加值不能為空根據(jù)給定的布隆過濾器判斷值是否存在不能為空很簡(jiǎn)單,只有兩個(gè)方法,往里面添加元素,檢查元素是否在里面這里的客戶端使用的是封裝的,可以在我的項(xiàng)目中查看完整的使用代碼。

前言
最近在研究布隆過濾器(如果不了解什么是布隆過濾器的,推薦看這篇如何判斷一個(gè)元素在億級(jí)數(shù)據(jù)中是否存在?了解),發(fā)現(xiàn)Guava提供了封裝好的類,但是只能單機(jī)使用,一般現(xiàn)在的應(yīng)用都是部署在分布式系統(tǒng)的,所以想找個(gè)可以在分布式系統(tǒng)下使用的布隆過濾器,找了半天只找到一個(gè)基于redis開發(fā)的模塊項(xiàng)目ReBloom,但是這個(gè)是需要額外安裝的,而且文檔里只說了怎么在docker下運(yùn)行,沒研究過docker所以放棄了。后來找到一篇博客講怎么利用布隆過濾器統(tǒng)計(jì)消息未讀數(shù)的(博客地址不記得了,是一位淘寶同學(xué)寫的),博客最后放了一份整合redis和bloomFilter的代碼demo,詳見BloomFilter.java,看了下實(shí)現(xiàn)比較簡(jiǎn)單,但是使用方式不是我想要的,所以參考著自己整理了一份。
BloomFilterHelper
package com.doodl6.springmvc.service.cache.redis;

import com.google.common.base.Preconditions;
import com.google.common.hash.Funnel;
import com.google.common.hash.Hashing;

public class BloomFilterHelper {

    private int numHashFunctions;

    private int bitSize;

    private Funnel funnel;

    public BloomFilterHelper(Funnel funnel, int expectedInsertions, double fpp) {
        Preconditions.checkArgument(funnel != null, "funnel不能為空");
        this.funnel = funnel;
        bitSize = optimalNumOfBits(expectedInsertions, fpp);
        numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, bitSize);
    }

    int[] murmurHashOffset(T value) {
        int[] offset = new int[numHashFunctions];

        long hash64 = Hashing.murmur3_128().hashObject(value, funnel).asLong();
        int hash1 = (int) hash64;
        int hash2 = (int) (hash64 >>> 32);
        for (int i = 1; i <= numHashFunctions; i++) {
            int nextHash = hash1 + i * hash2;
            if (nextHash < 0) {
                nextHash = ~nextHash;
            }
            offset[i - 1] = nextHash % bitSize;
        }

        return offset;
    }

    /**
     * 計(jì)算bit數(shù)組長(zhǎng)度
     */
    private int optimalNumOfBits(long n, double p) {
        if (p == 0) {
            p = Double.MIN_VALUE;
        }
        return (int) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
    }

    /**
     * 計(jì)算hash方法執(zhí)行次數(shù)
     */
    private int optimalNumOfHashFunctions(long n, long m) {
        return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
    }
}

BloomFilterHelper是實(shí)現(xiàn)功能的關(guān)鍵,包含了計(jì)算bitmap的核心算法,其實(shí)大部分代碼都是來源于Guava庫(kù)里面的BloomFilterStrategies類,但是因?yàn)檫@個(gè)類是專門為Guava的BloomFilter類使用的,所以沒有對(duì)外暴露一些重要的算法邏輯。

再來看怎么結(jié)合redis一起使用BloomFilterHelper

RedisService
package com.doodl6.springmvc.service.cache.redis;

import com.google.common.base.Preconditions;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 根據(jù)給定的布隆過濾器添加值
     */
    public  void addByBloomFilter(BloomFilterHelper bloomFilterHelper, String key, T value) {
        Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能為空");
        int[] offset = bloomFilterHelper.murmurHashOffset(value);
        for (int i : offset) {
            redisTemplate.opsForValue().setBit(key, i, true);
        }
    }

    /**
     * 根據(jù)給定的布隆過濾器判斷值是否存在
     */
    public  boolean includeByBloomFilter(BloomFilterHelper bloomFilterHelper, String key, T value) {
        Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能為空");
        int[] offset = bloomFilterHelper.murmurHashOffset(value);
        for (int i : offset) {
            if (!redisTemplate.opsForValue().getBit(key, i)) {
                return false;
            }
        }

        return true;
    }
}

RedisService很簡(jiǎn)單,只有兩個(gè)方法

addByBloomFilter,往redis里面添加元素

includeByBloomFilter,檢查元素是否在redis bloomFilter里面

這里redis的客戶端使用的是spring-data-redis封裝的,可以在我的項(xiàng)目SpringMVC-Project中查看完整的使用代碼。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72665.html

相關(guān)文章

  • [輪子系列]Google Guava之BloomFilter源碼分析及基于Redis重構(gòu)

    摘要:方法,即表示自動(dòng)擴(kuò)容,這個(gè)函數(shù)名是從中搬過來的。自動(dòng)擴(kuò)容最后,也是最重要的,其中用了布隆過濾器中計(jì)算型數(shù)組長(zhǎng)度的方法,得到之后使用命令初始化一個(gè)全部為的位數(shù)組。 本文源地址:http://www.fullstackyang.com/...,轉(zhuǎn)發(fā)請(qǐng)注明該地址或segmentfault地址,謝謝! 一、背景知識(shí) 在網(wǎng)上已經(jīng)有很多關(guān)于布隆過濾器的介紹了,這里就不再贅述,下面簡(jiǎn)單地提煉幾個(gè)要點(diǎn)...

    xiangchaobin 評(píng)論0 收藏0
  • Redis緩存穿透問題及解決方案

    摘要:方案二布隆過濾器攔截布隆過濾器介紹概念布隆過濾器英語(yǔ)是年由布隆提出的。這就是布隆過濾器的基本思想。防緩存穿透的布隆過濾器判斷是否為合法非法則不允許繼續(xù)查庫(kù)從緩存中獲取數(shù)據(jù)緩存為空從數(shù)據(jù)庫(kù)中獲取緩存空對(duì)象參考書籍開發(fā)與運(yùn)維 上周在工作中遇到了一個(gè)問題場(chǎng)景,即查詢商品的配件信息時(shí)(商品:配件為1:N的關(guān)系),如若商品并未配置配件信息,則查數(shù)據(jù)庫(kù)為空,且不會(huì)加入緩存,這就會(huì)導(dǎo)致,下次在查詢同...

    AlanKeene 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<