ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

如何在springboot项目中redis使用布隆过滤器防止缓存穿透

2020-11-27 11:58:33  阅读:250  来源: 互联网

标签:缓存 springboot int redis 布隆 bloomFilterHelper 过滤器 public


上一篇博客讲到了布隆过滤器在java中的应用,这一篇说
如何在springboot项目中redis使用布隆过滤器防止缓存穿透。

在这里插入图片描述
先引入依赖

        <!--使用Redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--借助guava的布隆过滤器-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>

yml redis配置

spring:
  redis:
    database: 3
    host: 127.0.0.1
    port: 6379
    password: 12345
    jedis.pool.max-idle: 100
    jedis.pool.max-wait: -1ms
    jedis.pool.min-idle: 2
    timeout: 2000ms

两个工具类

BloomFilterHelper

package com.whrfjd.rescenter.utis;

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

public class BloomFilterHelper<T> {

    private int numHashFunctions;

    private int bitSize;

    private Funnel<T> funnel;

    public BloomFilterHelper(Funnel<T> funnel, int expectedInsertions, double fpp) {
        Preconditions.checkArgument(funnel != null, "funnel不能为空");
        this.funnel = funnel;
        // 计算bit数组长度
        bitSize = optimalNumOfBits(expectedInsertions, fpp);
        // 计算hash方法执行次数
        numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, bitSize);
    }

    public 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;
    }

    /**
     * 计算bit数组长度
     */
    private int optimalNumOfBits(long n, double p) {
        if (p == 0) {
            // 设定最小期望长度
            p = Double.MIN_VALUE;
        }
        int sizeOfBitArray = (int) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
        return sizeOfBitArray;
    }

    /**
     * 计算hash方法执行次数
     */
    private int optimalNumOfHashFunctions(long n, long m) {
        int countOfHash = Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
        return countOfHash;
    }
}

RedisBloomFilter

package com.whrfjd.rescenter.utis;

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

/**
 * @Author : JCccc
 * @CreateTime : 2020/4/23
 * @Description :
 **/
@Service
public class RedisBloomFilter {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据给定的布隆过滤器添加值
     */
    public <T> void addByBloomFilter(BloomFilterHelper<T> bloomFilterHelper, String key, T value) {
        Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能为空");
        int[] offset = bloomFilterHelper.murmurHashOffset(value);
        for (int i : offset) {
            System.out.println("key : " + key + " " + "value : " + i);
            redisTemplate.opsForValue().setBit(key, i, true);
        }
    }

    /**
     * 根据给定的布隆过滤器判断值是否存在
     */
    public <T> boolean includeByBloomFilter(BloomFilterHelper<T> bloomFilterHelper, String key, T value) {
        Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能为空");
        int[] offset = bloomFilterHelper.murmurHashOffset(value);
        for (int i : offset) {
            System.out.println("key : " + key + " " + "value : " + i);
            if (!redisTemplate.opsForValue().getBit(key, i)) {
                return false;
            }
        }

        return true;
    }

}

配置完成现在可以测试了。
redis布隆过滤器数据添加

 @GetMapping("/redis/bloomFilter")
    @ApiOperation("redis布隆过滤器数据添加")
    public ResponseResult redisBloomFilter(){
        List<String> allResourceId = resCenterDao.getAllResourceId();
        for (String id : allResourceId) {
            //将所有的资源id放入到布隆过滤器中
            redisBloomFilter.addByBloomFilter(bloomFilterHelper,"bloom",id);
        }
        return new ResponseResult(ResponseEnum.SUCCESS);
    }

redis布隆过滤器资源测试

 @GetMapping("/redis/bloomFilter/resourceId")
    @ApiOperation("redis布隆过滤器资源测试")
    public ResponseResult redisBloomFilterResourceId(@RequestParam("resourceId")String resourceId){
        boolean mightContain = redisBloomFilter.includeByBloomFilter(bloomFilterHelper,"bloom",resourceId);
        if (!mightContain){
            return new QueryResult<>(ResCenterEnum.RESOURCE_EXSIT,"");
        }
        return new ResponseResult(ResponseEnum.SUCCESS);
    }

完成!

标签:缓存,springboot,int,redis,布隆,bloomFilterHelper,过滤器,public
来源: https://blog.csdn.net/weixin_43748936/article/details/110225696

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有