為什么要使用分布式緩存高并發(fā)環(huán)境下,例如典型的淘寶雙11秒殺,幾分鐘內(nèi)上億的用戶涌入淘寶,這個時候如果訪問不加攔截,讓大量的讀寫請求涌向數(shù)據(jù)庫,由于磁盤的處理速度與內(nèi)存顯然不在一個量級,服務(wù)器馬上就要宕機。從減輕數(shù)據(jù)庫的壓力和提高系統(tǒng)響應(yīng)速度兩個角度來考慮,都會在數(shù)據(jù)庫之前加一層緩存,訪問壓力越大的,在緩存之前就開始CDN攔截圖片等訪問請求。 并且由于最早的單臺機器的內(nèi)存資源以及承載能力有限,如果大量使用本地緩存,也會使相同的數(shù)據(jù)被不同的節(jié)點存儲多份,對內(nèi)存資源造成較大的浪費,因此,才催生出了分布式緩存。
分布式緩存應(yīng)用場景
分布式緩存比較:Memcache VS Redis1、Redis不僅僅支持簡單的k/v類型的數(shù)據(jù),同時還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲。而memcache只支持簡單數(shù)據(jù)類型,需要客戶端自己處理復(fù)雜對象 2、Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤中,重啟的時候可以再次加載進行使用(PS:持久化在rdb、aof)。 3、由于Memcache沒有持久化機制,因此宕機所有緩存數(shù)據(jù)失效。Redis配置為持久化,宕機重啟后,將自動加載宕機時刻的數(shù)據(jù)到緩存系統(tǒng)中。具有更好的災(zāi)備機制。 4、Memcache可以使用Magent在客戶端進行一致性hash做分布式。Redis支持在服務(wù)器端做分布式(PS:Twemproxy/Codis/Redis-cluster多種分布式實現(xiàn)方式) 5、Memcached的簡單限制就是鍵(key)和Value的限制。最大鍵長為250個字符??梢越邮艿膬Υ鏀?shù)據(jù)不能超過1MB(可修改配置文件變大),因為這是典型slab 的最大值,不適合虛擬機使用。而Redis的Key長度支持到512k。 6、Redis使用的是單線程模型,保證了數(shù)據(jù)按順序提交。Memcache需要使用cas保證數(shù)據(jù)一致性。CAS(Check and Set)是一個確保并發(fā)一致性的機制,屬于“樂觀鎖”范疇;原理很簡單:拿版本號,操作,對比版本號,如果一致就操作,不一致就放棄任何操作 cpu利用。由于Redis只使用單核,而Memcached可以使用多核,所以平均每一個核上Redis在存儲小數(shù)據(jù)時比Memcached性能更 高。而在100k以上的數(shù)據(jù)中,Memcached性能要高于Redis 。 7、memcache內(nèi)存管理:使用Slab Allocation。原理相當(dāng)簡單,預(yù)先分配一系列大小固定的組,然后根據(jù)數(shù)據(jù)大小選擇最合適的塊存儲。避免了內(nèi)存碎片。(缺點:不能變長,浪費了一定空間)memcached默認(rèn)情況下下一個slab的最大值為前一個的1.25倍。 8、redis內(nèi)存管理: Redis通過定義一個數(shù)組來記錄所有的內(nèi)存分配情況, Redis采用的是包裝的malloc/free,相較于Memcached的內(nèi)存 管理方法來說,要簡單很多。由于malloc 首先以鏈表的方式搜索已管理的內(nèi)存中可用的空間分配,導(dǎo)致內(nèi)存碎片比較多。 在此我向大家推薦一個Java高級群 :725633148 里面會分享一些資深架構(gòu)師錄制的視頻錄像:(有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化、分布式架構(gòu)、面試資料)等這些成為架構(gòu)師必備的知識體系 進群馬上免費領(lǐng)取,目前受益良多! 分布式緩存選型總結(jié)其實對于企業(yè)選型Memcache、Redis而言,更多還是應(yīng)該看業(yè)務(wù)使用場景(因為Memcache、Redis兩者都具有足夠高的性能和穩(wěn)定性)。假若業(yè)務(wù)場景需要用到持久化緩存功能、或者支持多種數(shù)據(jù)結(jié)構(gòu)的緩存功能,那么Redis則是最佳選擇。 (PS:Redis集群解決方式也優(yōu)于Memcache,Memcache在客戶端一致性hash的集群解決方案,Redis采用無中心的服務(wù)器端集群解決方案) 綜上所述:為了讓緩存系統(tǒng)能夠支持更多的業(yè)務(wù)場景,選擇Redis會更優(yōu)。 分布式緩存的常見問題和挑戰(zhàn)1.緩存雪崩 緩存雪崩我們可以簡單的理解為:由于原有緩存失效,新緩存未到期間(例如:我們設(shè)置緩存時采用了相同的過期時間,在同一時刻出現(xiàn)大面積的緩存過期),所有原本應(yīng)該訪問緩存的請求都去查詢數(shù)據(jù)庫了,而對數(shù)據(jù)庫CPU和內(nèi)存造成巨大壓力,嚴(yán)重的會造成數(shù)據(jù)庫宕機。從而形成一系列連鎖反應(yīng),造成整個系統(tǒng)崩潰。 2.緩存穿透 緩存穿透是指用戶查詢數(shù)據(jù),在數(shù)據(jù)庫沒有,自然在緩存中也不會有。這樣就導(dǎo)致用戶查詢的時候,在緩存中找不到,每次都要去數(shù)據(jù)庫再查詢一遍,然后返回空(相當(dāng)于進行了兩次無用的查詢)。這樣請求就繞過緩存直接查數(shù)據(jù)庫,這也是經(jīng)常提的緩存命中率問題。 3.緩存預(yù)熱 緩存預(yù)熱這個應(yīng)該是一個比較常見的概念,相信很多小伙伴都應(yīng)該可以很容易的理解,緩存預(yù)熱就是系統(tǒng)上線后,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請求的時候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)! 4.緩存更新 除了緩存服務(wù)器自帶的緩存失效策略之外,我們還可以根據(jù)具體的業(yè)務(wù)需求進行自定義的緩存淘汰,常見的策略有兩種: (1)定時去清理過期的緩存; (2)當(dāng)有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存。 兩者各有優(yōu)劣,第一種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較復(fù)雜!具體用哪種方案,大家可以根據(jù)自己的應(yīng)用場景來權(quán)衡。 5.緩存降級 當(dāng)訪問量劇增、服務(wù)出現(xiàn)問題(如響應(yīng)時間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時,仍然需要保證服務(wù)還是可用的,即使是有損服務(wù)。系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進行自動降級,也可以配置開關(guān)實現(xiàn)人工降級。 降級的最終目的是保證核心服務(wù)可用,即使是有損的。而且有些服務(wù)是無法降級的(如加入購物車、結(jié)算)。 在進行降級之前要對系統(tǒng)進行梳理,看看系統(tǒng)是不是可以丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;比如可以參考日志級別設(shè)置預(yù)案: (1)一般:比如有些服務(wù)偶爾因為網(wǎng)絡(luò)抖動或者服務(wù)正在上線而超時,可以自動降級; (2)警告:有些服務(wù)在一段時間內(nèi)成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發(fā)送告警; (3)錯誤:比如可用率低于90%,或者數(shù)據(jù)庫連接池被打爆了,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時可以根據(jù)情況自動降級或者人工降級; (4)嚴(yán)重錯誤:比如因為特殊原因數(shù)據(jù)錯誤了,此時需要緊急人工降級。 |
|