redis实现布隆过滤器

redis实现布隆过滤器

文档

  1. redis单机安装
  2. redis集群模式 -集群搭建
  3. 布隆过滤器 -Bloom Filter
  4. springboot整合redisson单机模式

官方文档

  1. 官网操作命令指南页面:https://redis.io/docs/latest/commands/?name=get&group=string
  2. Redis cluster specification

下载地址

  1. 官网:https://redis.io/
  2. 下载列表页面:https://download.redis.io/releases/

说明

  1. 版本选择:redis-7.0.0.tar.gz
  2. 下载地址:[https://download.redis.io/releases/redis-7.0.0.tar.gz\](

redis实现布隆过滤器

安装单机版redis
  1. 安装单机版redis参考文档:redis单机安装
springboot整合redisson单机模式
  1. springboot整合redisson单机模式参考文档:springboot整合redisson单机模式
方式一:Redisson RBloomFilter
  1. Redisson 提供了 R BloomFilter,底层用 Bitmap 实现。

  2. 使用示例

    1. 创建IpBlacklistService.java,校验IP黑名单

      java 复制代码
      @Service
      public class IpBlacklistService {
      
          private static final String BLOOM_KEY = "bloom:ip:blacklist";
          private static final long EXPECTED_INSERTIONS = 100_0000L;
          private static final double FALSE_PROBABILITY = 0.01;
      
          private final RedissonClient redissonClient;
      
          public IpBlacklistService(RedissonClient redissonClient) {
              this.redissonClient = redissonClient;
          }
      
          private RBloomFilter<String> getBloomFilter() {
              RBloomFilter<String> filter = redissonClient.getBloomFilter(BLOOM_KEY);
              if (!filter.isExists()) {
                  filter.tryInit(EXPECTED_INSERTIONS, FALSE_PROBABILITY);
              }
              return filter;
          }
      
          public void addToBlacklist(String ip) {
              getBloomFilter().add(ip);
          }
      
          public boolean isBlacklisted(String ip) {
              return getBloomFilter().contains(ip);
          }
      }
    2. 创建IpBlacklistController.java, 提供IP黑名单管理接口,依托Redis布隆过滤器实现黑名单的加入和查询

      java 复制代码
      @RestController
      @RequestMapping("/blacklist")
      public class IpBlacklistController {
      
          private final IpBlacklistService ipBlacklistService;
      
          public IpBlacklistController(IpBlacklistService ipBlacklistService) {
              this.ipBlacklistService = ipBlacklistService;
          }
      
          /**
           * 将 IP 加入黑名单
           *
           * @param ip 待加入黑名单的 IP 地址
           * @return "ok" 表示添加成功
           */
          @PostMapping("/ip")
          public String addIp(@RequestParam("ip") String ip) {
              ipBlacklistService.addToBlacklist(ip);
              return "ok";
          }
      
          /**
           * 判断 IP 是否在黑名单中
           *
           * @param ip 待校验的 IP 地址
           * @return true 可能 blacklisted(存在误判),false 一定不在黑名单
           */
          @GetMapping("/ip/check")
          public boolean checkIp(@RequestParam("ip") String ip) {
              return ipBlacklistService.isBlacklisted(ip);
          }
      }
    3. 调用接口curl命令(windows)

      shell 复制代码
      curl.exe -X POST "http://localhost:8080/redis01/blacklist/ip?ip=192.168.1.100"
      curl.exe "http://localhost:8080/redis01/blacklist/ip/check?ip=192.168.1.100"
方式二:手动用redis实现布隆过滤器
  1. 基本思路

    1. 维护一个长度为 m 的 bit 数组(全 0)
    2. 准备 k 个 彼此独立的 hash 函数,每个把元素映射到 [0, m-1] 的一个下标。
    3. 添加:把元素用 k 个 hash 得到 k 个下标,把这 k 个 bit 都置为 1。
    4. 查询:用同样的 k 个 hash 得到 k 个下标,若全是 1 就说"可能在",有任一是 0 就说"一定不在"。
  2. n、p、m、k的含义

    1. n:要存多少条数据
    2. p:能接受多高的误判率
    3. m:一共用多少 bit 存
    4. k:每个元素用几个 hash(写/查几个 bit)
  3. 参考文档:布隆过滤器 -Bloom Filter,了解n、p、m、k之间的关系

  4. 使用示例

    1. 创建RedisBloomFilter.java,手动实现布隆过滤器逻辑

      java 复制代码
      public class RedisBloomFilter {
      
          private final StringRedisTemplate redisTemplate;
          private final String key;
          private final int bitSize;
          private final int hashCount;
      
          public RedisBloomFilter(StringRedisTemplate redisTemplate, String key, long expectedInsertions, double fpp) {
              this.redisTemplate = redisTemplate;
              this.key = key;
              this.bitSize = optimalNumOfBits(expectedInsertions, fpp);
              this.hashCount = optimalNumOfHashFunctions(expectedInsertions, bitSize);
          }
      
          public void add(String value) {
              for (int i = 0; i < hashCount; i++) {
                  long hash = hash(value, i);
                  long index = (hash & 0x7FFFFFFFFFFFFFFFL) % bitSize;
                  redisTemplate.opsForValue().setBit(key, index, true);
              }
          }
      
          public boolean contains(String value) {
              for (int i = 0; i < hashCount; i++) {
                  long hash = hash(value, i);
                  long index = (hash & 0x7FFFFFFFFFFFFFFFL) % bitSize;
                  if (Boolean.FALSE.equals(redisTemplate.opsForValue().getBit(key, index))) {
                      return false;
                  }
              }
              return true;
          }
      
          private long hash(String value, int seed) {
              long result = 0;
              for (int i = 0; i < value.length(); i++) {
                  result = result * 31 + value.charAt(i) + seed;
              }
              return result;
          }
      
          static int optimalNumOfBits(long n, double p) {
              return (int) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));
          }
      
          static int optimalNumOfHashFunctions(long n, long m) {
              return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));
          }
      }
      • optimalNumOfBits(long n, double p)的作用:在给定预期元素个数 n 和目标误判率 p 时,算出布隆过滤器最少需要多少个 bit(m),使理论误判率不超过 p
      • optimalNumOfHashFunctions(long n, long m) 的作用:在已经定好 bit 数 m 和预期元素个数 n 的前提下,算出使误判率尽量低的 hash 函数个数 k
    2. 创建ManualIpBlacklistService.java,校验IP黑名单

      java 复制代码
      @Service
      public class ManualIpBlacklistService {
      
          private static final String BLOOM_KEY = "bloom:ip:blacklist";
          private static final long EXPECTED_INSERTIONS = 1_000_000L;
          private static final double FALSE_PROBABILITY = 0.01;
      
          private final StringRedisTemplate redisTemplate;
          private volatile RedisBloomFilter bloomFilter;
      
          public ManualIpBlacklistService(StringRedisTemplate redisTemplate) {
              this.redisTemplate = redisTemplate;
          }
      
          private RedisBloomFilter getBloomFilter() {
              if (bloomFilter == null) {
                  synchronized (this) {
                      if (bloomFilter == null) {
                          bloomFilter = new RedisBloomFilter(redisTemplate, BLOOM_KEY, EXPECTED_INSERTIONS, FALSE_PROBABILITY);
                      }
                  }
              }
              return bloomFilter;
          }
      
          public void addToBlacklist(String ip) {
              getBloomFilter().add(ip);
          }
      
          public boolean isBlacklisted(String ip) {
              return getBloomFilter().contains(ip);
          }
      }
    3. 创建ManualIpBlacklistController.java, 提供IP黑名单管理接口,依托Redis布隆过滤器实现黑名单的加入和查询

      java 复制代码
      @RestController
      @RequestMapping("/blacklist/manual")
      public class ManualIpBlacklistController {
      
          private final ManualIpBlacklistService manualIpBlacklistService;
      
          public ManualIpBlacklistController(ManualIpBlacklistService manualIpBlacklistService) {
              this.manualIpBlacklistService = manualIpBlacklistService;
          }
      
          /**
           * 将 IP 加入黑名单(手写布隆过滤器)
           *
           * @param ip 待加入黑名单的 IP 地址
           * @return "ok" 表示添加成功
           */
          @PostMapping("/ip")
          public String addIp(@RequestParam("ip") String ip) {
              manualIpBlacklistService.addToBlacklist(ip);
              return "ok";
          }
      
          /**
           * 判断 IP 是否在黑名单中(手写布隆过滤器)
           *
           * @param ip 待校验的 IP 地址
           * @return true 表示可能 blacklisted(存在误判),false 表示一定不在黑名单
           */
          @GetMapping("/ip/check")
          public boolean checkIp(@RequestParam("ip") String ip) {
              return manualIpBlacklistService.isBlacklisted(ip);
          }
      }
    4. 调用接口curl命令(windows)

      shell 复制代码
      curl.exe -X POST "http://localhost:8080/redis01/blacklist/manual/ip?ip=192.168.1.100"
      curl.exe "http://localhost:8080/redis01/blacklist/manual/ip/check?ip=192.168.1.100"

参考资料

  1. https://www.bilibili.com/video/BV13R4y1v7sP

注意事项

  1. 部分内容由AI生成
  2. 如有不对,欢迎指正!!!
相关推荐
编程小白gogogo16 小时前
苍穹外卖图片不显示解决教程
java·spring boot
Rick19931 天前
如何保证数据库和Redis缓存一致性
数据库·redis·缓存
indexsunny1 天前
互联网大厂Java求职面试实战:基于电商场景的技术问答及解析
java·spring boot·redis·kafka·security·microservices·面试指导
马克Markorg1 天前
SpringBoot + LangChain4j 打造企业级 RAG 智能知识库,多工具集成方案
spring boot·向量数据库·rag·qdrant·langchain4j·增强知识检索库
渣瓦攻城狮1 天前
互联网大厂Java面试:从数据库连接池到分布式缓存及微服务
java·redis·spring cloud·微服务·hikaricp·数据库连接池·分布式缓存
百锦再1 天前
Java中的日期时间API详解:从Date、Calendar到现代时间体系
java·开发语言·spring boot·struts·spring cloud·junit·kafka
树码小子1 天前
图书管理系统(2)图书列表接口
spring boot·mybatis·图书管理系统
Coder_Boy_1 天前
Java高级_资深_架构岗 核心知识点——高并发模块(底层+实践+最佳实践)
java·开发语言·人工智能·spring boot·分布式·微服务·架构
健康平安的活着1 天前
AI之Toolcalling的使用案例(langchain4j+springboot)
人工智能·spring boot·后端
百锦再1 天前
Java IO详解:File、FileInputStream与FileOutputStream
java·开发语言·jvm·spring boot·spring cloud·kafka·maven