一、缓存穿透:大量请求不命中
1.现象:
request请求在cache中未找到数据,直接查找storage
2.原因:
2.1业务代码自身问题--->在数据库中未找到数据,进入死循环
2.2恶意攻击、爬虫等--->大量不存在数据查找数据库,进入死循环
3.如何发现:
3.1业务响应时间
3.2业务本身问题
3.3相关指标:总调用数、缓存层命中数、存储层命中数
4.解决方法
4.1缓存空对象:存储层返回空对象, 使下次请求直接返回null
①如果是恶意攻击,需要占用更多的缓存空间--->缓存设置过期时间
②网络原因导致,出现缓存层和存储层数据短期的不一致
4.2布隆过滤器拦截
①位数组(二进制向量);一系列随机映射函数--->元素通过Hash函数对应位数组
②布隆过滤不存在,数据一定不存在;布隆过滤存在,数据不一定存在
private static final int insertions = 1000000; public static void main(String[] args) { System.out.println("初始化布隆过滤器,大小为100w,误判率为0.03"); BloomFilter<String> bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), insertions,0.03); System.out.println("创建示例集合"); List<String> list = new ArrayList<>(insertions); for (int i = 0; i < insertions; i++) { String uuid = UUID.randomUUID().toString(); bf.put(uuid); list.add(uuid); } System.out.println("开始过滤,1w数据,100个真的,9900个假的"); int num=0; int right=0; int wrong=0; for (int i = 0; i < 10000; i++) { String data = i % 100 == 0 ? list.get(i / 100) : UUID.randomUUID().toString(); if (bf.mightContain(data)) { num++; if (list.contains(data)) { right++; } else { wrong++; } } } NumberFormat percentFormat = NumberFormat.getPercentInstance(); percentFormat.setMaximumFractionDigits(2); System.out.println("100W中1W数据百分比结果: "); System.out.println("布隆认为存在的:"+num); System.out.println("真实存在的:"+right+"\t 正确率"+percentFormat.format((float)right/100)); System.out.println("不存在的:"+wrong+"\t 误判率:"+percentFormat.format((float)wrong/10000)); }
二、缓存击穿:热点数据集中过期
三、缓存雪崩:大量数据集中过期