Redis缓存问题

项目中为什么使用缓存:

  • 加快系统的响应速度,提高系统吞吐量
  • 通过缓存可以减少瞬间大量的请求操作数据库,减少数据库IO;避免数据库系统瘫痪,而引起系统不可用

一、缓存穿透:

概念:缓存key对应的数据在缓存中不存在,并且在数据中也不存在;每次请求都会到达数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库
解决方法:

1、缓存null对象:直接把数据库查询的数据放入redis中,即使他是一个空对象;这样可以解决同一个key反复请求数据的问题

缺点:

  • 如果更换key他依然会去查询一次数据库,如果有黑客使用一个随机不存在的key频繁访问依然会影响数据库
  • 缓存空对象会占用内存

2、布隆过滤器

布隆过滤器:(Bloom Filter)是由布隆在1970年提出的。它实际上是由一个很长的二进制向量和一系列随机映射函数组成,布隆过滤器可以用于检索一个元素是否在一个集合中

算法:
1. 根据一定的规则(误判率)计算出一个长度为n比特的数组,每个比特位初始化为0
2.根据一定的规则(误判率)计算需要k个hash函数,每个函数可以把key散列成为1个整数
3. 某个key加入集合时,用k个hash函数计算出k个散列值,把每个散列值映射到bit数组对应的bit位,并设置为1
4. 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为在集合中

优点:使用bit位表示元素是否存在,占用空间小;
缺点:

  • 存在误识别率:误判一个元素存在集合中,而实际上他并不存在(不会存在漏报:一个元素不存在数据集中,那么布隆过滤器一定不会判断他存在)
  • 删除元素困难:因为同一个bit位可能也标识其他元素;无法删除元素带来的问题是,如果我们把数据集的元素删除了,而布隆过滤器会判断他存在,这样请求依然会进入数据库,如果删除的数据较多我们应该重写布隆过滤器中的数据
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <optional>true</optional>
</dependency>
    private static int size = 1000000;//预计要插入多少数据
    private static double fpp = 0.01;//期望的误判率
    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);
    public static void main(String[] args) {
        //插入数据
        for (int i = 0; i < size; i++) {
            bloomFilter.put(i);
        }
        int count = 0;
        for (int i = size; i < size*2; i++) {
            if (bloomFilter.mightContain(i)) {
                count++;
                System.out.println(i + "误判了");
            }
        }
        System.out.println("总共的误判数:" + count); //总共的误判数:10314
    }

按照我们程序的执行结果可得出误判率=10314/1000000=0.010314(判断元素是否存在,应该是1000000个不存在) ,和我们定义的期望误差率0.01 接近

二、缓存击穿

概念:缓存key对应的数据存在,但在缓存中已经过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端数据库加载数据并回写缓存,这个时候大并发的请求可能会瞬间把数据库压垮;例如redis中key的过期时间;该类数据一般是热点数据

解决方案:

  • 如果是分布式系统使用分布式锁
  • 如果是单机部署JVM锁就可以

伪代码:们需要查缓存两次,这样可以保证在并发场景下,只有第一个线程去查数据库,后面的线程可以用缓存数据

redis.get(key)
lock()
redis.get(key)
select.db
redis.set(key,value)
unlock()

三、缓存雪崩

概念:缓存雪崩是指缓存中的数据大批量到过期时间或者缓存服务器宕机,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方法:

  • 缓存服务器:缓存服务器要高可用,例如redis搭建集群或者一主n备
  • 过期时间:分散各个key对应的过期时间
  • 服务限流或者降级、熔断

四、缓存一致性问题

redis缓存与数据库数据不一致问题

解决方法:

  • 延迟双删:休眠时间无法确定,该方法不靠谱
  • 使用队列:使用队列可以保证命令的顺序执行,但是影响系统的效率
  •  canal同步mysql的binlog:
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值