參考:
Redis 和 Memcached 有什么區(qū)別?Redis 的線程模型是什么桦踊?為什么單線程的 Redis 比多線程的 Memcached 效率要高得多?
一.redis 和 memcached 有啥區(qū)別?
1.redis 支持復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
redis 相比 memcached 來說驼修,擁有更多的數(shù)據(jù)結(jié)構(gòu),能支持更豐富的數(shù)據(jù)操作诈铛。如果需要緩存能夠支持更復(fù)雜的結(jié)構(gòu)和操作乙各, redis 會(huì)是不錯(cuò)的選擇。
2.redis 原生支持集群模式
在 redis3.x 版本中幢竹,便能支持 cluster 模式耳峦,而 memcached 沒有原生的集群模式,需要依靠客戶端來實(shí)現(xiàn)往集群中分片寫入數(shù)據(jù)焕毫。
3.性能對(duì)比
由于 redis 只使用單核蹲坷,而 memcached 可以使用多核驶乾,所以平均每一個(gè)核上 redis 在存儲(chǔ)小數(shù)據(jù)時(shí)比 memcached 性能更高。而在 100k 以上的數(shù)據(jù)中循签,memcached 性能要高于 redis轻掩,雖然 redis 最近也在存儲(chǔ)大數(shù)據(jù)的性能上進(jìn)行優(yōu)化,但是比起 memcached懦底,還是稍有遜色唇牧。
二.redis 的線程模型
redis 內(nèi)部使用文件事件處理器
file event handler
,這個(gè)文件事件處理器是單線程的聚唐,所以 redis 才叫做單線程的模型丐重。它采用 IO 多路復(fù)用機(jī)制同時(shí)監(jiān)聽多個(gè) socket,根據(jù) socket 上的事件來選擇對(duì)應(yīng)的事件處理器進(jìn)行處理杆查。
文件事件處理器的結(jié)構(gòu)包含 4 個(gè)部分:
- 多個(gè) socket
- IO 多路復(fù)用程序
- 文件事件分派器
- 事件處理器(連接應(yīng)答處理器扮惦、命令請(qǐng)求處理器、命令回復(fù)處理器)
多個(gè) socket 可能會(huì)并發(fā)產(chǎn)生不同的操作亲桦,每個(gè)操作對(duì)應(yīng)不同的文件事件崖蜜,但是 IO 多路復(fù)用程序會(huì)監(jiān)聽多個(gè) socket,會(huì)將 socket 產(chǎn)生的事件放入隊(duì)列中排隊(duì)客峭,事件分派器每次從隊(duì)列中取出一個(gè)事件豫领,把該事件交給對(duì)應(yīng)的事件處理器進(jìn)行處理。
來看客戶端與 redis 的一次通信過程:
1.客戶端 socket01 向 redis 的 server socket 請(qǐng)求建立連接舔琅,此時(shí) server socket 會(huì)產(chǎn)生一個(gè)
AE_READABLE
事件等恐,IO 多路復(fù)用程序監(jiān)聽到 server socket 產(chǎn)生的事件后,將該事件壓入隊(duì)列中备蚓。
2.文件事件分派器從隊(duì)列中獲取該事件课蔬,交給連接應(yīng)答處理器
。
3.連接應(yīng)答處理器會(huì)創(chuàng)建一個(gè)能與客戶端通信的 socket01郊尝,并將該 socket01 的AE_READABLE
事件與命令請(qǐng)求處理器關(guān)聯(lián)二跋。
4.假設(shè)此時(shí)客戶端發(fā)送了一個(gè)set key value
請(qǐng)求,此時(shí) redis 中的 socket01 會(huì)產(chǎn)生AE_READABLE
事件流昏,IO 多路復(fù)用程序?qū)⑹录喝腙?duì)列扎即,此時(shí)事件分派器從隊(duì)列中獲取到該事件,由于前面 socket01 的AE_READABLE
事件已經(jīng)與命令請(qǐng)求處理器關(guān)聯(lián)横缔,因此事件分派器將事件交給命令請(qǐng)求處理器來處理铺遂。
5.命令請(qǐng)求處理器讀取 socket01 的key value
并在自己內(nèi)存中完成key value
的設(shè)置。操作完成后茎刚,它會(huì)將 socket01 的AE_WRITABLE
事件與命令回復(fù)處理器關(guān)聯(lián)襟锐。
6.如果此時(shí)客戶端準(zhǔn)備好接收返回結(jié)果了,那么 redis 中的 socket01 會(huì)產(chǎn)生一個(gè)AE_WRITABLE
事件膛锭,同樣壓入隊(duì)列中粮坞,事件分派器找到相關(guān)聯(lián)的命令回復(fù)處理器蚊荣,由命令回復(fù)處理器對(duì) socket01 輸入本次操作的一個(gè)結(jié)果,比如ok
莫杈,之后解除 socket01 的AE_WRITABLE
事件與命令回復(fù)處理器的關(guān)聯(lián)互例。
這樣便完成了一次通信。
三.為啥 redis 單線程模型也能效率這么高筝闹?
- 純內(nèi)存操作
- 核心是基于非阻塞的 IO 多路復(fù)用機(jī)制
- 單線程反而避免了多線程的頻繁上下文切換問題