轉自: https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961272&idx=1&sn=79ad515b013b0ffc33324db86ba0f834&chksm=bd2d02648a5a8b728db094312f55574ec521b30e3de8aacf1d2d948a3ac24dbf30e835089fa7&scene=21#wechat_redirect
mysql
memcache和redis是互聯網分層架構中,最經常使用的KV緩存。很多同窗在選型的時候會糾結,究竟是選擇memcache仍是redis。面試
畫外音:不鼓勵粗暴的實踐,例如「memcache提供的功能是redis提供的功能的子集,不用想太多,選redis準沒錯」。redis
雖然redis比memcache更晚出來,且功能確實也更豐富,但對於一個技術人,瞭解「因此然」恐怕比「選擇誰」更重要一些。sql
何時傾向於選擇redis?數據庫
業務需求決定技術選型,當業務有這樣一些特色的時候,選擇redis會更加適合。緩存
複雜數據結構網絡
value是哈希,列表,集合,有序集合這類複雜的數據結構時,會選擇redis,由於mc沒法知足這些需求。數據結構
最典型的場景,用戶訂單列表,用戶消息,帖子評論列表等。多線程
持久化架構
mc沒法知足持久化的需求,只得選擇redis。
可是,這裏要提醒的是,真的使用對了redis的持久化功能麼?
千萬不要把redis看成數據庫用:
(1)redis的按期快照不能保證數據不丟失
(2)redis的AOF會下降效率,而且不能支持太大的數據量
不要指望redis作固化存儲會比mysql作得好,不一樣的工具作各自擅長的事情,把redis看成數據庫用,這樣的設計八成是錯誤的。
緩存場景,開啓固化功能,有什麼利弊?
若是隻是緩存場景,數據存放在數據庫,緩存在redis,此時若是開啓固化功能:
優勢是,redis掛了再重啓,內存裏可以快速恢復熱數據,不會瞬時將壓力壓到數據庫上,沒有一個cache預熱的過程。
缺點是,在redis掛了的過程當中,若是數據庫中有數據的修改,可能致使redis重啓後,數據庫與redis的數據不一致。
所以,只讀場景,或者容許一些不一致的業務場景,能夠嘗試開啓redis的固化功能。
自然高可用
redis自然支持集羣功能,能夠實現主動複製,讀寫分離。
redis官方也提供了sentinel集羣管理工具,可以實現主從服務監控,故障自動轉移,這一切,對於客戶端都是透明的,無需程序改動,也無需人工介入。
而memcache,要想要實現高可用,須要進行二次開發,例如客戶端的雙讀雙寫,或者服務端的集羣同步。
可是,這裏要提醒的是,大部分業務場景,緩存真的須要高可用麼?
(1)緩存場景,不少時候,是容許cache miss
(2)緩存掛了,不少時候能夠經過DB讀取數據
因此,須要認真剖析業務場景,高可用,是否真的是對緩存的主要需求?
畫外音:即時通信業務中,用戶的在線狀態,就有高可用需求。
存儲的內容比較大
memcache的value存儲,最大爲1M,若是存儲的value很大,只能使用redis。
何時傾向於memcache?
純KV,數據量很是大,併發量很是大的業務,使用memcache或許更適合。
這要從mc與redis的底層實現機制差別提及。
內存分配
memcache使用預分配內存池的方式管理內存,可以省去內存分配時間。
redis則是臨時申請空間,可能致使碎片。
從這一點上,mc會更快一些。
虛擬內存使用
memcache把全部的數據存儲在物理內存裏。
redis有本身的VM機制,理論上可以存儲比物理內存更多的數據,當數據超量時,會引起swap,把冷數據刷到磁盤上。
從這一點上,數據量大時,mc會更快一些。
網絡模型
memcache使用非阻塞IO複用模型,redis也是使用非阻塞IO複用模型。
但因爲redis還提供一些非KV存儲以外的排序,聚合功能,在執行這些功能時,複雜的CPU計算,會阻塞整個IO調度。
從這一點上,因爲redis提供的功能較多,mc會更快一些。
線程模型
memcache使用多線程,主線程監聽,worker子線程接受請求,執行讀寫,這個過程當中,可能存在鎖衝突。
redis使用單線程,雖無鎖衝突,但難以利用多核的特性提高總體吞吐量。
從這一點上,mc會快一些。
最後說兩點
代碼可讀性,代碼質量
看過mc和redis的代碼,從可讀性上說,redis是我見過代碼最清爽的軟件,甚至沒有之一,或許簡單是redis設計的初衷,編譯redis甚至不須要configure,不須要依賴第三方庫,一個make就搞定了。
而memcache,多是考慮了太多的擴展性,多系統的兼容性,代碼不清爽,看起來費勁。
例如網絡IO的部分,redis源碼1-2個文件就搞定了,mc使用了libevent,一個fd傳過來傳過去,又pipe又線程傳遞的,特別容易把人繞暈。
畫外音:理論上,mc只支持kv,而redis支持了這麼多功能,mc性能應該高很是多很是多,但實際並不是如此,真的可能和代碼質量有關。
水平擴展的支持
不論是mc和redis,服務端集羣沒有自然支持水平擴展,須要在客戶端進行分片,這其實對調用方並不友好。若是能服務端集羣可以支持水平擴展,會更完美一些。
相關文章:
說了不少,但願你們對redis和memcache有了新的認識,哪怕是一點點。