緩存面試-基礎知識大補

緩存面試

在面試中佔很大比例,我們要從緩存組件的訪問協議、Client 入手,掌握如何訪問各種緩存組件,如 Memcached、Redis、Pika 等 ;儘可能深入理解緩存組件的實現方案、設計原理,緩存的各種特性,如何快速定位緩存數據與預期不一致問題 ;儘可能知曉大中型系統是如何對緩存進行架構設計。

應用端緩存

應用端緩存也就是代碼層面,需要通過寫代碼方式來進行分佈式緩存的寫入和讀取,主要涉及:

  • 寫緩存時,我們需要將數據分散到緩存的各個節點中,即要實現數據分片。
  • 讀緩存時,需考慮主從或者多副本粗略以及使用多組緩存進行容錯。

緩存數據分片及分片算法

需要將數據進行分片存儲,即將數據通過分片算法打散到各個緩存節點中,類似於分庫分表思想。

  • Hash分片算法

Hash分片算法就是我們拿到緩存的key,然後對其做hash運算,最後將hash運算的結果對緩存總節點數取餘,得到的數字則為具體的分片節點。

  • 一致性Hash分片算法-2^32的hash環。
  1. 然後將各個緩存節點的IP或者機器名稱計算hash值,是每個節點計算多個hash出來,也就是所謂的虛擬節點。為了數據能更加的均勻,且能避免節點雪崩的發生。
  2. 將計算出來的hash值即虛擬節點放到hash環上。
  3. 當我們要寫入一個key的時候,就可以先對這個key做hash計算出hash值,,確定在hash環上的位置。
  4. 最後在環上按照順時針的方式查找,遇到的第一個緩存節點就是它要存放的節點。

系統自行管理的緩存

redis的sentinel模式就是用來解決redis部署時高可用問題,它可以在主節點掛了以後自動將從節點提升為主節點,保證整體集群的可用。所以服務端對於我們開發影響不是太大。

緩存系統設計注意事項

涉及:緩存雪崩、緩存穿透、緩存擊穿

(1)緩存雪崩

在高併發系統,如果緩存系統故障,大量的請求無法從緩存完成數據請求,因此就全量洶湧衝向磁盤數據庫系統,導致數據庫被打死,整個系統徹底崩潰。

緩存雪崩解決方案

  • 從原因來看主要是緩存系統不夠高可用,因此提高緩存系統的穩定性和可用性十分必要,對於使用Redis作為緩存的系統而言需要使用Sentinel哨兵機制、集群化、持久化等來提高緩存系統的HA。
  • 另一方面除了保證緩存系統的HA之外,服務本身也需要支持降級,可以使用奈飛的Hystrix來實現服務的熔斷、降級、限流來降低出現雪崩時的故障程度。
  • 說白了就是別讓服務徹底死掉就行,就像大雪封高速肯定徹底不能通行了,堵車就是慢一些至少可以走,如果還不清楚,回想一下每年你回鄉的車票是怎麼從12306搶回來的。

(2)緩存穿透

在高併發系統中緩存穿透,其實是這樣的如果一個req需要請求的key在緩存中沒有,這時業務線程就會訪問磁盤數據庫系統,然而磁盤數據庫也沒有這個key,無奈業務線程只能返回null,白白處理一圈。

小概率事件在高併發系統幾乎要成為必然,也就是如果某時段有大量惡意的不存在的key的爆破請求,那麼服務將一直處理這些根本不存在的請求,導致正常請求無法被處理,從而出現問題。

緩存穿透解決方案

高併發系統也是如此,有效甄別是否存在這個key再決定是否讀取很重要,常見的做法有

  • 把不存在的key寫一下null,這樣再來就相當於命中了,其實這種方法侷限性很大。
  • 類似於在海量數據中查找某個key是否存在,考慮空間複雜度和時間複雜度,一般選用布隆過濾器來實現。
<code>布隆過濾器是個好東西,有非常多的用途,包括:垃圾郵件識別、搜索蜘蛛爬蟲url去重等,
主要藉助K個哈希函數和一個超大的bit數組來降低哈希衝突本身帶來的誤判,從而提高識別準確性。
布隆過濾器也存在一定的誤判,假如判斷存在可能不一定存在,但是假如判斷不存在就一定不存在,

因此剛好用在解決緩存穿透的key查找場景,事實上很多系統都是基於布隆過濾器來解決緩存穿透問題的。/<code>


(3)緩存擊穿

緩存擊穿是這樣一種情況:由於緩存系統中的熱點數據都有過期時間,如果沒有過期時間就造成了主存和緩存的數據不一致,因此過期時間一般都不會太長,設想某時刻一批熱點數據同時在緩存系統中過期失效,那麼這部分數據就都將請求磁盤數據庫系統。

緩存擊穿解決方案


  • 在設置熱點數據過期時間時儘量分散,比如設置100ms的基礎值,在此基礎上正負浮動10ms,從而降低相同時刻出現CacheMiss的key的數量。
  • 另外一種做法是多線程加鎖,其中第一個線程發現CacheMiss之後進行加鎖,再從數據庫獲取內容之後寫到緩存中,其他線程獲取鎖失敗則阻塞數ms之後再進行緩存讀取,這樣可以降低訪問數據數據庫的線程數,需要注意在單機和集群需要使用不同的鎖,集群環境使用分佈式鎖來實現,但是由於鎖的存在也會影響併發效率。
  • 還有一種辦法是使用類似於Redis的SETNX命令,這種貌似存在問題
  • 最後一種方法是在業務層對使用的熱點數據查看是否即將過期,如果即將過期則去數據庫獲取最新數據進行更新並延長該熱點key在緩存系統中的時間,從而避免後面的過期CacheMiss,相當於把事情提前解決了。

緩存擊穿的解決方法都有一定的權衡,實際中根據自己的需求來解決。


分享到:


相關文章: