解決(緩解)大量不存在的緩存請求到數據庫,即緩存擊穿
由布隆提出的,她本身是一個很長的二進制向量
也就是說布隆過濾器只能判斷數據是否一定不存在,而無法判斷數據是否一定存在。
- 優點:由於存放的不是完整的數據,所以佔用的內存很少,而且新增,查詢速度夠快;
- 缺點: 隨着數據的增加,誤判率隨之增加;無法做到刪除數據;只能判斷數據是否一定不存在,而無法判斷數據是否一定存在。
guava實現布過濾器
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 < 1000000; i++) {
bloomFilter.put(i);
}
int count = 0;
for (int i = 1000000; i < 2000000; i++) {
if (bloomFilter.mightContain(i)) {
count++;
System.out.println(i + "誤判了");
}
}
System.out.println("總共的誤判數:" + count);
}
redisson實現布隆過濾器
假設一個網頁黑名單有URL爲100億,每個樣本爲64B,失誤率爲0.01%,
經過上述公式計算後,需要布隆過濾器大小爲25GB,這遠遠小於使用哈希表的640GB的空間。
並且由於是通過hash進行查找的,所以基本都可以在O(1)的時間完成!
@PostMapping("/addUser")
public Integer insert(@RequestBody MUser user) {
RBloomFilter<String> bloomFilter = redisson.getBloomFilter(Constant.REDISSON_BLOOMFILTER_USER);
//布隆過濾器計算的正確率爲97%,初始化布隆過濾器容量爲50000L
bloomFilter.tryInit(500000L,0.03);
if (bloomFilter.contains(user.getName())) {
throw new InvalidArgumentException("用戶名:" + user.getName() + "已經存在");
}
user.setId(null);
int res = userMapper.insertSelective(user);
if (res > 0) {
//加入布隆過濾器
bloomFilter.add(user.getName());
}
return user.getId();
}