緩存的優缺點

轉:https://www.cnblogs.com/bethunebtj/p/9159914.htmlhtml

1.爲什麼須要緩存?

在高併發請求時,爲什麼咱們頻繁提到緩存技術?最直接的緣由是,目前磁盤IO和網絡IO相對於內存IO的成百上千倍的性能劣勢。
作個簡單計算,若是咱們須要某個數據,該數據從數據庫磁盤讀出來須要0.1s,從交換機傳過來須要0.05s,那麼每一個請求完成最少0.15s(固然,事實上磁盤和網絡IO也沒有這麼慢,這裏只是舉例),該數據庫服務器每秒只能響應67個請求;而若是該數據存在於本機內存裏,讀出來只須要10us,那麼每秒鐘可以響應100,000個請求。web

經過將高頻使用的數據存在離cpu更近的位置,以減小數據傳輸時間,從而提升處理效率,這就是緩存的意義。redis

2.在哪裏用緩存?

一切地方。例如:數據庫

  • 咱們從硬盤讀數據的時候,其實操做系統還額外把附近的數據都讀到了內存裏
  • 例如,CPU在從內存裏讀數據的時候,也額外讀了許多數據到各級cache裏
  • 各個輸入輸出之間用buffer保存一批數據統一發送和接受,而不是一個byte一個byte的處理

上面這是系統層面,在軟件系統設計層面,不少地方也用了緩存:瀏覽器

  • 瀏覽器會緩存頁面的元素,這樣在重複訪問網頁時,就避開了要從互聯網上下載數據(例如大圖片)
  • web服務會把靜態的東西提早部署在CDN上,這也是一種緩存
  • 數據庫會緩存查詢,因此同一條查詢第二次就是要比第一次快
  • 內存數據庫(如redis)選擇把大量數據存在內存而非硬盤裏,這能夠看做是一個大型緩存,只是把整個數據庫緩存了起來
  • 應用程序把最近幾回計算的結果放在本地內存裏,若是下次到來的請求仍是原請求,就跳過計算直接返回結果

3.緩存的那些坑

緩存頗有用,可是緩存用很差也會埋不少坑:緩存

緩存穿透

緩存穿透是說收到了一個請求,可是該請求緩存裏沒有,只能去數據庫裏查詢,而後放進緩存。這裏面有兩個風險,一個是同時有好多請求訪問同一個數據,而後業務系統把這些請求全發到了數據庫;第二個是有人惡意構造一個邏輯上不存在的數據,而後大量發送這個請求,這樣每次請求都會被髮送到數據庫,可能致使數據掛掉。服務器

怎麼應對這種狀況呢?對於惡意訪問,一個思路是事先作校驗,對惡意數據直接過濾掉,不要發到數據庫層;第二個思路是緩存空結果,就是對查詢不存在的數據仍然記錄一條該數據不存在在緩存裏,這樣能有效的減小查詢數據庫的次數。網絡

那麼非惡意訪問呢?這個要結合緩存擊穿來說。併發

緩存擊穿

上面提到的某個數據沒有,而後好多請求都被髮到數據庫其實能夠歸爲緩存擊穿的範疇:對於熱點數據,當數據失效的一瞬間,全部請求都被下放到數據庫去請求更新緩存,數據庫被壓垮。分佈式

怎麼防範這種問題呢?一個思路是全局鎖,就是全部訪問某個數據的請求都共享一個鎖,得到鎖的那個纔有資格去訪問數據庫,其餘線程必須等待。可是如今的業務都是分佈式的,本地鎖無法控制其餘服務器也等待,因此要用到全局鎖,好比用redis的setnx實現全局鎖。

另外一個思路是對即將過時的數據主動刷新,作法能夠有不少,好比起一個線程輪詢數據,好比把全部數據劃分爲不一樣的緩存區間,按期分區間刷新數據等等。這第二個思路又和咱們接下來要講的緩存雪崩有關係。

緩存雪崩

緩存雪崩是指好比咱們給全部的數據設置了一樣的過時時間,而後在某一個歷史性時刻,整個緩存的數據所有過時了,而後瞬間全部的請求都被打到了數據庫,數據庫就崩了。

解決思路要麼是分治,劃分更小的緩存區間,按區間過時;要麼是給每一個key的過時時間加個隨機值,避免同時過時,達到錯峯刷新緩存的目的。

緩存刷新

說到刷新緩存,其實也有坑的。好比我以前的一份工做裏,有一次大活動,正是如火如荼的時候,全部的廣告位忽然都變空白了。後來追查緣由,全部的廣告素材都在緩存裏,而後起了個程序,專門負責刷新緩存,每次把當前的素材全量刷新。

壞就壞在這個全量上。由於大活動的時候流量極大,廣告更新壓力也很大,把負責提供更新素材的程序壓崩了。刷新緩存的程序在請求時,收到了一個返回結果Null。接下來就喜聞樂見了,刷新程序根據這個null,清空了整個緩存,全部廣告素材都失效了。

總之,想要作好高併發系統的緩存,就要考慮到各類邊角狀況,當心設計,任何細小的疏忽均可能致使系統崩潰。

相關文章
相關標籤/搜索