Redis是单线程为什么还那么快?
Redis為什么還那么快
基于內(nèi)存
??Redis完全基于內(nèi)存,絕大部分請(qǐng)求是純粹的內(nèi)存操作,Redis將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,讀寫數(shù)據(jù)的時(shí)候不會(huì)受到硬盤I/O速度的限制(內(nèi)存速度為什么比硬盤快?),類似于HashMap(HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1))。
單線程
??Redis采用單線程的模型,確保每個(gè)操作的原子性,避免不必要的上下文切換和競(jìng)爭(zhēng)條件,自然也就不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗CPU,也不用去考慮各種鎖的問題,不存在加解鎖的操作,所以沒有可能出現(xiàn)死鎖導(dǎo)致的性能消耗
使用多路復(fù)用
??Redis采用網(wǎng)絡(luò)IO多路復(fù)用技術(shù)來保證多鏈接的時(shí)候系統(tǒng)的高吞吐量。可以讓單個(gè)線程高效的處理多個(gè)鏈接請(qǐng)求,減少網(wǎng)絡(luò)IO時(shí)間消耗。主要是利用了select、poll、epoll可以同時(shí)監(jiān)察多了IO時(shí)間的能力,一次順序的處理就緒的IO事件避免了大量的無用的操作,從而提高效率。
自己的事件分離器
??redis使用自己實(shí)現(xiàn)的事件分離器,效率比較高,內(nèi)部采用非阻塞的執(zhí)行方式,吞吐量能力比較大
靈活多變的數(shù)據(jù)結(jié)構(gòu)
??redis內(nèi)部使用一個(gè)redisObject對(duì)象來表示所有的key和calue。redisObject主要的信息包括數(shù)據(jù)類型、編碼方式、數(shù)據(jù)指針、虛擬內(nèi)存等。主要包含string、Hash、List、Set、Sorted Set物種數(shù)據(jù)類型,針對(duì)不同的場(chǎng)景使用對(duì)應(yīng)的數(shù)據(jù)類型,減少內(nèi)存使用的同時(shí),節(jié)省網(wǎng)絡(luò)流量的傳輸
Redis為什么是單線程?為什么不用多線程?
??首先需要明確的一點(diǎn)就是單線程指的是網(wǎng)絡(luò)請(qǐng)求模塊使用了一個(gè)線程,所以不需要考慮并發(fā)安全性,其他科模塊也會(huì)用到多線程,在使用redis的過程中充分的發(fā)揮其優(yōu)勢(shì),避免一些不當(dāng)操作導(dǎo)致性能的下降。說redis是單線程只是在4.0版本之前,在4.0之后的版本中就加入了多線程的支持。Redis從一開始就使用單線程模型處理來自客戶端的網(wǎng)絡(luò)請(qǐng)求,其實(shí)原因是多方面的,重要的有三個(gè):高可維護(hù)性、單線程也可以處理并發(fā)請(qǐng)求、性能瓶頸不是CPU
多線程模型雖然在某些方面變現(xiàn)優(yōu)異,但是他的執(zhí)行順序是不確定的,代碼的執(zhí)行過程不再是串行的,并且多個(gè)線程同時(shí)訪問的變量如果沒有謹(jǐn)慎處理可能最后的結(jié)果會(huì)是不正確的
使用單線程并不代表不能并發(fā)處理任務(wù),Redis雖然使用的是單線程模型處理用戶的請(qǐng)求,但他確實(shí)用I/O多路復(fù)用機(jī)制并發(fā)處理客戶端的多個(gè)鏈接。使用I/O多路復(fù)用技術(shù)能夠極大的減少系統(tǒng)的開銷,系統(tǒng)不在需要額外創(chuàng)建和維護(hù)進(jìn)程和線程來監(jiān)聽客戶端的大量鏈接,減少了服務(wù)器開發(fā)和維護(hù)的成本。
性能瓶頸是Redis選擇單線程模型的決定性原因。多線程技術(shù)確實(shí)能夠幫助我們充分的利用CPU的計(jì)算資源來并發(fā)的執(zhí)行任務(wù),但是CPU資源并不是Redis服務(wù)器的性能瓶頸。即使實(shí)在一個(gè)普通的linux中啟動(dòng)Redis服務(wù),也可以達(dá)到百萬QPS。
總結(jié)
??Redis并不是CPU密集型的服務(wù),如果不持久化,所有的Redis數(shù)據(jù)都只會(huì)在內(nèi)存中完成,并不會(huì)涉及到任何的I/O操作,所以處理速度是非常快的。Redis的瓶頸是在于網(wǎng)絡(luò)傳輸帶來的延遲和等待客戶端的數(shù)據(jù)傳輸(網(wǎng)絡(luò)I/O),所以使用多線程模型來處理全部的外部請(qǐng)求并不是一個(gè)很好的選擇。
??多線程雖然可以充分的利用CPU資源,但是在操作系統(tǒng)上的切換也會(huì)帶來額外的開銷,比如所加載和執(zhí)行線程的上下文,頻繁的對(duì)線程上下文進(jìn)行切換還會(huì)導(dǎo)致性能的急劇下降,可能會(huì)導(dǎo)致我們的優(yōu)化進(jìn)行倒退,這也是為什么Redis對(duì)于使用多線程技術(shù)的非常謹(jǐn)慎的原因。
??Redis在4.0后的版本中引入了多線程,加入了一些可以被其他線程異步處理的刪除操作(UNLINK、FLUSHALL ASYNC 和 FLUSHDB ASYNC)。在Redis中使用DEL命令刪除鍵對(duì)應(yīng)的值,如果鍵占用的空間比較小,同步刪除并不會(huì)太耗時(shí),但是針對(duì)一些超大的鍵值對(duì),比如幾十或者幾百M(fèi)B的數(shù)據(jù)并不能很快的處理完,就會(huì)消耗較多的時(shí)間,會(huì)影響到Redis服務(wù)處理請(qǐng)求的速度和可用性。其實(shí)這個(gè)釋放內(nèi)存的工作可以交給后臺(tái)的多線程進(jìn)行異步的處理,這就是UNLINK命令,他只是將鍵從元數(shù)據(jù)中刪除,其真正的刪除是在后臺(tái)異步進(jìn)行。
??說了這么多,Redis選擇使用單線程模型處理客戶端的請(qǐng)求還是因?yàn)镃PU不是Redis服務(wù)器的瓶頸,所以使用多線程模型可能會(huì)起到相反的效果,其主要的瓶頸是在網(wǎng)絡(luò)I/O上。Redis引入多線程主要是針對(duì)一些大的鍵值對(duì)的刪除操作,在后臺(tái)異步進(jìn)行空間的釋放,減少對(duì)Redis主線程的阻塞,提高執(zhí)行效率。
總結(jié)
以上是生活随笔為你收集整理的Redis是单线程为什么还那么快?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python二级基础知识点
- 下一篇: 双摄与双目视觉