網站首頁 編程語言 正文
前言
隨著我們業務開發越來越來大,并染請求就會越來越多,那么我們的項目的壓力就會越來越大,基本都會使用緩存,除本地緩存,還會用到redis緩存,但是你以為使用緩存就沒啥問題了么,那肯定不是的,使用了緩存又會出現新的問題,比如,緩存的key失效導致大量的請求到數據庫,大量的讀請求瞬間到達了數據庫,cpu的使用率爆增,導致數據庫都可能掛掉,這種情況下我們就要考慮使用redis的布隆過濾器了。
緩存穿透、擊穿、雪崩
首先我們從緩存會出現的幾種問題,來進行分析,在高并發的場景下如果出現這種情況,我們應該如何解決。
正常情況下,我們的web應用會先去請求緩存服務,如果緩存命中,那么就去拿緩存里面的數據,返回結果給應用,
緩存穿透
緩存穿透與緩存雪崩和緩存擊穿還是不一樣的,雪崩和擊穿的情況下,數據庫的數據都是真正常的,可以去請求數據庫獲取數據,只是緩存層出現問題,等待緩存恢復了,就會減輕數據庫的壓力。 而緩存透不一樣的就是,緩存和數據庫都沒有要請求的數據,大量的請求來了,數據庫的壓力很大。
出現情況
- 數據庫數據被大量清除,導致訪問不到
- 黑客惡意攻擊
常見的解決方案
- redis緩存空值,請求不到的時候返回給應用空值。
- 使用布隆過濾器,把數據庫的一部分數據hash到布隆過濾器里,在請求數據庫之前先去布隆過濾器里篩選到一部分請求,判斷數據是否存在,避免直接去訪問數據庫。
緩存擊穿
出現情況
- 大量熱點數據庫過期,導致無法從緩存獲取到數據,大量請求數據庫也無法返回書就
解決方案
- 加鎖,保證同一時間內,只允許有一個線程去更新緩存,等鎖釋放后在重新去請求緩存。
- 熱點數據不去設置過期時間,如果要設置過期時間,在過期的時候通知后臺去更新緩存的過期時間。
緩存雪崩
- 大量緩存在同一時間失效,導致大量請求進入數據庫
- redis故障宕機,導致緩存不能使用。
解決方案
- 同上加鎖
- 給緩存的過期時間加入隨機數,保證緩存不會在同一時間同時失效。
- 副本key策略,就是對于一個key,在它的基礎上在設置一個key,它們的value都是一樣的,只不過一個設置過期時間、一個不設置過期時間,相當于給key做了個副本,只不過在更新緩存的時候,副本key也是要更新的,避免出現數據不一致的現象。
布隆過濾器 Bloom filter
前面提到過布隆過濾器在請求比較高的時候,可以幫助我們抵擋一部分請求,從而減輕數據庫的壓力,布隆過濾器的數據結構是一個二進制的bit向量,或者說是一個bit數組,它相對于list、set、map這些集合,它占用的空間更少,不足之處處就是返回的結果會有一定概率的誤差。
public static void main(String[] args) {
int size = 1_000_000;
BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);
for (int i = 0; i < size; i++) {
bloomFilter.put(i);
}
for (int i = 0; i < size; i++) {
if (!bloomFilter.mightContain(i)) {
System.out.println("有漏網之魚");
}
}
List<Integer> list = new ArrayList<>(1000);
for (int i = size + 10000; i < size + 20000; i++) {
if (bloomFilter.mightContain(i)) {
list.add(i);
}
}
System.out.println("有誤差的數量:" + list.size());
}
確實有誤差的數量,但是誤差量不大,追求效率的同時只是犧牲一點誤差了。
總結
加鎖的排隊的場景確實能幫助我們很好的解決緩存穿透、擊穿的一些問題,但是效率也是非常低了,因為每個請求都是排隊等待,如果可以接受輕微誤差的話,布隆過濾器的確是個很不錯的選擇,Bloom filter的bitmap的存儲效率確實很高。
原文鏈接:https://juejin.cn/post/7181839631728508965
相關推薦
- 2022-04-19 Django的開發步驟原來是這樣的_python
- 2022-11-03 anaconda?部署Jupyter?Notebook服務器過程詳解_python
- 2022-05-07 Qt+OpenCV實現目標檢測詳解_C 語言
- 2022-07-15 C#中Timer定時器類的簡單使用_C#教程
- 2022-10-16 Python實現自定義Jupyter魔法命令_python
- 2022-08-13 Flutter實現不同縮放動畫效果詳解_Android
- 2022-06-06 Python字符串常規操作小結_python
- 2022-07-20 C/C++詳解實現二層轉發_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支