高併發下快取技術應用

2021-09-06 15:30:28 字數 3652 閱讀 7539

背景

在某些電商促消活動中需要搞活動,對某些頁面的訪問量(qps)往往會非常高。如果直接讀資料庫,肯定db會承受不住。那比較常見的方案就是讓大部分相同資訊的請求都盡可能壓在cache上來緩解db的壓力,從而盡可能去滿足高併發訪問的需求

優化:這種快取技術一般用於不會經常變動資訊,並且訪問次數較多的頁面,這樣就不用每次都動態載入。

/*手動渲染 利用thymeleaf 的 thymeleafviewresolver*/

springwebcontext ctx =

newspringwebcontext

(request,response,request.

getservletcontext()

,request.

getlocale()

, model.

asmap()

;// model 就是將引數存入 ,其中的所有引數 都是為了將頁面渲染出來 放入其中,在返回乙個靜態的html原始碼

/*利用 gettemplateengine()方法的process() 方法,需要傳入模板名稱和context 變數*/

html = thymeleafviewresolver.

gettemplateengine()

.process

("goods_list"

,ctx)

;//ctx + 模板 返回原始碼

/*得到手動渲染的模板*/if(

!stringutils.

isempty

(html)

)return html;

}當訪問list頁面的時候,從快取中取如果取到就返回這個html,(這裡方法的返回格式已經設定為text/htm,這樣就是返回html的源**),如果取不到,利用thymeleafviewresolver的gettemplateengine().process和我們獲取到的資料,渲染模板

並存入快取,然後返回給前端。

一般這個頁面快取時間,也不會很長,防止資料的時效性很低。但是可以防止短時間大併發訪問。

與頁面快取相似

相比頁面快取是更細粒度快取 + 快取 更新。在實際專案中, 不會大規模使用頁面快取,因為涉及到分頁,一般只快取前面1-2頁。

物件快取就是 當用到使用者資料的時候,可以從快取中取出。比如:更新使用者密碼

/** 將從資料庫取物件 利用優化變為從快取中取 物件資料

/** 將從資料庫取物件 利用優化變為從快取中取 物件資料

* * @param id

* @return

*/public miaoshauser getbyid

(long id)

//取不到 從資料庫裡取 再放到 快取裡

user = miaoshauserdao.

getbyid

(id);if

(user !=null)

return user;

}

在進行物件更新時進行資料庫加密更新操作後,直接刪除redis內的對應使用者的redis值,但是token 快取不能刪除,而是應該修改重新設定,不然就無法登陸了(因為我們登陸是從快取中取),所以要進行更新操作,再將更新後的物件資訊存入redis中

/**更新使用者密碼方法: 涉及到物件快取 ---若更新物件快取的相關的資料 要處理快取

* 同步資料庫和快取的資訊,不然會造成資料不一致的情況

* */

public

boolean

updatepassword

(string token,

long id,string formpassword)

// 更新資料庫 資訊

miaoshauser updateuser =

newmiaoshauser()

; updateuser.

setid

(id)

;/*設定密碼 到資料庫 ,這時候 應該是formpassword ,更新密碼一定是先在前端填入 密碼,然後前端做 一次 加密傳進來*/

updateuser.

setpassword

(md5util.

formpasstodbpass

(formpassword,user.

getsalt()

)); miaoshauserdao.

updatepassword

(updateuser)

;// 更新完資料庫資訊,防止快取中資訊不一致,處理快取 且涉及到所有該物件的快取都需要處理

// 乙個 是 根據 token 獲取物件,所以需要更新 token key 的快取物件資料, 乙個是根據id 獲取物件,同理

/** 處理快取:

* 1. 刪除相關快取資料

* 2. 更新相關快取中的資料

* */

redisservice.

delete

(miaoshauserkey.getbyname,

""+id)

;//該物件快取可以直接刪,因為沒有可以從資料取

//但是token 快取不能刪除,而是應該修改重新設定,不然就無法登陸了(因為我們登陸是從快取中取)

user.

setpassword

(updateuser.

getpassword()

);//將物件 攜帶新的密碼放入快取

redisservice.

set(miaoshauserkey.token,token,user)

;return

true

;}

1.更新快取後保證資料庫中資料和快取資料一致性。 可以選擇淘汰快取和更新快取

淘汰:價效比高,僅僅會設計一次未命中,再從資料庫取

更新:操作複雜,涉及到對應的業務邏輯。

更新快取很直接,但是涉及到本次更新的資料結果需要一堆資料運算(例如更新使用者餘額,可能需要先看看有沒有優惠券等),複雜度就增加了。而淘汰快取僅僅會增加一次cache miss,代價可以忽略,所以建議淘汰快取)

2.若一定要更新,比如登陸狀態下,更新密碼,那一定要更新快取,因為 session從快取中拿,密碼不一致,會導致登陸失效

這裡先淘汰快取,在更新資料庫資訊。(若先更新在淘汰,淘汰失敗快取中有髒資料)

保證資料一致性。

高併發下快取失效問題

快取穿透 指查詢乙個一定不存在的資料,由於快取是不命中,將去查詢資料庫,但是資料庫也無此記錄,我們沒有將這次查詢的null寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義 風險 利用不存在的資料進行攻擊,資料庫瞬時壓力增大,最終導致崩潰 解決 null結果快取,並加入短...

高併發下快取失效問題

1.快取穿透 查詢乙個一定不存在的資料,由於快取一定不命中,將查詢資料庫,並且沒有將null寫入快取,這將導致這個不存在的資料每次請求都到儲存層查詢。風險 利用不存在的資料進行攻擊,資料庫瞬時壓力增大,最終導致崩潰。解決方案 null結果快取,並加入短暫過期時間。2.快取雪崩 指設定快取時key採用...

高併發下快取穿透 快取雪崩,快取擊穿

併發進來後第乙個請求到達資料庫後,得到的資料並不存在,那麼這時返回null,這個null也會同時存在快取中,然而做快取判斷是,快取中為null就會去資料庫中查詢,那麼這時後面的併發,在來查詢這個不存在的資料是都會進入資料庫 導致資料庫壓力過大,從而導致系統崩潰 快取的key大面積的失效,如100萬的...