首页 > 其他分享 >分布式布隆过滤器

分布式布隆过滤器

时间:2023-08-20 18:33:27浏览次数:39  
标签:skuId 布隆 过滤器 bloomFilter RBloomFilter 分布式

1. 分布式布隆过滤器的价值

集群环境太浪费系统资源、集群环境也不容易对布隆过滤器进行维护,所以采用Redisson框架的分布式布隆过滤器。

2. Redisson提供的分布式布隆过滤器的使用

// 获取一个分布式的布隆过滤器(RedissonClient)
RBloomFilter<V> getBloomFilter(String name);

// 初始化分布式的布隆过滤器(RBloomFilter)
boolean tryInit(long expectedInsertions, double falseProbability);

// 判断布隆过滤器中是否存在数据(RBloomFilter)
boolean contains(T object);

// 判断布隆过滤器是否存在(RBloomFilter)
boolean isExists();

3. 分布式布隆过滤器的初始化

@PostConstruct
public void init(){
	// 查询所有的skuId
	List<Long> skuIds = skuInfoMapper.findAllSkuIds();

	// 通过RedissonClient创建BloomFilter
	RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(GmallConstant.REDIS_BLOOMFILTER_SKU_DETAIL);

	// 判断bloomFilter是否存在,如果不存在进行初始化
	if (!bloomFilter.isExists()){
		bloomFilter.tryInit(1000000, 0.000001);

		// 将skuId存储到bloomFilter
		skuIds.forEach(skuId -> {
			bloomFilter.add(skuId);
		});
	}

	log.info("布隆过滤器初始化完毕,判断skuId为51的商品在bloomFilter中是否存在:" + bloomFilter.contains(51L));
}

4. 获取分布式布隆过滤器

private RBloomFilter<Long> redissonBloomFilter;

// 获取分布式布隆过滤器
@PostConstruct
public void getRedissonBloomFilter(){
	log.info("获取了分布式布隆过滤器......");
	redissonBloomFilter = redissonClient.getBloomFilter(GmallConstant.REDIS_BLOOMFILTER_SKU_DETAIL);
}

// 判断当前skuId在布隆过滤器中是否存在
if (!redissonBloomFilter.contains(skuId)){
	log.error("当前查询的商品在布隆过滤器中不存在,在数据库中也不存在......");
	return null;
}

5. 布隆过滤器的重置

5.1 思路

创建新的bloom过滤器,删除原有的bloom过滤器,在对新的bloom过滤器进行重命名;并且需要保证后两者的原子性操作

5.2 代码实现

// 查询所有的skuId
List<Long> skuIds = skuInfoMapper.findAllSkuIds();

// 创建新的布隆过滤器
RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(GmallConstant.REDIS_BLOOMFILTER_SKU_DETAIL_NEW);
bloomFilter.tryInit(1000000, 0.000001);
skuIds.forEach(skuId -> bloomFilter.add(skuId));
log.info("新的布隆过滤器创建好了,判断100在布隆过滤器中是否存在:" + bloomFilter.contains(100L));

// 删除原有的布隆过滤器和配置,并把新创建的布隆过滤器和配置名称重命名为原有的布隆过滤器和配置名称
String script = "redis.call(\"del\" , KEYS[1])\n" +
	"redis.call(\"del\" , \"{\"..KEYS[1]..\"}:config\")\n" +
	"redis.call(\"rename\" , KEYS[2] , KEYS[1])\n" +
	"redis.call(\"rename\" , \"{\"..KEYS[2]..\"}:config\" , \"{\"..KEYS[1]..\"}:config\")\n" +
	"return 1";
redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(GmallConstant.REDIS_BLOOMFILTER_SKU_DETAIL, GmallConstant.REDIS_BLOOMFILTER_SKU_DETAIL_NEW));

5.3 服务触发时机

  1. 定时任务触发
@Slf4j
@Component
public class ResetBloomFilterTimeTask {

    @Autowired
    private BloomFilterService bloomFilterService;

    /**
     * ?:表示废弃掉这一位,仅支持日期和星期,这两位其中之一被指定值以后,为了避免冲突,需要将另一个域的值设为?
     * cron表达式各位的意义:秒 分 时 日期 月 星期,不支持年
     */
    @Scheduled(cron = "0 0 3 */7 * ?") // cron属性需要一个cron表达式,这个cron表达式用来指定方法在执行的时候的时间规则
    public void resetBloomFilterTask(){
        bloomFilterService.resetBloomFilter();
        log.info("布隆过滤器重置方法执行了......");
    }
}

启动类添加@EnableScheduling注解,开启定时任务功能
cron表达式:https://help.aliyun.com/document_detail/64769.html
2. 提供一个接口,在后台开放调用该接口的功能,系统前台提供一个按钮,点击按钮调用该接口

/**
 * 重置布隆过滤器的接口
 */
@RestController
@RequestMapping(value = "/admin/product")
public class BloomFilterController {

    @Autowired
    private BloomFilterService bloomFilterService;

    @GetMapping(value = "/resetBloomFilter")
    public Result resetBloomFilter(){
        bloomFilterService.resetBloomFilter();
        return Result.ok();
    }
}
  1. 每删除一次数据调用一次

标签:skuId,布隆,过滤器,bloomFilter,RBloomFilter,分布式
From: https://www.cnblogs.com/insilently/p/17644366.html

相关文章

  • 2-16-Gateway网关-全局过滤器
    14-15都是通过配置修改实现的预设过滤器所谓的全局过滤器可以认为是全局生效的自定义过滤器通过新建类实现接口即可packagecn.itcast.study.mygateway;importorg.springframework.cloud.gateway.filter.GatewayFilterChain;importorg.springframework.cloud.gateway.fil......
  • 2-17-Gateway网关-过滤器链执行顺序
    自定义过滤器可以通过设置order注解来随意放置执行顺序配置过滤器则会在全局与单服务之间来回跳(因为两个都是从1开始计数,也可以自定义指定order属性)每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。GlobalFilter通过实现Ordered接口,或者添......
  • 读发布!设计与部署稳定的分布式系统(第2版)笔记33_混沌工程
    1. 康威定律1.1. 梅尔文·康威1.1.1. MelvinConway1.1.2. 1968年1.1.3. 在设计系统时,组织受制于其自身的沟通结构,这使得它设计的系统结构与沟通结构相一致。1.1.3.1. 社会学现象1.2. 要在系统内部或系统之间构建接口,两个人必须以某种方式沟通有关该接口的规范1.2.......
  • 认证过滤器
    我们需要自定义一个过滤器,这个过滤器会去获取请求头中的token,对token进行解析取出其中的userid。使用userid去redis中获取对应的LoginUser对象。然后封装Authentication对象存入SecurityContextHolderpackagecom.security.filter;importcom.security.domain.LoginUser;......
  • 2-14-Gateway网关-路由断言工厂[15-Gateway网关-路由的过滤器配置]
    所谓的断言工厂与过滤器都是通过yml配置生效以下都将从配置的角度说明如何配置具体哪一个怎么用可以直接访问spring官网查看spring:cloud:gateway:routes:-id:user-serviceuri:lb://userservicepredicates:-Path=/us......
  • Redis分布式锁笔记
    1redis分布式锁实现原理所谓分布式锁,应当基本如下几项核心性质:• 独占性:对于同一把锁,在同一时刻只能被一个取锁方占有,这是锁最基础的一项特征• 健壮性:即不能产生死锁(deadlock).假如某个占有锁的使用方因为宕机而无法主动执行解锁动作,锁也应该能够被正常传承下去,被其......
  • uniapp中使用过滤器filters来格式化时间
    uniapp中使用过滤器filters来格式化时间看那个创云商城源码的时候看到的,觉得蛮有用的,扒下来备用,应该也能直接用于JS  <template><viewclass="mix-timeline"><viewclass="cell"v-for="(item,index)inlist":key="index">......
  • 异常过滤器
    一.什么是异常过滤器异常过滤器是.NETCore中一种用于处理全局异常的机制。它可以在代码发生异常时捕获、处理和记录异常,并提供自定义的异常处理逻辑,把异常报错自定义。异常过滤器在整个程序的范围内生效,可以用于处理各种异常情况。二.异常过滤器的使用定义异常过滤器要继......
  • Springboot使用Redisson作为分布式锁
    官方地址:https://github.com/redisson/redisson/wiki/Table-of-Content一些官网说明    Redisson采用了基于NIO的Netty框架,不仅能作为Redis底层驱动客户端,具备提供对Redis各种组态形式的连接功能,对Redis命令能以同步发送、异步形式发送、异步流形式发送或管道形式发送的功能......
  • 全局异常过滤器
    在ASP.NETCore中,可以使用异常过滤器(ExceptionFilter)来捕获和处理应用程序中的异常。IExceptionFilter接口和IAsyncExceptionFilter接口都可以用来实现自定义的异常过滤器。首先,在WebApi中创建一个名为CustomExceptionFilter的实体类 在这个示例中,我们创建了一个名为......