oracle缓存和Redis,说说数据缓存那点事:Redis和memcached对比
【此為"一森咖記"公眾號——第86篇文章】
本文預計閱讀15分鐘
【引言】
當我們?yōu)橐粋€并發(fā)量較大的應用做數(shù)據(jù)架構時,會考慮使用緩存,意欲達到三個目標:
1. 加快用戶訪問速度,提高業(yè)務用戶體驗;
2. 降低后端服務負載,保證系統(tǒng)平滑平穩(wěn);
3. 保證數(shù)據(jù)盡可能及時更新,最大程度保證數(shù)據(jù)一致性。
之前的兩篇文章分別介紹了數(shù)據(jù)緩存層常用的兩個產(chǎn)品redis和memcached,點擊如下兩篇文章:
今天對比分析下Redis和memcached。
【大綱】
1. Redis和memcached的區(qū)別
2. redis相比memcache的優(yōu)勢
3. redis常見性能問題和解決方案
4. 緩存使用時的常見現(xiàn)象
一、 Redis和memcached的區(qū)別
1. 數(shù)據(jù)類型
memcached所有的值均是簡單的字符串,redis支持豐富數(shù)據(jù)類型,支持string,list,set,sorted set,hash;
2.?線程機制
Redis為單線程,Memcached為多線程工作,每一個核上Redis在存儲小數(shù)據(jù)時比Memcached性能更高。而在100k以上的數(shù)據(jù)時,Memcached性能要高于Redis;
3. 存儲方式
redis和Memcached均是內(nèi)存數(shù)據(jù)庫,但redis可以數(shù)據(jù)持久化,Memcached不支持持久化。Redis并非所有的數(shù)據(jù)一直在內(nèi)存,當物理內(nèi)存用完時,Redis使用LRU算法將value交換到磁盤,memcached超過內(nèi)存比例會抹掉前面的數(shù)據(jù)。故,memcached斷電,重啟系統(tǒng)后,數(shù)據(jù)不可恢復;redis數(shù)據(jù)丟失后可以通過RDB和AOF恢復。
4. 分布式存儲
Memcached和Redis是基于服務器物理內(nèi)存級的數(shù)據(jù)緩存,如需要處理的數(shù)據(jù)量超過單臺機器的物理內(nèi)存,就需構建分布式集群來擴展存儲能力。
Memcached本身并不支持分布式,只能在客戶端通過像一致性哈希這樣的分布式算法
來實現(xiàn)Memcached的分布式存儲,為客戶端式分布式緩存;Redis更偏向于服務器端構建分布式緩存,沒有采用一致性哈希做分布式。在Redis Cluster中,每個Master節(jié)點都有對應的兩個冗余Slave節(jié)點。當Master節(jié)點退出后,集群會自動選擇一個Slave節(jié)點成為新的Master節(jié)點。熟悉MySQL高可用架構MHA部署的親,可以更容易理解。
5.?底層模型不同
Redis自己構建VM機制 ,而系統(tǒng)調(diào)用系統(tǒng)函數(shù)會浪費一定的時間去移動和請求。
6. value大小
redis最大可以達到1GB,而memcache只有1MB
小結:
1. redis支持master-slave復制模式;memcache可以使用一致性hash做分布式。
2. 如有持久化方面的需求或者對數(shù)據(jù)類型和處理有要求,應選擇redis;
3. 如果是簡單的key/value存儲可以考慮memcached;
4. 內(nèi)存管理機制,Memcached主要的cache機制是LRU算法+超時失效。Redis采用的是包裝的mallc/free,相較于Memcached的內(nèi)存管理方法來說,要簡單很多。
二、 redis相比memcache的優(yōu)勢
1、 memcached所有的值均是簡單的字符串,redis作為其替代者,支持更為豐富的數(shù)據(jù)類型;
2、redis的速度比memcached快很多;
3、redis可以持久化其數(shù)據(jù)。
市面上,目前使用redis較多,但須知redis有哪些性能問題。
三、?redis常見性能問題和解決方案
1.Master最好不要做任何持久化工作(RDB內(nèi)存快照和AOF日志文件)
原因: 1) 如Master寫RDB內(nèi)存快照,save命令調(diào)度rdbSave函數(shù),會阻塞主線程的工作,當快照比較大時對性能影響是非常大的,會間斷性暫停服務,所以Master最好不要寫RDB內(nèi)存快照。2) Master調(diào)用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內(nèi)存資源,導致服務load過高,出現(xiàn)短暫服務暫停現(xiàn)象。
如RDB內(nèi)存快照和AOF日志文件;
2.如果數(shù)據(jù)比較重要,Slave開啟AOF備份數(shù)據(jù),策略設置最好為每秒同步一次;
3.為了主從復制的速度和連接的穩(wěn)定性,Master和Slave最好在同一個局域網(wǎng);
4.避免在壓力很大的主庫上增加從庫;
5.主從復制不要用圖狀結構,用串行鏈表結構,可方便解決單點故障問題,實現(xiàn)Slave對Master的替換。如果Master宕機,可立刻啟用Slave1做Master。
四、?緩存使用時的常見現(xiàn)象
使用數(shù)據(jù)緩存會發(fā)生幾種現(xiàn)象和解決方法:緩存雪崩、緩存擊穿、緩存擊穿、緩存預熱。
4.1緩存穿透
緩存穿透是指查詢一個一定不存在的數(shù)據(jù),由于緩存是不命中時需要從數(shù)據(jù)庫查詢,查不到數(shù)據(jù)則不寫入緩存,這將導致這個不存在的數(shù)據(jù)每次請求都要到數(shù)據(jù)庫去查詢,造成緩存穿透,也是經(jīng)常提的緩存命中率問題。
解決辦法
1. 采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被這個bitmap攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力。
2. 如果查詢數(shù)據(jù)庫也為空,直接設置一個默認值存放到緩存,這樣第二次到緩沖中獲取就有值了,而不會繼續(xù)訪問數(shù)據(jù)庫,但它的過期時間會很短,最長不超過五分鐘。這種辦法最簡單粗暴。
4.2緩存雪崩
緩存雪崩,是指在某一個時間段,緩存集中過期失效。
由于原有緩存失效(過期),新緩存未到期間。所有請求都去查詢數(shù)據(jù)庫,而對數(shù)據(jù)庫CPU和內(nèi)存造成巨大壓力,嚴重的會造成數(shù)據(jù)庫宕機。從而形成一系列連鎖反應,造成整個系統(tǒng)崩潰。
某個時期緩存集中過期時自然形成的緩存雪崩,一定是在某個時間段集中創(chuàng)建緩存,數(shù)據(jù)庫如能頂住壓力,緩存的定期創(chuàng)建無非就是對數(shù)據(jù)庫產(chǎn)生周期性壓力;比較可怕的是而緩存服務節(jié)點宕機,對數(shù)據(jù)庫服務器造成的壓力是不可預知,很可能瞬間把數(shù)據(jù)庫壓垮。
解決辦法
1)在緩存失效后,通過加鎖或者隊列來控制讀數(shù)據(jù)庫寫緩存的線程數(shù)量。如對某個key只允許一個線程查詢數(shù)據(jù)和寫緩存,其他線程等待。此方法只允許一個線程重建緩存,其他線程等待重建緩存的線程執(zhí)行完;加鎖排隊只是為了減輕數(shù)據(jù)庫的壓力,并沒有提高系統(tǒng)吞吐量。假設在高并發(fā)下,緩存重建期間key是鎖著的,過來100個請求99個都在阻塞。同樣會導致用戶等待超時,此方法治標不治本。
2)可以通過緩存reload機制,預先去更新緩存,再即將發(fā)生大并發(fā)訪問前手動觸發(fā)加載緩存;
3)設置不同的key的過期時間,讓緩存失效時間點盡量均勻. 如可以在原有的失效時間上增加一個隨機值,如1-5分鐘隨機。緩存的過期時間的重復率就會降低,避免引發(fā)集體失效的事件;
4)做二級緩存,或者雙緩存策略。A1為原始緩存,A2為拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置為短期,A2設置為長期;此方法等同于方法3。
4.3緩存擊穿
緩存擊穿,是指一個key非常熱點,,大并發(fā)集中對這一個點進行訪問,當這個key在失效的瞬間,持續(xù)的大并發(fā)就穿破緩存,直接請求數(shù)據(jù)庫,就像在一個屏障上鑿開了一個洞,引起數(shù)據(jù)庫壓力瞬間增大,造成過大壓力。
緩存擊穿和緩存雪崩的區(qū)別在于這里針對某一key緩存,前者則是很多key。
解決辦法:
1)設置熱點數(shù)據(jù)永遠不過期,這種方案由于沒有設置真正的過期時間,實際上已經(jīng)不存在熱點 key 產(chǎn)生的一系列危害,但會存在數(shù)據(jù)不一致,代碼復雜度會增大。
加互斥鎖,此方案思路簡單,但存在一定隱患,如構建緩存過程出現(xiàn)問題或者時間較長,可能會存在死鎖和線程池阻塞的風險;這種方法最大的優(yōu)點是能較好的降低后端存儲負載并在一致性上做的較好。
緩存預熱
緩存預熱就是系統(tǒng)上線后,提前將相關的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。避免在用戶請求的時候,先查詢數(shù)據(jù)庫,再將數(shù)據(jù)緩存的問題。用戶直接查詢事先被預熱的緩存數(shù)據(jù)。
解決方法:
1)直接寫個緩存刷新頁面,上線時手工操作下。
2)數(shù)據(jù)量不大,可以在應用啟動時提前加載常用的熱點數(shù)據(jù)。
3)定時刷新緩存
4.4緩存更新
通過expire來設置key的過期時間,Redis的6種數(shù)據(jù)淘汰策略:
1)noeviction:返回錯誤當內(nèi)存限制達到并且客戶端嘗試執(zhí)行會讓更多內(nèi)存被使用的命令(大部分的寫入指令,但DEL和幾個例外)
2)allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新添加的數(shù)據(jù)有空間存放。
3)volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限于在過期集合的鍵,使得新添加的數(shù)據(jù)有空間存放。
4)allkeys-random: 回收隨機的鍵使得新添加的數(shù)據(jù)有空間存放。
5)volatile-random: 回收隨機的鍵使得新添加的數(shù)據(jù)有空間存放,但僅限于在過期集合的鍵。
6)volatile-ttl: 回收在過期集合的鍵,并且優(yōu)先回收存活時間(TTL)較短的鍵,使得新添加的數(shù)據(jù)有空間存放。
除了上述緩存失效策略外,還可以根據(jù)具體的業(yè)務需求進行自定義的緩存淘汰,常見的策略有兩種:
1)定時去清理過期的緩存;
2)當用戶請求過來時,再行判斷此請求所用緩存是否過期,過期的話就去庫取新數(shù)并更新緩存。
方法1優(yōu)點簡單,缺點是維護大量緩存的key是繁瑣;
方法2缺點是每次用戶請求均要判斷緩存是否失效,邏輯相對復雜;
上述兩種客戶化方法業(yè)務可根據(jù)具體業(yè)務場景來權衡使用。
4.5緩存降級
當訪問量劇增、響應時間慢或不響應、非核心服務影響到核心流程的性能時,為保證核心業(yè)務服務可用,可對某些數(shù)據(jù)服務自動降級或人工降級。如電商系統(tǒng)無法降級的服務有加入購物車、訂單結算;可降級的服務有某些商品的訪問瀏覽。
【總結】
1.?如下兩篇推文分別講述了redis和memcached的兩種緩存;
2. 今天文章內(nèi)容主要介紹了兩者的區(qū)別,并介紹了使用數(shù)據(jù)緩存時常見的緩存擊穿、緩存穿透、緩存雪崩5種常見現(xiàn)象和處理方式;
3. 后續(xù)將持續(xù)進行試驗進行論證。
To be continued.
【參考】
https://blog.csdn.net/m0_37501154/article/details/89916036
【參考】
https://www.cnblogs.com/lijiasnong/p/9963853.html
【參考】
https://blog.csdn.net/qq_36071795/article/details/83988177
以下為個人公眾號“一森咖記”,歡迎關注。
總結
以上是生活随笔為你收集整理的oracle缓存和Redis,说说数据缓存那点事:Redis和memcached对比的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。