大數據專家,教你學Redis緩存穿透終極解決方案,手寫布隆過濾器

前言

緩存穿透概念

當查詢一個一定不存在的數據,由於緩存不命中,去查詢數據庫也無法查詢出結果,因此不會寫入到緩存中,這會導致每個查詢都去請求數據庫,造成緩存穿透。

大數據專家,教你學Redis緩存穿透終極解決方案,手寫布隆過濾器

 

解決方案:

布隆過濾對所有的可能查詢的參數以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緩存穿透終極解決方案,手寫布隆過濾器

 

大數據專家,教你學Redis緩存穿透終極解決方案,手寫布隆過濾器

 

大數據專家,教你學Redis緩存穿透終極解決方案,手寫布隆過濾器

 

Redis緩存穿透終極解決方案,手寫布隆過濾器,學習視頻+代碼+課件

 

需要的小夥伴,可以轉發評論關注小編↓↓↓↓↓↓↓↓錯過今天,時不再來!

好的東西就要分享給大家學習!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章