Redis緩存問題—緩存穿透、緩存擊穿與緩存雪崩

概述

  • Redis緩存的使用,極大的提升了應用程序的性能和效率,特別是數據查詢方面。但同時,它也帶來了一些問題。其中,最要害的問題,就是數據的一致性問題,從嚴格意義上講,這個問題無解。如果對數據的一致性要求很高,那麼就不能使用緩存。
  • 在緩存使用的過程中也存在一些典型的問題:緩存擊穿、緩存穿透、緩存雪崩
Redis緩存問題—緩存穿透、緩存擊穿與緩存雪崩

緩存擊穿

  • 緩存擊穿,大併發集中對某一數據進行訪問,並且緩存中不存在訪問的數據(第一次訪問或者緩存過期),持續的大併發就穿破緩存,直接請求數據庫。
  • 雙重檢測鎖機制(提升效率)
  • ItemService
<code>public Item queryItemById(String itemId){
Item item = itemCacheHander.getItemFromCache(itemId);
if(item == null) {
synchronized (this) {
item = itemCacheHander.getItemFromCache(itemId);
if (item == null) {
System.out.println("--------------查詢數據庫");
item = itemDAO.queryItem(itemId);
itemCacheHander.addItemToCache(item);
}
}
}
return item;
}/<code>

緩存穿透

  • 緩存穿透,是指查詢一個數據庫不存在的數據。首先查詢緩存,緩存中不存在則查詢數據庫,數據查詢到的數據依然為空,設置到緩存中也為空;因此後續所有對次數據的查詢都會先查詢緩存,緩存不存在繼而又查詢數據庫。
  • 即使數據庫查詢為空,也向緩衝中寫入非空值
  • ItemCacheHandler
<code>/**
* 存緩存
* @param item
*/
public void addItemToCacheEx(Item item){
String json = new Gson().toJson(item);
//設置過期時間
redisTemplate.boundValueOps("item-"+item.getItemId()).set(json,5);
}/<code>
  • ItemService
<code>public Item queryItemById(String itemId){
Item item = itemCacheHander.getItemFromCache(itemId);
if(item == null) {
synchronized (this) {
item = itemCacheHander.getItemFromCache(itemId);
if (item == null) {
System.out.println("--------------查詢數據庫");
item = itemDAO.queryItem(itemId);
// 如果從數據庫查詢信息為null,則創建一個對象寫入到緩衝,並設置過期時間
if(item == null) {
item = new Item();
item.setItemId(itemId);
itemCacheHander.addItemToCacheEx(item);
}else {
itemCacheHander.addItemToCache(item);
}

}

}
}
return item;
}/<code>

緩存雪崩

  • 緩存雪崩,是指在某一個時間段,緩存集中過期失效,則大量的併發訪問查詢都落到了數據庫上。
  • 例如馬上就要到雙十一零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了緩存,假設緩存一個小時。那麼到了凌晨一點鐘的時候,這批商品的緩存就都過期了。而對這批商品的訪問查詢,都落到了數據庫上,對於數據庫而言,就會產生週期性的壓力波峰。


分享到:


相關文章: