前言
緩存穿透概念
當查詢一個一定不存在的數據,由於緩存不命中,去查詢數據庫也無法查詢出結果,因此不會寫入到緩存中,這會導致每個查詢都去請求數據庫,造成緩存穿透。
解決方案:
布隆過濾對所有的可能查詢的參數以hash形式存儲,在控制器層先進行校驗,不符合則丟棄,從而避免了對底層存儲系統的查詢壓力。bloomfilter就類似於一個hash set,用於快速判某個元素是否存在於集合中,其典型的應用場景就是快速判斷一個key是否存在於某容器,不存在就直接返回。舉例:將真實正確Id在添加完成之後便加入到過濾器當中,每次再進行查詢時,先確認要查詢的Id是否在過濾器中,如果不在,則說明Id爲非法Id。
緩存空對象當從數據庫查詢不到值,就把參數和控制緩存起來,設置一個簡短的過期時間(因爲緩存是需要內存的,如果有過多空值key,佔用內存多),在該時間段如果有攜帶此參數再次請求,就可以直接返回。可能導致該段時間緩存層和數據庫數據不一致,對於需要保持一致性的業務有影響。
小編覺得學習的話,就得視頻+代碼+課件配合着學習,這樣才能夠理解的最夠透徹,掌握到知識的精髓,這不,已經都給大家準備好了,大家可以好好學習一波!!!!
BloomFilter_Test.java (手寫布隆過濾器代碼)
import com.google.common.hash.Funnels;
import com.google.common.hash.Hashing;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import java.nio.charset.Charset;
public class BloomFilter_Test {
private JedisPool jedisPool = null;
private Jedis jedis = null;
//要存儲的數據量··
private static long n = 10000;
//所能容忍錯誤率
private static double fpp = 0.01F;
//bit數組長度
private static long numBits = optimalNumOfBits(n, fpp);
//hash函數個數
private int numHashFunctions = optimalNumOfHashFunctions(n, numBits);
public static void main(String[] args) {
System.out.println(numBits);
// long[] indexs = new BloomFilter_Test().getIndexs("hello");
BloomFilter_Test filterTest = new BloomFilter_Test();
filterTest.init();
int ex_count = 0;
int ne_count = 0;
/**
* 存在: 不一定存在
* 不存在:一定不存在
*/
for (int i = 0; i < 20000; i++) {
// filterTest.put("bf",100 + i + "");
boolean exist = filterTest.isExist("bf", 100 + i + "");
if(exist){
ex_count++;
}else{
ne_count++;
}
}
//ex_count:6729 ne_count 3271
System.out.println("ex_count:" + ex_count + "\t" + "ne_count " + ne_count);
}
public void init(){
//測試連接redis
jedisPool = new JedisPool("192.168.150.111", 6379);
jedis = jedisPool.getResource();
}
private long getCount(){
Pipeline pipeline = jedis.pipelined();
Response<Long> bf = pipeline.bitcount("bf");
pipeline.sync();
Long count = bf.get();
pipeline.close();
return count;
}
/**
* 判斷keys是否存在於集合where中
*/
public boolean isExist(String where, String key) {
long[] indexs = getIndexs(key);
boolean result;
//這裏使用了Redis管道來降低過濾器運行當中訪問Redis次數 降低Redis併發量
Pipeline pipeline = jedis.pipelined();
try {
for (long index : indexs) {
pipeline.getbit(where, index);
}
result = !pipeline.syncAndReturnAll().contains(false);
} finally {
pipeline.close();
}
// if (!result) {
// put(where, key);
// }
return result;
}
/**
* 將key存入redis bitmap
*/
private void put(String where, String key) {
long[] indexs = getIndexs(key);
//這裏使用了Redis管道來降低過濾器運行當中訪問Redis次數 降低Redis併發量
Pipeline pipeline = jedis.pipelined();
try {
for (long index : indexs) {
pipeline.setbit(where, index, true);
}
pipeline.sync();
/**
* 把數據存儲到mysql中
*/
} finally {
pipeline.close();
}
}
這只是部分代碼~~~
布隆過濾器算法課件
Redis緩存穿透終極解決方案,手寫布隆過濾器,學習視頻+代碼+課件
需要的小夥伴,可以轉發評論關注小編↓↓↓↓↓↓↓↓錯過今天,時不再來!
好的東西就要分享給大家學習!