redis高级篇2 springboot+redis+bloomfilter实现过滤案例

一 bloomfilter的作用

1.1 作用

Bloomfilter:默认是有0组成bit数组和hash函数构成的数据结构,用来判断在海量数据中是否存在某个元素。

应用案例:解决缓存穿透。Bloomfilter放在redis前面,如果查询bf中没有则直接返回,如果存在则查询redis,如果redis不存在,则查询mysql数据库。bf拦截一些不必要的请求。

1.2 案例

1.2.1 流程逻辑

1.构建过程

1)预加载符合条件的记录;2)计算每条记录的hash值;3)计算hash值对应bitmap数组的位置;4)修改值为1;

2.查询过程

1)计算元素的hash位置;2)计算hash值对应二进制数组的位置;3)找到数组中对应位置的值,0代表不存在;1代表存在。

1.2.2 setbit的构建过程

1.@postConstruct初始化白名单数据

2.计算元素的hash值

3.通过上一步的hash值算出对应的二进制数组的坑位,将对应坑位的值修改为数字;1表示存在。

1.2.3 查询是否存在

1.计算元素的hash值;2通过上一步的hash值计算出对应的二进制数组对应的坑位,返回对应坑位的值,0表示无;1表示存在。

二 工程搭建

2.1 工程结构

2.2 不使用bloomfilter过滤器的情况 

2.2.1 新增初始化数据

1.controller

2.service

 2.2.2 查询数据

1.controller

 2.service

 2.2.3 初始化数据库

1.数据库配置

2.数据库脚本

CREATE TABLE `t_customer` (
  `id` bigint(11) NOT NULL,
  `cname` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `phone` varchar(255) DEFAULT NULL,
  `sex` varchar(255) DEFAULT NULL,
  `birth` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 2.2.4 启动服务测试

1.页面访问新增数据

http://localhost:8083/customer/add

2.访问查询接口

访问存在的数据id=1

访问不存在的数据id=3

 控制台显示信息:

2023-07-31 18:44:11.850  INFO 4172 --- [nio-8083-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
刚开始redis不存在。。。。。。

 3.查看数据库接口

4.查看redis

 2.3 使用bloomfilter过滤器的情况 

2.3.1 逻辑架构

2.3.2 初始化白名单数据

这里将customer:12作为key,存储到redis数据库中。

@Component
@Slf4j
public class BloomFilterInit
{
    @Resource
    private RedisTemplate redisTemplate;

    @PostConstruct //初始化白名单数据
    public void initWhiteListData(){
        //1.白名单客户加载到布隆过滤器中
        String key="customer:12";
        //2.计算hashvalues,由于存储计算出来可能存在负数,我们取绝对值
        int hashValue=Math.abs(key.hashCode());
        //3.通过hashvalue和2的32次方后取余,获得对应的下标坑位
        long index=(long)(hashValue%Math.pow(2,32));
        log.info("key"+"对应的index:"+index);
        //4.设置redis里面的bitmap对应的白名单 whitelistcustomer的坑位,将改值设置为1;
        redisTemplate.opsForValue().setBit("whiteListCustomer",index,true);
    }
}

截图

 2.3.3 使用bloomfilter过滤判断

 public Customer findDataByBloomFilter(Integer id){
        //1.封装key
        String key=CACHA_KEY_CUSTOMER+id;
        //2.布隆过滤器check,无是绝对无,有是可能有
        //===============================================
        if(!checkUtils.checkWithBloomFilter("whiteListCustomer",key))
        {
            log.info("白名单无此顾客,不可以访问: "+key);
            return null;
        }
       //3.查询redis
        Customer customer=(Customer) redisTemplate.opsForValue().get(key);
        if(customer==null){
            System.out.println("redis不存在。。。。。。");
            //4.redis为空,查询mysql
            customer=customerDao.selectByPrimaryKey(id);
            if(customer!=null){
                System.out.println("redis不存在,查询mysql存在");
                //5.mysql中数据存在, 把mysq查询出来的数据回写redis,保持一致性
                redisTemplate.opsForValue().set(key,customer);
                System.out.println("redis不存在,查询mysql存在,回写redis最新数据....");
            }
        }
        return customer;

    }

checkutil工具类:

package com.ljf.redis.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @auther zzyy
 * @create 2022-12-27 14:56
 */
@Component
@Slf4j
public class CheckUtils
{
    @Resource
    private RedisTemplate redisTemplate;

    public boolean checkWithBloomFilter(String checkItem,String key)
    {
        int hashValue = Math.abs(key.hashCode());
        long index = (long)(hashValue % Math.pow(2,32));
        boolean existOK = redisTemplate.opsForValue().getBit(checkItem,index);
        log.info("--->key:"+key+" 对应坑位下标index: "+index+" 是否存在:"+existOK);

        return existOK;
    }
}

2.截图

  2.3.4 判断测试

1.访问customer:1 但是初始白名单放入的是customer:12; 不存在则一定过滤掉。

控制台:

2023-07-31 18:47:43.243  INFO 4172 --- [io-8083-exec-10] com.ljf.redis.util.CheckUtils            : --->key:customer:1 对应坑位下标index: 1581185131 是否存在:false
2023-07-31 18:47:43.243  INFO 4172 --- [io-8083-exec-10] c.l.r.service.impl.CustomerServiceImpl   : 白名单无此顾客,不可以访问: customer:1

2.修改初始化白名单,customer:12 改为customer:1

3.再次启动服务,再次访问

4.控制台信息

 2023-07-31 19:10:08.794  INFO 19236 --- [nio-8083-exec-2] com.ljf.redis.util.CheckUtils            : --->key:customer:1 对应坑位下标index: 1581185131 是否存在:true

5.redis中查看

127.0.0.1:6379> get whiteListCustomer
@
127.0.0.1:6379> 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值