阿里P8架構師談:分布式緩存的應用場景、選型比較、問題和挑戰
為什么要使用分布式緩存
高并發環境下,例如典型的淘寶雙11秒殺,幾分鐘內上億的用戶涌入淘寶,這個時候如果訪問不加攔截,讓大量的讀寫請求涌向數據庫,由于磁盤的處理速度與內存顯然不在一個量級,服務器馬上就要宕機。從減輕數據庫的壓力和提高系統響應速度兩個角度來考慮,都會在數據庫之前加一層緩存,訪問壓力越大的,在緩存之前就開始CDN攔截圖片等訪問請求。
并且由于最早的單臺機器的內存資源以及承載能力有限,如果大量使用本地緩存,也會使相同的數據被不同的節點存儲多份,對內存資源造成較大的浪費,因此,才催生出了分布式緩存。

分布式緩存應用場景
- 頁面緩存.用來緩存Web 頁面的內容片段,包括HTML、CSS 和圖片等;
- 應用對象緩存.緩存系統作為ORM 框架的二級緩存對外提供服務,目的是減輕數據庫的負載壓力,加速應用訪問;
- 解決分布式Web部署的session同步問題,狀態緩存.緩存包括Session 會話狀態及應用橫向擴展時的狀態數據等,這類數據一般是難以恢復的,對可用性要求較高,多應用于高可用集群。
- 并行處理.通常涉及大量中間計算結果需要共享;
- 云計算領域提供分布式緩存服務。
分布式緩存比較:Memcache VS Redis
1、Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。而memcache只支持簡單數據類型,需要客戶端自己處理復雜對象
2、Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啟的時候可以再次加載進行使用(PS:持久化在rdb、aof)。
3、由于Memcache沒有持久化機制,因此宕機所有緩存數據失效。Redis配置為持久化,宕機重啟后,將自動加載宕機時刻的數據到緩存系統中。具有更好的災備機制。
4、Memcache可以使用Magent在客戶端進行一致性hash做分布式。Redis支持在服務器端做分布式(PS:Twemproxy/Codis/Redis-cluster多種分布式實現方式)
5、Memcached的簡單限制就是鍵(key)和Value的限制。***鍵長為250個字符。可以接受的儲存數據不能超過1MB(可修改配置文件變大),因為這是典型slab 的***值,不適合虛擬機使用。而Redis的Key長度支持到512k。
6、Redis使用的是單線程模型,保證了數據按順序提交。Memcache需要使用cas保證數據一致性。CAS(Check and Set)是一個確保并發一致性的機制,屬于“樂觀鎖”范疇;原理很簡單:拿版本號,操作,對比版本號,如果一致就操作,不一致就放棄任何操作
cpu利用。由于Redis只使用單核,而Memcached可以使用多核,所以平均每一個核上Redis在存儲小數據時比Memcached性能更 高。而在100k以上的數據中,Memcached性能要高于Redis 。
7、memcache內存管理:使用Slab Allocation。原理相當簡單,預先分配一系列大小固定的組,然后根據數據大小選擇最合適的塊存儲。避免了內存碎片。(缺點:不能變長,浪費了一定空間)memcached默認情況下下一個slab的***值為前一個的1.25倍。
8、redis內存管理: Redis通過定義一個數組來記錄所有的內存分配情況, Redis采用的是包裝的malloc/free,相較于Memcached的內存 管理方法來說,要簡單很多。由于malloc 首先以鏈表的方式搜索已管理的內存中可用的空間分配,導致內存碎片比較多。
分布式緩存選型總結
其實對于企業選型Memcache、Redis而言,更多還是應該看業務使用場景(因為Memcache、Redis兩者都具有足夠高的性能和穩定性)。假若業務場景需要用到持久化緩存功能、或者支持多種數據結構的緩存功能,那么Redis則是***選擇。
(PS:Redis集群解決方式也優于Memcache,Memcache在客戶端一致性hash的集群解決方案,Redis采用無中心的服務器端集群解決方案)
綜上所述:為了讓緩存系統能夠支持更多的業務場景,選擇Redis會更優。
分布式緩存的常見問題和挑戰
1.緩存雪崩
緩存雪崩我們可以簡單的理解為:由于原有緩存失效,新緩存未到期間(例如:我們設置緩存時采用了相同的過期時間,在同一時刻出現大面積的緩存過期),所有原本應該訪問緩存的請求都去查詢數據庫了,而對數據庫CPU和內存造成巨大壓力,嚴重的會造成數據庫宕機。從而形成一系列連鎖反應,造成整個系統崩潰。
2.緩存穿透
緩存穿透是指用戶查詢數據,在數據庫沒有,自然在緩存中也不會有。這樣就導致用戶查詢的時候,在緩存中找不到,每次都要去數據庫再查詢一遍,然后返回空(相當于進行了兩次無用的查詢)。這樣請求就繞過緩存直接查數據庫,這也是經常提的緩存***率問題。
3.緩存預熱
緩存預熱這個應該是一個比較常見的概念,相信很多小伙伴都應該可以很容易的理解,緩存預熱就是系統上線后,將相關的緩存數據直接加載到緩存系統。這樣就可以避免在用戶請求的時候,先查詢數據庫,然后再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!
4.緩存更新
除了緩存服務器自帶的緩存失效策略之外,我們還可以根據具體的業務需求進行自定義的緩存淘汰,常見的策略有兩種:
(1)定時去清理過期的緩存;
(2)當有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統得到新數據并更新緩存。
兩者各有優劣,***種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較復雜!具體用哪種方案,大家可以根據自己的應用場景來權衡。
5.緩存降級
當訪問量劇增、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統可以根據一些關鍵數據進行自動降級,也可以配置開關實現人工降級。
降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的(如加入購物車、結算)。
在進行降級之前要對系統進行梳理,看看系統是不是可以丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;比如可以參考日志級別設置預案:
(1)一般:比如有些服務偶爾因為網絡抖動或者服務正在上線而超時,可以自動降級;
(2)警告:有些服務在一段時間內成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發送告警;
(3)錯誤:比如可用率低于90%,或者數據庫連接池被打爆了,或者訪問量突然猛增到系統能承受的***閥值,此時可以根據情況自動降級或者人工降級;
(4)嚴重錯誤:比如因為特殊原因數據錯誤了,此時需要緊急人工降級。




























