一、有什麼用
用來修復緩存穿透的利器。什麼是緩存穿透?
面試必考的緩存穿透、雪崩、擊穿
二、是什麼
其實就是利用bitmap來解決緩存穿透的一種技術手段。
三、原理
- 容器啓動從數據庫裏讀出全部商品,通過hash計算得到一個下標作爲bitmap的位,將其置爲1。
- 用戶搜商品的時候先經過hash計算得到位下標,然後去布隆過濾器裏查看這個位下標的值是不是1,是1代表有商品,再去mysql查。若是0則直接返回沒商品即可。(位的運算極其的快,性能消耗幾乎忽略不計)
- 可能多個商品通過hash計算得到的值一樣,這就發生了hash碰撞,這也意味着布隆過濾器不是100%靠譜,可能漏掉某些商品,所以具體應用場景還得看業務需求是否允許。所以即使高併發場景也足夠了。
這裏是進行了三次不同的hash算法來減少hash碰撞的機率。
四、問題
- 如何讓碰撞機率更小?
可以讓一個商品經過N次不同的hash方法計算,然後搜索商品的時候看N次hash值在bitmap裏是不是都是1,有一個不是1就返回沒有商品。幾乎能保證99%+不碰撞。
- 如果黑客攻擊你,就是鑽了個空子,搜了個ooxx,經過三次hash計算得到的位下標在bitmap裏都是1,結果去查了db,db查完沒有這商品。然後就一直利用ooxx刷你怎麼破
你可以再加一層過濾,bitmap裏都是1,mysql裏沒有的商品放到redis裏,每次搜商品先去redis裏查下是否存在,若存在則直接返回沒有這個商品。
五、具體實現
1、三種方式
- 客戶端實現布隆算法以及自己存儲bitmap
就是完全不借助redis,用自己的jvm內存來存儲這塊bitmap。
優點:算法自定義,定義幾次算法都自己說了算。
缺點:佔用內存過大的話會產生性能問題
- 客戶端實現布隆算法,然後數據存儲交給redis,因爲redis也是支持bitmap的
優點:算法自定義,定義幾次算法都自己說了算。
缺點:佔用內存過大的話會產生性能問題
- 客戶端啥也不管,redis實現布隆過濾器算法以及bitmap存儲
這種需要redis server集成redisbloom.so模塊
優點:省事,客戶端啥也不用管
缺點:內置的布隆過濾器算法我們不知道,而且不能自定義不同算法
2、個人推薦
個人推薦第2種方式,因爲第一種方式的話所佔用的內存是jvm內存,而第2種的話完美的將這塊內存交給了緩存服務。第3種的話具體的布隆算法我們不知情,而且需要redis額外集成。第2種我們還以隨意自定義hash算法,定義幾個都是我們說了算。
3、redis-server集成布隆過濾器步驟
(1)https://redis.io/modules 找到RedisBloom
(2)點小房子,會打開這個網站https://github.com/RedisBloom/RedisBloom
(3)下載wget https://github.com/RedisBloom/RedisBloom/archive/master.zip
(4)執行如下命令
# 解壓縮剛纔的RedisBloom
unzip master.zip
cd master
# 編譯安裝
make
# make完生成redisbloom.so,拷貝到redis的安裝目錄(redis安裝時make install的目錄)
cp redisbloom.so /home/main/redis/redis5
# 修改redis配置文件,讓其集成redisbloom.so
vim /etc/redis/redis_6379
# 集成redisbloom.so
loadmodule /home/main/redis/redis5/redisbloom.so
# 啓動redis-server
redis-server /etc/redis/redis_6379
# 客戶端連接
redis-cli -p 6379
# 會多出bf.命令,可以輸入bf.然後按tab鍵查看有沒有
# 比如我們bf.add ooxx abc,相當於給abc這個商品計算了一個位下標,且設置值爲1
bf.add ooxx abc
# 這裏就是客戶端搜鎖abc,我們這邊判斷是否存在這麼一個商品,返回1就是存在
bf.exits ooxx abc
1
# 不存在sdfsdf,會返回0。這時候我們可以把sdfsdf單獨存到redis,代表黑名單商品,搜索進來發現是這個直接返回沒找到
bf.exits ooxx sdfsdf
0
六、總結
- 面試必考的緩存穿透、雪崩、擊穿
- 原理
- 問題
- 具體實現
七、個人公衆號
微信公衆號【Java碼農社區】