Redis实例案件--缓存雪崩、穿透

echo编辑整理,欢迎转载,转载请声明文章来源。欢迎添加echo微信(微信号:t2421499075)交流学习。 百战不败,依不自称常胜,百败不颓,依能奋力前行。——这才是真正的堪称强大!!!


本文主要描述了Redis的一些真实异常案例,但是都是总结是的描写。仅仅讲述了雪崩和穿透,对于穿透描述了布隆过滤器的使用。如果有需要可以继续阅读,对于这两种情况比较熟悉的可以绕过。

什么是缓存雪崩?

简单说就是数据存在不断查询引起的。缓存雪崩其实是一个比较特殊的情况,它的主要引起原因是Redis的数据大批量过期,导致的某个Redis出现宕机或者多个Redis宕机,然后宕机滚雪球,最终导致真个服务瘫痪。根本的原因最常见的就是我们Redis的大量数据设置统一的过期时间,当我们Redis中数据过期之后,瞬间会对Redis造成相当大的压力,如果数据过期之后,我们需要马上查询数据库来更新缓存,这个时候会产生很大的访问量,导致数据库压力剧增,很有可能数据库也因此就瘫痪了。

怎么解决缓存雪崩情况?

  • 永不过期
  • 随机设置过期时间
  • 预更新

什么是缓存穿透?

简单说是数据不存在的查询导致的。真实案例:互联网行业快速发展,线上的订购量也不断逐年上增,随着而来的快递查询服务剧增,某某电商公司,在公司的快递查询入口上做了Redis集群,以便于大量用户的访问和大量数据的快速吞吐。某日该快递查询入口收到大量的空订单请求(订单号是不存在的),Redis集群接受请求之后,发现数据在Redis不存在,最终请求全部转发数据库导致数据库瘫痪。这是一个真实的案例,也就是我们常说的缓存穿透。引起的原因就是Redis集群中并没有访问需要的订单号,该请求就直接绕过了Redis集群,直接导致数据库瘫痪。解决办法:让我们的请求先判断数据库是否存在该数据,存在的情况然后才查询数据库。

怎么解决?

  • 布隆过滤器

布隆过滤器特点

  • 如果布隆过滤器判断元素返回存在,有可能这个元素不存在(hash碰撞)
  • 如果布隆过滤器判断元素返回不存在,那么一定不存在

布隆过滤器的实现

public class BloomFilterDemo {
    private static final int insertions = 1000000;

    public static void main(String[] args) {

        // 初始化一个存储string数据的布隆过滤器,初始化大小为100W
        // 默认误判率是0.03
        BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), insertions);

        // 用于存放所有实际存在的key,判断key是否存在
        Set<String> sets = new HashSet<String>(insertions);

        // 用于存放所有实际存在的key,可以取出使用
        List<String> lists = new ArrayList<String>(insertions);

        // 向三个容器初始化100W个随机并且唯一的字符串
        for (int i = 0; i < insertions; i++) {
            String uuid = UUID.randomUUID().toString();
            bf.put(uuid);
            sets.add(uuid);
            lists.add(uuid);
        }

        int right = 0; // 正确判断的次数
        int wrong = 0; // 错误判断的次数

        for (int i = 0; i < 10000; i++) {
            // 可以被100整除的时候,取一个存在的数。否则随机生成一个UUID
            // 0-10000之间,可以被100整除的数有100个(100的倍数)
            String data = i % 100 == 0 ? lists.get(i / 100) : UUID.randomUUID().toString();

            if (bf.mightContain(data)) {
                if (sets.contains(data)) {
                    // 判断存在实际存在的时候,命中
                    right++;
                    continue;
                }
                // 判断存在却不存在的时候,错误
                wrong++;
            }
        }

        NumberFormat percentFormat =NumberFormat.getPercentInstance();
        percentFormat.setMaximumFractionDigits(2); //最大小数位数
        float percent = (float) wrong / 9900;
        float bingo = (float) (9900 - wrong) / 9900;

        System.out.println("在100W个元素中,判断100个实际存在的元素,布隆过滤器认为存在的:"+right);
        System.out.println("在100W个元素中,判断9900个实际不存在的元素,误认为存在的:"+wrong+"" +
                ",命中率:" + percentFormat.format(bingo) + ",误判率:" + percentFormat.format(percent) );
    }
}

注意

布隆过滤器存在一定的误判率,但是并不印象我们目前的场景,如果对于误判精度较高的场景布隆过滤器不一定合适。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xlecho

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值