关于redis:深入理解redis布隆过滤器BloomFilter

1.布隆过滤器是什么

2.布隆过滤器的特点

3.布隆过滤器应用场景

4.布隆过滤器原理

5.布隆过滤器优缺点

6.布隆过滤器利用

7.总结

1.布隆过滤器是什么

redis的布隆过滤器其实有点像咱们之前学习过的hyperloglog 深刻了解redis——新类型bitmap/hyperloglgo/GEO ,它也是不保留元素的一个汇合,它也不保留元素的具体内容,然而能断定这个元素是否在这个汇合中存在(hyperloglog是断定汇合中存在的不反复元素的个数)。

1)它是由一个初值都为零的bit数组和多个哈希函数形成,用来疾速判断某个数据是否存在。

2)实质就是判断具体数据存不存在一个大的汇合中。

3)布隆过滤器是一种相似set的数据结构,只是统计后果不太精确

2.布隆过滤器的特点

1)一个元素如果在布隆过滤器里断定后果为不存在,则肯定不存在
2)一个元素在布隆过滤器里断定结果存在,则不肯定存在(原理会在上面解释)
3)布隆过滤器能够增加元素,然而不能删除元素,删除元素会导致误判率减少。
4)误判只会产生在过滤器没有增加过的元素,对于已经增加过的元素不会产生误判。

3.布隆过滤器应用场景

1)解决缓存穿透的问题:

缓存穿透是什么:
个别状况下,咱们在查问数据的时候,如果用到redis,那么先去查redis,如果缓存中没有,再去查数据库,如果数据库中也不存在,那么就产生了缓存穿透

当产生缓存穿透的时候,可能会有大量的查问直击mysql,肯定水平上会拖垮数据库。

解决方案:
1.1)给空key设置一个空value.
然而当大量空key进去的时候,也相当于查了很屡次mysql,也可能会拖垮数据库。

1.2)应用布隆过滤器
把已存在的key保留在布隆过滤器中,相当于redis后面有一层布隆过滤器的爱护。
当呈现申请的时候:
1.2.1)先去查问布隆过滤器是否存在(如果布隆过滤器返回为不存在,那是肯定不存在。)
1.2.2)如果存在,才去redis,甚至mysql查问,如果不存在,间接返回。

2)黑白名单的问题:
解决原理同上,把黑名单全副放入布隆过滤器,再进行过滤。

3)海量数据查找是否存在的问题都能够用布隆过滤器。(比方现有50亿个电话号码,和10万个电话号码,疾速精确地断定号码是否存在。)

4.布隆过滤器原理

布隆过滤器应用了多个Hash函数和一个初始值都为0的bit大型数组形成

add:
比方咱们当初有一个对象obj1,它先用多个hash函数失去多个不同的值再拿数组长度进行对这多个值取模失去多个地位将这几个地位置为1,就实现了add操作。

query:
查问的时候,只有多个哈希函数算进去的下标其中有一位是0就代表这个key不存在,如果都是1,可能是存在,则可能遇上了哈希抵触(这就是为什么,布隆过滤器,无是肯定无,有可能有)。

为什么布隆过滤器不能删除:
如果布隆过滤器删除了一个元素,就是将某个对象的多个下标置为了0,就大概率会影响到别的元素因为很可能多个元素共享了某一个下标,所以删除元素会导致误判率减少。

5.布隆过滤器优缺点

长处:高效地插入和查问,占用空间少

毛病:不能删除元素,存在误判。

6.布隆过滤器利用

public class RedissonBloomFilterDemo {
    public static final int _1W = 10000;

    //布隆过滤器里预计要插入多少数据
    public static int size = 100 * _1W;
    //误判率,它越小误判的个数也就越少
    public static double fpp = 0.03;
    
    static RedissonClient redissonClient = null;
    static RBloomFilter rBloomFilter = null;

    static {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://192.168.111.147:6379").setDatabase(0);
        //结构redisson
        redissonClient = Redisson.create(config);
        //通过redisson结构rBloomFilter
        rBloomFilter = redissonClient.getBloomFilter("phoneListBloomFilter", new StringCodec());
        //初始化布隆过滤器
        rBloomFilter.tryInit(size, fpp);

        // 1测试  布隆过滤器有+redis有
        rBloomFilter.add("10086");
        redissonClient.getBucket("10086", new StringCodec()).set("chinamobile10086");

        // 2测试  布隆过滤器有+redis无
        //rBloomFilter.add("10087");

        //3 测试 ,都没有

    }

    public static void main(String[] args) {
        String phoneListById = getPhoneListById("10087");
        System.out.println("------查问进去的后果: " + phoneListById);
        //暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        redissonClient.shutdown();
    }

    private static String getPhoneListById(String IDNumber) {
        String result = null;

        if (IDNumber == null) {
            return null;
        }
            //1 先去布隆过滤器外面查问
        if (rBloomFilter.contains(IDNumber)) {
            //2 布隆过滤器里有,再去redis外面查问
            RBucket rBucket = redissonClient.getBucket(IDNumber, new StringCodec());
            result = rBucket.get();
            if (result != null) {
                return "i come from redis: " + result;
            } else {
                result = getPhoneListByMySQL(IDNumber);
                if (result == null) {
                    return null;
                }
                // 从新将数据更新回redis
                redissonClient.getBucket(IDNumber, new StringCodec()).set(result);
            }
            return "i come from mysql: " + result;
        }
        return result;
    }

    private static String getPhoneListByMySQL(String IDNumber) {
        return "chinamobile" + IDNumber;
    }
}

7.总结

明天学习和总结了布隆过滤器,它是一种不保留数据,然而能断定数据是否在汇合中存在的一种数据类型。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理