SpringBoot中布隆过滤器的使用

1、引入依赖

		<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>

·

2、写一个布隆过滤器类

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.nio.charset.Charset;

@Component
public class BloomFilterUtil {
    /**
     * expectedInsertions:期望添加的数据个数
     * fpp:期望的误判率,期望的误判率越低,布隆过滤器计算时间越长
     * @return
     */
    @Bean
    public BloomFilter<String> goodsIDBloom(){
        BloomFilter<String> filter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 1000,0.00001);
        return filter;
    }

    @Bean
    public BloomFilter<String> orderBloom(){
        BloomFilter<String> filter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 1000,0.00001);
        return filter;
    }
}

·

3、项目启动时,就把数据存储进去,put()方法

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.hash.BloomFilter;
import com.liu.seckill.entity.SeckillGood;
import com.liu.seckill.service.SeckillGoodService;
import com.liu.seckill.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class InitConfig implements InitializingBean {
    @Autowired
    UserService userService;
    @Autowired
    SeckillGoodService seckillGoodService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RedisConfig redisConfig;
    @Autowired
    @Qualifier("goodsIDBloom")
    BloomFilter<String> goodsIDBloom;
    /**
     * 把商品库存加载到 Redis中
     * 每天更新
     * @throws Exception
     */
    @Override
    @Scheduled(fixedRate = 1000*60*60*24)
    public void afterPropertiesSet() throws Exception {
        //只缓存秒杀还没结束或秒杀还没开始的商品
        List<SeckillGood> seckillGoods = seckillGoodService.list(new QueryWrapper<SeckillGood>().ge("end_time", LocalDateTime.now()));
        if (seckillGoods == null) {
            log.info("暂无秒杀商品");
            return;
        }
        //将秒杀商品ID和库存分别存入redis中
        List<Long> seckillGoodIDList = new ArrayList<>();
        for (SeckillGood seckillGood : seckillGoods) {
            seckillGoodIDList.add(seckillGood.getSgId());
            //设置过期时间
            long millis = Duration.between(LocalDateTime.now(), seckillGood.getEndTime()).toMillis();
            redisTemplate.opsForValue().set("seckillGoodID:" + seckillGood.getSgId(), seckillGood.getSgStock(), millis, TimeUnit.MILLISECONDS);
            //存储值到布隆过滤器中
            goodsIDBloom.put(seckillGood.getSgId()+"");
        }
        redisTemplate.opsForValue().set("seckillGoodIDList:", seckillGoodIDList,1,TimeUnit.DAYS);

    }
}

·

4、使用布隆过滤器,mightContain()方法

@RestController
@Slf4j
@RequestMapping("/seckillOrder")
public class SeckillOrderController  {
 	//如果有多个布隆过滤器,就同时使用@Qualifier和@Autowired
    @Autowired
    @Qualifier("goodsIDBloom")
    BloomFilter<String> goodsIDBloom;
    @Autowired
    @Qualifier("orderBloom")
    BloomFilter<String> orderBloom;

    @GetMapping("/seckillGoods/{goodId}")
    public Result seckillGoods(@PathVariable("goodId") Long goodId) {
        ValueOperations valueOperations = redisTemplate.opsForValue();

        //判断秒杀商品是否存在
        //如果商品id在布隆过滤器中存在,那么就要再去判断在不在redis中,在,才能证明真的在
        if (goodsIDBloom.mightContain(goodId+"")){
            ArrayList<Long> seckillGoodIDList = (ArrayList<Long>) valueOperations.get("seckillGoodIDList:");
            Assert.isTrue(seckillGoodIDList.contains(goodId),"未找到该商品,商品ID有误或此商品不参与秒杀或此商品秒杀已结束");
        }else {
            Assert.isTrue(false,"未找到该商品,商品ID有误或此商品不参与秒杀或此商品秒杀已结束");
        }
    }
}

·

参考:https://blog.csdn.net/weixin_49390750/article/details/125139084

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值