1. 程式人生 > >Redis實現快取與分散式鎖

Redis實現快取與分散式鎖

# 快取與分散式鎖 哪些資料適合放入快取 - 即時性、資料一致性要求不高的 - 訪問量大且更新頻率不高的資料 **選擇redis做為快取中介軟體** ```xml ``` ### 問題記錄與分析 #### 產生堆外記憶體溢位:OutOfDirectMemoryError 1. springboot2.0 以後預設使用lettuce作為操作redis的客戶端,它使用netty進行網路通訊。 2. lettuce的bug導致netty堆外記憶體溢位 解決方案: 切換到jedis(或者升級lettuce) ```xml ``` #### 高併發下快取失效問題-快取穿透 **快取穿透:** 指查詢一個一定不存在的資料,由於快取是不命中,將要去查詢資料庫,但是資料庫也沒有該記錄,我們將這次查詢的null寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義 **風險:** 利用不存在資料進行攻擊,資料庫瞬時壓力增大,最終導致崩潰 **解決:** null結果快取,並加入短暫過期時間 #### 高併發下快取失效問題-快取雪崩 **快取雪崩:** 快取雪崩是指我們設定快取時key採用了相同的過期時間,導致快取在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩。 **解決:** 原有的失效時間基礎上增加一個隨機值,比如1-5min隨機,這樣每一個快取的過期時間的重複率就會降低,就很難引發集體失效的事件。 #### 高併發下快取失效問題-快取擊穿 **快取擊穿:** - 對於一些設定了過期時間的key,如果這些key可能會在某些時間點被超高併發地訪問,是一種非常”熱點“的資料。 - 如果這個key在大量請求同時進來前正好失效,那麼所有key的資料查詢都落到db,我們稱之為快取擊穿。 **解決:** 加鎖,大量併發只讓一個請求去查,其他請求等待,查到以後釋放鎖,其他請求獲取到鎖,先查快取,就會有資料,不用去db。 **加鎖實踐:** springboot所有的元件在容器中都是單例的,可以使用synchronized(this),JUC(Lock)等解決單體應用中的問題,但是分散式系統中,要想鎖住所有資料,就必須使用分散式鎖 通過分析 分散式鎖必須保證加鎖(佔位+過期時間)和刪除鎖(判斷+刪除)的原子性。 加鎖可以使用redis setnx ex命令來操作,但是刪除鎖的時候 ,要先判斷再刪除,想把這兩步操作做成原則性的,需要採用redis+lusj指令碼的方式來操作。 ```java pu