高並發之緩存的特徵和應用
知識
09-20
- 緩存的特徵
- 命中率:命中數/(命中數 + 沒有命中數),命中率越高產生收益也就越高,性能也就越好,相應的也就越短,吞吐量也就越高,抗並發的能力也就越強
- 最大元素(空間):緩存中科院存放的最大元素的數量,當緩存的數量超過了緩存空間,則會觸發緩存清空策略
- 清空策略:
- FIFO先進先出策略,先進入的優先清除,
- LFU最少使用策略,對比命中數,
- LRU最近最少使用策略,
- 過期時間,
- 隨機等等。
- 緩存的分類和應用場景
- 本地緩存:Guava Cache,SpringMVC本地緩存,Mybatis二級緩存
- 分散式緩存:Memceche,Redis
- Guava Cache緩存的基本使用
- 如果cache,get("key1"),是去查詢緩存如果沒有命中的話就去調用load方法
- 高並發場景緩存會出現的問題
- 緩存的一致性
- 更新資料庫成功---更新緩存失敗
- 更新緩存成功---更新資料庫失敗
- 更新資料庫成功---淘汰緩存失敗
- 淘汰緩存成功---更新資料庫失敗
- 緩存並發
- 並發時請求緩存時已過期或者沒有命中或者更新的情況下有大量的請求訪問資料庫,
- 解決辦法:在緩存更新或者過期的情況下,先嘗試獲取到lock,當更新完成後,嘗試釋放鎖,其他的請求只需要犧牲一定的等待時間
- 緩存穿透
- 在高並發的場景下,如果某一個key被高並發的訪問沒有被命中,出於對容錯性的考慮會嘗試從後端的資料庫獲取,從而導致大量的請求訪問了資料庫,主要是當key對應的數據為空或者為null的情況下,
- 解決方法:
- .對查詢結果為空的對象也進行緩存,如果是集合可以緩存一個空的集合,而不是null,如果是單個對象可以通過欄位標識來區分,(實現相對簡單)
- 對所有可能對應數據為空的key進行統一的存放,並在請求前做攔截(實現相對複雜)
- 緩存雪崩現象
- 以上都有可能導致緩存雪崩,還有緩存周期性的時效也有可能導致緩存的雪崩,可以通過設置不同的過期時間來避免緩存失效
- 高並發緩存之Redis緩存的應用
- 應用場景之匯率顯示,各個國家的匯率是不同的,而且時刻都在改變,那麼如何動態的實時顯示數據呢?首先我們的數據來源第三方介面,當調用第三方介面推送給我們的數據需要進行數據清洗,然後利用利用GuavaCache 緩存最近幾分鐘內所有匯率的分時數據,key是數據的時間單位到分鐘,通過小時跟分鐘緩存每個國家匯率的分時數據,當一分鐘有多次推送時,將原有的緩存進行覆蓋,這樣每個國家的匯率每分鐘只會緩存一條數據,然後啟動一個定時任務,每分鐘將最近幾分鐘裡面的數據寫入到Redis裡面,使用Hash結構,key也是分時數據的小時和分鐘
- 應用場景之運動排名實時更新,以輕加APP中活動模塊的排名實現為例,每位用戶參加完運動都會進行計算消耗的卡路里,第一步是入庫,入庫成功然後在保存當前用戶的運動數據到Redis,key為用戶ID+運動方案ID,同時使用Redis的ZADD函數加入到Redis的有序集合中會自動根據value進行排序,如果已經有了就會替換最新,如果想獲取指定區間內的排名,比如前50,則可以用ZRANGE函數獲取,更多的實現請參考http://redisdoc.com。
- 應用場景之分散式session,正常單機的架構不存在session丟失的問題,但是在分散式架構中,session共享就是個問題,因為當你第一次請求時有可能在第一台伺服器,第二次時由於負載均衡策略會跑到其他伺服器執行請求,這樣第一次的請求session就丟失了,如何讓一台伺服器的session在另一台上也能共享?這裡還是用到redis了,當我們登錄時驗證用戶賬號密碼都正確的情況下,通過twitter的snoflke演算法實現分散式ID作為token然後以token為key,用戶信息作為value存儲到redis,同時將token存儲到cookie保存登錄狀態,這樣做的好處是在分散式的環境中伺服器之間的數據需要時間同步,這樣就會有延遲,就有可能導致session不一致,使用redis就能解決不一致的問題。
- 高並發緩存之頁面緩存
- 頁面緩存通常採用模板引擎,比如springboot推薦的freemark,thymeleaf,等等,換句話說也就是做頁面靜態化處理,介面數據通過介面從後端獲取,實現前後端分離靜態頁面無需連接資料庫打開速度會明顯提高, 另外一種是通過手動渲染得到HTML然後緩存到redis,不過常用的實現方式也是最直接的是採用模板引擎
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※類型轉換運算符 運算符重載 operator new operator delete
※編譯過程的五個階段
TAG:程序員小新人學習 |