redis高级(缓存穿透)

场景:

当大量请求过来查询redis,redis无该数据,数据库也无该数据,所有请求指向数据库,这时会造成数据库崩溃,该现象称为redis缓存穿透

两种解决方案:

一、当redis无该数据去查数据库,数据库无该数据时,在redis中存入空

@GetMapping("info/{id}")
    public R getInfo(@PathVariable("id") String id){

        Object order = redisUtil.get(id);
        if (order == null){
            System.out.println("查询数据库");
            order = orderService.getById(id);
            if (order != null){
                redisUtil.set(id,order);
            }
            // 数据库也无此数据,在redis中存入空数据
            redisUtil.set(id,"无此数据");
        }
        return R.ok().data("order",order);
    }

结论:

  1. redis中会存入大量空数据,占用内存;
  2. 只是针对某个key,当有大量不同key请求依然存在问题

二、使用布隆过滤器
在这里插入图片描述
1.maven依赖

<!-- guava引入布隆过滤器 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>

2.创建业务类BloomFilterImpl

package com.example.order.service.impl;

import com.example.order.mapper.UserOrderMapper;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;

/**
 * @author xiaozikang
 * @date 2020/10/18 15:47
 * @Email:xiaozikangwy@163.com
 */
@Component
public class BloomFilterImpl {

    // 预存的数据个数 100w
    private static int expectedInsertions = 1000000;

    //可接受的错误率
    private static double fpp = 0.001;

    // 创建布隆过滤器的对象
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(),expectedInsertions,fpp);

    @Resource
    private UserOrderMapper orderMapper;

    /**
     * BloomFilterImpl对象被创建后,立即初始化的方法
     */
    @PostConstruct
    public void initData(){
        // 查询数据库中所有的id
        List<Integer> ids = orderMapper.selectAllIds();
        // 初始化到布隆过滤器中
        for (Integer id : ids) {
            bloomFilter.put(id);
        }
    }

    /**
     * 判断布隆过滤器中是否存在该id
     * @param id
     * @return
     */
    public boolean mightContain(Integer id){
        return bloomFilter.mightContain(id);
    }

}

3.使用布隆过滤器判断

@GetMapping("info/{id}")
    public R getInfo2(@PathVariable("id") Integer id){

        Object order = redisUtil.get(String.valueOf(id));
        if (order == null){
            // 判断布隆过滤器是否已经存在
            boolean b = bloomFilter.mightContain(id);
            if (!b){
                return R.error().message("查询无果");
            }
            System.out.println("查询数据库");
            order = orderService.getById(id);
            if (order != null){
                redisUtil.set(String.valueOf(id),order);
            }
            return R.error().message("查询无果");
        }
        return R.ok().data("order",order);
    }

结论:

  1. 为了保证布隆过滤器与数据库一致,数据库进行增删也得同步redis和布隆过滤器
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值