你管這破玩意叫緩存穿透?還是緩存擊穿?
大家好,我是哪吒。
今天分享一下Redis布隆過濾器的原理和應用場景,解決緩存穿透,實現快速入門,豐富個人簡歷,提高面試level,給自己增加一點談資,秒變面試小達人,BAT不是夢。
一、緩存預熱
Redis緩存預熱是指在服務器啟動或應用程序啟動之前,將一些數據先存儲到Redis中,以提高Redis的性能和數據一致性。這可以減少服務器在啟動或應用程序啟動時的數據傳輸量和延遲,從而提高應用程序的性能和可靠性。
1、緩存預熱常見步驟
(1)數據準備
在應用程序啟動或服務器啟動之前,準備一些數據,這些數據可以是靜態數據、緩存數據或其他需要預熱的數據。
(2)數據存儲
將數據存儲到Redis中,可以使用Redis的列表(List)數據類型或集合(Set)數據類型。
(3)數據預熱
在服務器啟動或應用程序啟動之前,將數據存儲到Redis中。可以使用Redis的客戶端工具或命令行工具來執行此操作。
(4)數據清洗
在服務器啟動或應用程序啟動之后,可能會對存儲在Redis中的數據進行清洗和處理。例如,可以刪除過期的數據、修改錯誤的數據等。
需要注意的是,Redis緩存預熱可能會增加服務器的開銷,因此應該在必要時進行。同時,為了減少預熱的次數,可以考慮使用Redis的其他數據類型,如哈希表(Hash)或有序集合(Sorted Set)。此外,為了提高數據一致性和性能,可以使用Redis的持久化功能,將數據存儲到Redis中,并在服務器重啟后自動恢復數據。
2、代碼實現
@Component
@Slf4j
public class BloomFilterInit
{
@Resource
private RedisTemplate redisTemplate;
//初始化白名單數據
@PostConstruct
public void init() {
//1 白名單客戶加載到布隆過濾器
String key = "customer:1";
//2 計算hashValue,由于存在計算出來負數的可能,我們取絕對值
int hashValue = Math.abs(key.hashCode());
//3 通過hashValue和2的32次方后取余,獲得對應的下標坑位
long index = (long)(hashValue % Math.pow(2,32));
log.info(key+" 對應的坑位index:{}",index);
//4 設置redis里面的bitmap對應類型白名單:whitelistCustomer的坑位,將該值設置為1
redisTemplate.opsForValue().setBit("whitelistCustomer",index,true);
}
}
二、緩存雪崩
Redis緩存雪崩是指在緩存系統中,由于某些原因,緩存的數據突然大量地被刪除或修改,導致緩存系統的性能下降,甚至無法正常工作。
1、什么情況會發生緩存雪崩?
(1)誤刪除
由于誤操作或故障,緩存系統可能會誤刪除一些正常的數據。這種情況通常會在數據庫中發生。
(2)誤修改
由于誤操作或故障,緩存系統可能會誤修改一些正常的數據。這種情況通常會在數據庫中發生。
(3)負載波動
緩存系統通常會承受一定的負載波動,例如,在高峰期間,數據量可能會大幅增加,從而導致緩存系統的性能下降。
(4)數據變化頻繁
如果緩存系統中的數據變化頻繁,例如,每秒鐘都會有大量的數據插入或刪除,那么緩存系統可能會因為響應過慢而導致雪崩。
2、Redis緩存集群實現高可用
- 主從 + 哨兵
- Redis集群
- 開啟Redis持久化機制aof/rdb,盡快恢復緩存集群。
3、如何避免Redis緩存雪崩?
(1)數據備份
定期備份數據,以防止誤刪除或誤修改。
(2)數據同步
定期同步數據,以防止數據不一致。
(3)負載均衡
使用負載均衡器將請求分配到多個Redis實例上,以減輕單個實例的負載。
(4)數據優化
優化數據庫結構,減少數據變化頻繁的情況。
(5)監控與告警
監控Redis實例的性能指標,及時發現緩存系統的異常,并發出告警。
三、緩存穿透
Redis緩存穿透是指在Redis緩存系統中,由于某些原因,緩存的數據無法被正常訪問或處理,導致緩存失去了它的作用。
1、什么情況會發生緩存穿透?
(1)數據量過大
當緩存中存儲的數據量過大時,緩存的數據量可能會超過Redis的數據存儲限制,從而導致緩存失去了它的作用。
(2)數據更新頻繁
當緩存中存儲的數據更新頻繁時,緩存的數據可能會出現異步的變化,導致緩存無法被正常訪問。
(3)數據過期
當緩存中存儲的數據過期時,緩存的數據可能會失去它的作用,因為Redis會在一定時間后自動將過期的數據刪除。
(4)數據權限限制
當緩存中存儲的數據受到權限限制時,只有擁有足夠權限的用戶才能訪問和處理這些數據,從而導致緩存失去了它的作用。
(5)Redis性能瓶頸
當Redis服務器的性能達到極限時,Redis緩存可能會因為響應過慢而導致穿透。
2、如何避免Redis緩存穿透?
(1)設置合理的緩存大小
根據實際需求設置合理的緩存大小,以避免緩存穿透。
(2)優化數據結構
根據實際需求優化數據結構,以減少數據的大小和更新頻率。
(3)設置合理的過期時間
設置合理的過期時間,以避免緩存失去它的作用。
(4)增加Redis的并發處理能力
通過增加Redis的并發處理能力,以提高緩存的處理能力和響應速度。
(5)優化Redis服務器的硬件和軟件配置
通過優化Redis服務器的硬件和軟件配置,以提高Redis的性能和處理能力。
Redis緩存穿透
四、通過空對象緩存解決緩存穿透
如果發生了緩存穿透,可以針對要查詢的數據,在Redis中插入一條數據,添加一個約定好的默認值,比如defaultNull。
比如你想通過某個id查詢某某訂單,Redis中沒有,MySQL中也沒有,此時,就可以在Redis中插入一條,存為defaultNull,下次再查詢就有了,因為是提前約定好的,前端也明白是啥意思,一切OK,歲月靜好。
這種方式只能解決key相同的情況,如果key都不同,則完蛋。
五、Google布隆過濾器Guava解決緩存穿透
1、引入pom
<!--guava Google 開源的 Guava 中自帶的布隆過濾器-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
2、創建布隆過濾器
BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 100);
布隆過濾器中添加元素。
bloomFilter.mightContain(1)
判斷布隆過濾器中是否存在。
bloomFilter.mightContain(1)
3、fpp誤判率
@Service
@Slf4j
public class GuavaBloomFilterService {
public static final int SIZE = 1000000;
//誤判率
public static double fpp = 0.01;
//創建guava布隆過濾器
private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), SIZE, fpp);
public void guavaBloomFilter() {
for (int i = 1; i <= SIZE; i++) {
bloomFilter.put(i);
}
ArrayList<Integer> list = new ArrayList<>(10000);
for (int i = SIZE + 1; i <= SIZE + (10000); i++) {
if (bloomFilter.mightContain(i)) {
log.info("被誤判了:{}", i);
list.add(i);
}
}
log.info("誤判總數量:{}", list.size());
}
}
六、Redis緩存擊穿
Redis緩存擊穿是指在Redis緩存系統中,由于某些原因,緩存的數據無法被正常訪問或處理,導致緩存失去了它的作用。
1、什么情況會發生緩存擊穿?
根本原因:熱點Key失效。
(1)數據量過大
當緩存中存儲的數據量過大時,緩存的數據量可能會超過Redis的數據存儲限制,從而導致緩存失去了它的作用。
(2)數據更新頻繁
當緩存中存儲的數據更新頻繁時,緩存的數據可能會出現異步的變化,導致緩存無法被正常訪問。
(3)數據過期
當緩存中存儲的數據過期時,緩存的數據可能會失去它的作用,因為Redis會在一定時間后自動將過期的數據刪除。
(4)數據權限限制
當緩存中存儲的數據受到權限限制時,只有擁有足夠權限的用戶才能訪問和處理這些數據,從而導致緩存失去了它的作用。
(5)Redis性能瓶頸
當Redis服務器的性能達到極限時,Redis緩存可能會因為響應過慢而導致擊穿。
2、如何避免Redis緩存擊穿?
(1)設置合理的緩存大小
根據實際需求設置合理的緩存大小,以避免緩存穿透。
(2)優化數據結構
根據實際需求優化數據結構,以減少數據的大小和更新頻率。
(3)設置合理的過期時間
設置合理的過期時間,以避免緩存失去它的作用。
(4)增加Redis的并發處理能力
通過增加Redis的并發處理能力,以提高緩存的處理能力和響應速度。
(5)優化Redis服務器的硬件和軟件配置
通過優化Redis服務器的硬件和軟件配置,以提高Redis的性能和處理能力。
七、Redis緩存擊穿解決方案
1、互斥更新
通過雙檢加鎖機制。
2、差異失效時間
先更新從緩存B,再更新主緩存A,而且讓從緩存B的緩存失效時間長于A,保證A失效時,B還在。
本文轉載自微信公眾號「哪吒編程」,可以通過以下二維碼關注。轉載本文請聯系哪吒編程公眾號。