系統的存儲性能,我們可以通過各種手段來提升,但是在些場景下,僅僅提升存儲系統的性能已經遠遠達不到我們的要求了,主要場景有:
需要經過複雜運算後得出的數據,存儲系統無能為力讀多寫少的數據,存儲系統有心無力。
這兩種場景,想必我們在實際業務中也經常遇到,比如說,我要根據某些特定條件還計算用戶的昨日排名,我們如果每次都通過MySQL語句來處理大量數據,那麼無論再怎麼優化MySQL也無濟於事。另外一個,要知道絕大部分的在線業務都是讀多寫少的,例如一個商品詳情頁面,如果每一次訪問,我們都要去數據庫查找一些,即使有索引,也會對MySQL數據庫產生非常大的壓力。
所以,緩存的出現就是為了彌補存儲系統在這些複雜的業務場景下遇到的瓶頸,而緩存的基本原理是將可能重複使用的數據放到內存中,一次生成、多次使用,避免每次使用直接去請求存儲系統。
緩存可以給性能帶來大幅度的提升,拿Memcache來說,單臺Memcache服務器簡單的key-Value查詢可以達到 TPS 50000以上,其架構如下:
有利就有弊,緩存雖然大大的減輕了存儲系統的壓力,但同時也會給架構帶來更多的複雜性。而我們則需要針對這些複雜性做出相應的處理,否則,在某些場景下會導致系統直接崩潰。
緩存穿透
什麼是緩存穿透?它是指緩存沒有發揮作用,業務系統雖然去緩存系統查詢數據,但緩存中沒有相應數據,業務系統需要再次去存儲系統查詢數據。
通常存在兩種情況:
1、 存儲數據確實不存在
這種情況是緩存數據確實不存在。在我們實際應用場景中,如果沒有查找某個數據,則不會在緩存中存儲相應的數據,這樣就會導致在查詢時未找到相應數據,每次都去存儲系統中再查詢一遍,然後再返回數據不存在。所以,在這種情況下,緩存並沒有起到分擔存儲訪問壓力的作用。
在正常情況下,業務上讀取不存在的數據的請求量並不會很大,但是如果有黑客攻擊,故意大量訪問某些讀取不存在數據的業務,還是有可能把存儲系統拖垮。所以,我們在實際業務場景中,還需要注意到這方面的問題。至於解決方法,也比較簡單,就是如果沒有查找到數據,則直接設置一個默認值存在緩存中即可了。
2、緩存數據生成耗費大量時間或資源
這種情況是存儲系統中存在數據,但生成緩存數據需要耗費較長的時間或者消耗大量資源,而如果用戶在訪問時,剛好遇到緩存失效,這時候,訪問壓力會集中在存儲系統上,緩存就不會發揮作用了。
緩存雪崩
緩存雪崩是指當緩存失效或過期後引起系統性能急劇下降的情況。對於高併發的業務系統來說,當緩存失效後,系統需要重新生成緩存,在這期間,可能會接到成百上千的請求,而這些請求都會去請求存儲系統,生成新的緩存,從而造成存儲系統產生很大的性能壓力,更嚴重的情況下,導致數據庫瞬時壓力過重雪崩。
緩存雪崩常見的解決方法有兩種:更新鎖機制和後臺更新機制。
一、更新鎖機制
對緩存更新操作進行加鎖保護,保證只有一個線程能夠進行緩存更新,其他的線程要麼等待鎖釋放後重新讀取緩存,要麼就返回空值或者默認值。
而對於 採用分佈式集群的業務,由於服務器過多,即使單臺一個線程來更新緩存,幾十上百臺服務器一起更新也有幾個線程,同樣會引起雪崩的問題,因此這情況需要用到分佈式鎖,如Zookeeper。
二、後臺更新機制
後臺更新,意味著,不再由業務來驅動更新了,而是由後臺來更新緩存,這種緩存的有效期為永久有效。後臺更新無論是單機多線程還是分佈式集群的場景都比較適合,而且相對於更新鎖機制要簡單一些。
後臺更新機制也比較適合剛上線的時候進行緩存預熱,將相關的緩存數據直接加載到緩存系統,而不是等到用戶訪問才來觸發緩存加載。
緩存熱點
緩存系統本身性能比較高,但對於一些熱點的數據來說,如果大量業務請求命中同一份緩存數據,那麼緩存服務器的壓力也會很大。
緩存熱點的解決方案就是複製多份緩存副本,將請求分散到多個緩存服務器上,減輕緩存熱點導致的單臺緩存服務器的壓力。但這裡需要注意的是,不能將所有的緩存副本設置統一的過期時間,否則在同時失效到生成緩存的期間,可能 會引發雪崩效應。
緩存是實現業務場景中是經常遇到的,對於高併發業務來說,更為重要,但是需要明白的是,對於緩存根據實際情況來運用,雖然緩存帶來了性能的可觀提升,如果我們隨意應用,維護也是一種成本 ,反而提升了系統的複雜性。
聲明:本系列學習內容來自於《從零開始學架構》。另,圖片源於網絡,若有侵權,請及時聯繫刪除。
閱讀更多 格雷文於 的文章