1、線程問題
由于Redis只使用單核,而Memcached可以使用多核,所以平均每一個(gè)核上Redis在存儲(chǔ)小數(shù)據(jù)時(shí)比Memcached性能更高。而在100k以上的數(shù)據(jù)中,Memcached性能要高于Redis,雖然Redis最近也在存儲(chǔ)大數(shù)據(jù)的性能上進(jìn)行優(yōu)化,但是比起 Memcached,還是稍有遜色。
因?yàn)?Redis 的操作都非常快速——它的數(shù)據(jù)全部在內(nèi)存里,完全不需要訪問磁盤。至于并發(fā),Redis 使用多路 I/O 復(fù)用技術(shù),本身的并發(fā)效率不成問題。
當(dāng)然,單個(gè) Redis 進(jìn)程沒辦法使用多核(任一時(shí)刻只能跑在一個(gè) CPU 核心上),但是它本來就不是非常計(jì)算密集型的服務(wù)。如果單核性能不夠用,可以多開幾個(gè)進(jìn)程。
Redis 單線程-多路復(fù)用io模型
、
2、內(nèi)存使用效率對(duì)比:
使用簡單的key-value存儲(chǔ)的話,Memcached的內(nèi)存利用率更高,而如果Redis采用hash結(jié)構(gòu)來做key-value存儲(chǔ),由于其組合式的壓縮,其內(nèi)存利用率會(huì)高于Memcached。
3、數(shù)據(jù)類型:
Redis相比Memcached來說,擁有更多的數(shù)據(jù)結(jié)構(gòu)和并支持更豐富的數(shù)據(jù)操作,通常在Memcached 里,你需要將數(shù)據(jù)拿到客戶端來進(jìn)行類似的修改再set回去。這大大增加了網(wǎng)絡(luò)IO的次數(shù)和數(shù)據(jù)體積。在Redis中,這些復(fù)雜的操作通常和一般的 GET/SET一樣高效。所以,如果需要緩存能夠支持更復(fù)雜的結(jié)構(gòu)和操作,那么Redis會(huì)是不錯(cuò)的選擇。
4、安全機(jī)制
memcached采用cas機(jī)制,而redis有事務(wù)機(jī)制。
5、事件模型
memcached采用了libevent事件模型,多線程模型可以發(fā)揮多核作用,Redis實(shí)現(xiàn)了自己的一套和libevent類似的事件驅(qū)動(dòng)機(jī)制,兩者都采用了epoll通信模型和非阻塞機(jī)制。
epoll是在2.6內(nèi)核中提出的,是之前的select和poll的增強(qiáng)版本。相對(duì)于select和poll來說,epoll更加靈活,沒有描述符限制。epoll使用一個(gè)文件描述符管理多個(gè)描述符,將用戶關(guān)系的文件描述符的事件存放到內(nèi)核的一個(gè)事件表中,這樣在用戶空間和內(nèi)核空間的copy只需一次。
最后講講 為什么epoll會(huì)比select高效,主要從三方面來進(jìn)行論述。
(1)elect對(duì)描述符狀態(tài)的改變是通過輪詢來進(jìn)行查找的;而epoll是當(dāng)描述符狀態(tài)發(fā)生改變時(shí)主動(dòng)進(jìn)行通知內(nèi)核,這就是所謂的Reactor事件處理機(jī)制。可以用“好萊塢原則”進(jìn)行描述:不要打電話給我們,我們會(huì)打電話通知你。相比之下,select的機(jī)制就好比面試結(jié)束后不停給面試官打電話詢問面試結(jié)果。效率孰高孰低,可見一 斑。
(2)select的文件描述符是使用鏈表進(jìn)行組織的;而epoll是使用紅黑樹這一高效數(shù)據(jù)結(jié)構(gòu)組織的。
(3)select從內(nèi)核到用戶空間傳遞文件描述符上發(fā)送的信息是使用內(nèi)存復(fù)制的方式進(jìn)行的;而epoll是采用共享內(nèi)存的方式。
6、內(nèi)存管理方面
Memcached使用預(yù)分配的內(nèi)存池的方式,使用slab和大小不同的chunk來管理內(nèi)存,Item根據(jù)大小選擇合適的chunk存儲(chǔ),內(nèi)存池的方式可以省去申請(qǐng)/釋放內(nèi)存的開銷,并且能減小內(nèi)存碎片產(chǎn)生,但這種方式也會(huì)帶來一定程度上的空間浪費(fèi),并且在內(nèi)存仍然有很大空間時(shí),新的數(shù)據(jù)也可能會(huì)被剔除,原因可以參考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/
Redis使用現(xiàn)場(chǎng)申請(qǐng)內(nèi)存的方式來存儲(chǔ)數(shù)據(jù),并且很少使用free-list等方式來優(yōu)化內(nèi)存分配,會(huì)在一定程度上存在內(nèi)存碎片,Redis跟據(jù)存儲(chǔ)命令參數(shù),會(huì)把帶過期時(shí)間的數(shù)據(jù)單獨(dú)存放在一起,并把它們稱為臨時(shí)數(shù)據(jù),非臨時(shí)數(shù)據(jù)是永遠(yuǎn)不會(huì)被剔除的,即便物理內(nèi)存不夠,導(dǎo)致swap也不會(huì)剔除任何非臨時(shí)數(shù)據(jù)(但會(huì)嘗試剔除部分臨時(shí)數(shù)據(jù)),這點(diǎn)上Redis更適合作為存儲(chǔ)而不是cache。
7、redis并發(fā)
Redis 是一個(gè)高性能的key-value數(shù)據(jù)庫。 redis的出現(xiàn),很大程度補(bǔ)償了memcached這類keyvalue存儲(chǔ)的不足,在部 分場(chǎng)合可以對(duì)關(guān)系數(shù)據(jù)庫起到很好的補(bǔ)充作用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。
性能測(cè)試結(jié)果:
SET操作每秒鐘 110000 次,GET操作每秒鐘 81000 次,服務(wù)器配置如下:
Linux 2.6, Xeon X3320 2.5Ghz.
stackoverflow 網(wǎng)站使用 Redis 做為緩存服務(wù)器。