Redis為何選擇單線程?
在Redisv6.0以前,Redis的核心網(wǎng)絡(luò)模型選擇用單線程來(lái)實(shí)現(xiàn)。
核心意思就是,對(duì)于一個(gè) DB 來(lái)說(shuō),CPU 通常不會(huì)是瓶頸,因?yàn)榇蠖鄶?shù)請(qǐng)求不會(huì)是 CPU 密集型的,而是 I/O 密集型。
具體到 Redis的話,如果不考慮 RDB/AOF 等持久化方案,Redis是完全的純內(nèi)存操作,執(zhí)行速度是非常快的,因此這部分操作通常不會(huì)是性能瓶頸,Redis真正的性能瓶頸在于網(wǎng)絡(luò) I/O,也就是客戶端和服務(wù)端之間的網(wǎng)絡(luò)傳輸延遲,因此 Redis選擇了單線程的 I/O 多路復(fù)用來(lái)實(shí)現(xiàn)它的核心網(wǎng)絡(luò)模型。
實(shí)際上更加具體的選擇單線程的原因如下:
避免過(guò)多的上下文切換開(kāi)銷:如果是單線程則可以規(guī)避進(jìn)程內(nèi)頻繁的線程切換開(kāi)銷,因?yàn)槌绦蚴冀K運(yùn)行在進(jìn)程中單個(gè)線程內(nèi),沒(méi)有多線程切換的場(chǎng)景。
避免同步機(jī)制的開(kāi)銷:如果 Redis選擇多線程模型,又因?yàn)?Redis是一個(gè)數(shù)據(jù)庫(kù),那么勢(shì)必涉及到底層數(shù)據(jù)同步的問(wèn)題,則必然會(huì)引入某些同步機(jī)制,比如鎖,而我們知道 Redis不僅僅提供了簡(jiǎn)單的 key-value 數(shù)據(jù)結(jié)構(gòu),還有 list、set 和 hash 等等其他豐富的數(shù)據(jù)結(jié)構(gòu),而不同的數(shù)據(jù)結(jié)構(gòu)對(duì)同步訪問(wèn)的加鎖粒度又不盡相同,可能會(huì)導(dǎo)致在操作數(shù)據(jù)過(guò)程中帶來(lái)很多加鎖解鎖的開(kāi)銷,增加程序復(fù)雜度的同時(shí)還會(huì)降低性能。
簡(jiǎn)單可維護(hù):如果 Redis使用多線程模式,那么所有的底層數(shù)據(jù)結(jié)構(gòu)都必須實(shí)現(xiàn)成線程安全的,這無(wú)疑又使得 Redis的實(shí)現(xiàn)變得更加復(fù)雜。
總而言之,Redis選擇單線程可以說(shuō)是多方博弈之后的一種權(quán)衡:在保證足夠的性能表現(xiàn)之下,使用單線程保持代碼的簡(jiǎn)單和可維護(hù)性。
Redis真的是單線程?
討論 這個(gè)問(wèn)題前,先看下 Redis的版本中兩個(gè)重要的節(jié)點(diǎn):
Redis 4.0(引入多線程處理異步任務(wù))
Redis 6.0(正式在網(wǎng)絡(luò)模型中實(shí)現(xiàn) I/O 多線程)
所以,網(wǎng)絡(luò)上說(shuō)的Redis是單線程,通常是指在Redis 6.0之前,其核心網(wǎng)絡(luò)模型使用的是單線程;而Redis的異步任務(wù)使用的仍是多線程。
Redis在 4.0 版本的時(shí)候就已經(jīng)引入了的多線程來(lái)做一些異步操作,此舉主要針對(duì)的是那些非常耗時(shí)的命令,通過(guò)將這些命令的執(zhí)行進(jìn)行異步化,避免阻塞單線程的事件循環(huán)。
在 Redis 4.0 之后增加了一些的非阻塞命令如 UNLINK、FLUSHALL ASYNC、FLUSHDB ASYNC。
Redisv6.0為何引入多線程?
很簡(jiǎn)單,就是 Redis的網(wǎng)絡(luò) I/O 瓶頸已經(jīng)越來(lái)越明顯了。
隨著互聯(lián)網(wǎng)的飛速發(fā)展,互聯(lián)網(wǎng)業(yè)務(wù)系統(tǒng)所要處理的線上流量越來(lái)越大,Redis的單線程模式會(huì)導(dǎo)致系統(tǒng)消耗很多 CPU 時(shí)間在網(wǎng)絡(luò) I/O 上從而降低吞吐量,要提升 Redis的性能有兩個(gè)方向:
優(yōu)化網(wǎng)絡(luò) I/O 模塊
提高機(jī)器內(nèi)存讀寫(xiě)的速度
后者依賴于硬件的發(fā)展,暫時(shí)無(wú)解。所以只能從前者下手,網(wǎng)絡(luò) I/O 的優(yōu)化又可以分為兩個(gè)方向:
零拷貝技術(shù)或者 DPDK 技術(shù)
利用多核優(yōu)勢(shì)
零拷貝技術(shù)有其局限性,無(wú)法完全適配 Redis這一類復(fù)雜的網(wǎng)絡(luò) I/O 場(chǎng)景,更多網(wǎng)絡(luò) I/O 對(duì) CPU 時(shí)間的消耗和 Linux 零拷貝技術(shù)。而 DPDK 技術(shù)通過(guò)旁路網(wǎng)卡 I/O 繞過(guò)內(nèi)核協(xié)議棧的方式又太過(guò)于復(fù)雜以及需要內(nèi)核甚至是硬件的支持。
因此,利用多核優(yōu)勢(shì)成為了優(yōu)化網(wǎng)絡(luò) I/O 性價(jià)比最高的方案。
-
網(wǎng)絡(luò)
+關(guān)注
關(guān)注
14文章
7703瀏覽量
90093 -
線程
+關(guān)注
關(guān)注
0文章
507瀏覽量
20012 -
Redis
+關(guān)注
關(guān)注
0文章
381瀏覽量
11227
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
單線程的雙任務(wù)調(diào)度
單線程SRAM靜態(tài)內(nèi)存使用
一種單線程編程思路簡(jiǎn)析
多線程好還是單線程好?單線程和多線程的區(qū)別 優(yōu)缺點(diǎn)分析
從I/O的阻塞與非阻塞、I/O處理的單線程與多線程角度探討服務(wù)器模型
阿里云Redis多線程性能提升思路解析
實(shí)現(xiàn)Java多線程爬蟲(chóng)的兩點(diǎn)

這款16核怪物在單線程和多線程性能方面均躍居主流處理器榜首
Redis常見(jiàn)面試題及答案

單線程也能開(kāi)發(fā)異步任務(wù)?ACE JS框架到底是如何做到的

Redis基礎(chǔ)架構(gòu)設(shè)計(jì)及核心網(wǎng)絡(luò)模型架構(gòu)演進(jìn)
單線程是否會(huì)引起 fail-fast機(jī)制

Go在單線程計(jì)算性能上的優(yōu)勢(shì)

評(píng)論