為什么redis 是單線程的?

以前一直有個(gè)誤區(qū),以為:高性能服務(wù)器 一定是 多線程來(lái)實(shí)現(xiàn)的

原因很簡(jiǎn)單因?yàn)檎`區(qū)二導(dǎo)致的:多線程 一定比 單線程 效率高。其實(shí)不然。

在說(shuō)這個(gè)事前希望大家都能對(duì) CPU 、 內(nèi)存 、 硬盤的速度都有了解了,這樣可能理解得更深刻一點(diǎn),不了解的朋友點(diǎn):CPU到底比內(nèi)存跟硬盤快多少

redis 核心就是 如果我的數(shù)據(jù)全都在內(nèi)存里,我單線程的去操作 就是效率最高的,為什么呢,因?yàn)槎嗑€程的本質(zhì)就是 CPU 模擬出來(lái)多個(gè)線程的情況,這種模擬出來(lái)的情況就有一個(gè)代價(jià),就是上下文的切換,對(duì)于一個(gè)內(nèi)存的系統(tǒng)來(lái)說(shuō),它沒(méi)有上下文的切換就是效率最高的。redis 用 單個(gè)CPU 綁定一塊內(nèi)存的數(shù)據(jù),然后針對(duì)這塊內(nèi)存的數(shù)據(jù)進(jìn)行多次讀寫(xiě)的時(shí)候,都是在一個(gè)CPU上完成的,所以它是單線程處理這個(gè)事。在內(nèi)存的情況下,這個(gè)方案就是最佳方案 ?—— 阿里 沈詢

因?yàn)橐淮蜟PU上下文的切換大概在 1500ns 左右。

從內(nèi)存中讀取 1MB 的連續(xù)數(shù)據(jù),耗時(shí)大約為 250us,假設(shè)1MB的數(shù)據(jù)由多個(gè)線程讀取了1000次,那么就有1000次時(shí)間上下文的切換,

那么就有1500ns * 1000 = 1500us ,我單線程的讀完1MB數(shù)據(jù)才250us ,你光時(shí)間上下文的切換就用了1500us了,我還不算你每次讀一點(diǎn)數(shù)據(jù) 的時(shí)間,

那什么時(shí)候用多線程的方案呢?

答案是:下層的存儲(chǔ)等慢速的情況。比如磁盤

內(nèi)存是一個(gè) IOPS 非常高的系統(tǒng),因?yàn)槲蚁肷暾?qǐng)一塊內(nèi)存就申請(qǐng)一塊內(nèi)存,銷毀一塊內(nèi)存我就銷毀一塊內(nèi)存,內(nèi)存的申請(qǐng)和銷毀是很容易的。而且內(nèi)存是可以動(dòng)態(tài)的申請(qǐng)大小的。

磁盤的特性是:IPOS很低很低,但吞吐量很高。這就意味著,大量的讀寫(xiě)操作都必須攢到一起,再提交到磁盤的時(shí)候,性能最高。為什么呢?

如果我有一個(gè)事務(wù)組的操作(就是幾個(gè)已經(jīng)分開(kāi)了的事務(wù)請(qǐng)求,比如寫(xiě)讀寫(xiě)讀寫(xiě),這么五個(gè)操作在一起),在內(nèi)存中,因?yàn)镮OPS非常高,我可以一個(gè)一個(gè)的完成,但是如果在磁盤中也有這種請(qǐng)求方式的話,

我第一個(gè)寫(xiě)操作是這樣完成的:我先在硬盤中尋址,大概花費(fèi)10ms,然后我讀一個(gè)數(shù)據(jù)可能花費(fèi)1ms然后我再運(yùn)算(忽略不計(jì)),再寫(xiě)回硬盤又是10ms ,總共21ms

第二個(gè)操作去讀花了10ms, 第三個(gè)又是寫(xiě)花費(fèi)了21ms ,然后我再讀10ms, 寫(xiě)21ms ,五個(gè)請(qǐng)求總共花費(fèi)83ms,這還是最理想的情況下,這如果在內(nèi)存中,大概1ms不到。

所以對(duì)于磁盤來(lái)說(shuō),它吞吐量這么大,那最好的方案肯定是我將N個(gè)請(qǐng)求一起放在一個(gè)buff里,然后一起去提交。

方法就是用異步:將請(qǐng)求和處理的線程不綁定,請(qǐng)求的線程將請(qǐng)求放在一個(gè)buff里,然后等buff快滿了,處理的線程再去處理這個(gè)buff。然后由這個(gè)buff 統(tǒng)一的去寫(xiě)入磁盤,或者讀磁盤,這樣效率就是最高。java里的 IO不就是這么干的么~

對(duì)于慢速設(shè)備,這種處理方式就是最佳的,慢速設(shè)備有磁盤,網(wǎng)絡(luò) ,SSD 等等,

多線程 ,異步的方式處理這些問(wèn)題非常常見(jiàn),大名鼎鼎的netty 就是這么干的。

終于把 redis 為什么是單線程說(shuō)清楚了,把什么時(shí)候用單線程跟多線程也說(shuō)清楚了,其實(shí)也是些很簡(jiǎn)單的東西,只是基礎(chǔ)不好的時(shí)候,就真的尷尬。。。。

補(bǔ)一發(fā)大師語(yǔ)錄:來(lái)說(shuō)說(shuō),為何單核cpu綁定一塊內(nèi)存效率最高

“我們不能任由操作系統(tǒng)負(fù)載均衡,因?yàn)槲覀冏约焊私庾约旱某绦?,所以我們可以手?dòng)地為其分配CPU核,而不會(huì)過(guò)多地占用CPU”,默認(rèn)情況下單線程在進(jìn)行系統(tǒng)調(diào)用的時(shí)候會(huì)隨機(jī)使用CPU內(nèi)核,為了優(yōu)化Redis,我們可以使用工具為單線程綁定固定的CPU內(nèi)核,減少不必要的性能損耗!

redis作為單進(jìn)程模型的程序,為了充分利用多核CPU,常常在一臺(tái)server上會(huì)啟動(dòng)多個(gè)實(shí)例。而為了減少切換的開(kāi)銷,有必要為每個(gè)實(shí)例指定其所運(yùn)行的CPU。

Linux 上 ?taskset 可以將某個(gè)進(jìn)程綁定到一個(gè)特定的CPU。你比操作系統(tǒng)更了解自己的程序,為了避免調(diào)度器愚蠢的調(diào)度你的程序,或是為了在多線程程序中避免緩存失效造成的開(kāi)銷。

順便再提一句:redis 的瓶頸在網(wǎng)絡(luò)上 。。。。

關(guān)注公眾號(hào)獲取更多java資源
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 近乎所有與Java相關(guān)的面試都會(huì)問(wèn)到緩存的問(wèn)題,基礎(chǔ)一點(diǎn)的會(huì)問(wèn)到什么是“二八定律”、什么是“熱數(shù)據(jù)和冷數(shù)據(jù)” ,復(fù)...
    Java資訊庫(kù)閱讀 1,146評(píng)論 0 3
  • [西湖論劍awd] web1 打比賽的時(shí)候?yàn)榱耸r(shí)看到一個(gè)洞就直接打了然后權(quán)限維持就沒(méi)仔細(xì)看,趁著有空看一下(主要...
    ckj123閱讀 1,080評(píng)論 2 2
  • 這次的五、六章增添了很多的圖文形式,特別是在第六章,圖片明顯的增多,閱讀起來(lái)也不會(huì)那么的枯燥,圖文的形式能增加對(duì)文...
    毛毛花_閱讀 861評(píng)論 0 0
  • ?看完布拉格之戀,覺(jué)得格外寂寞。 因?yàn)檫@部電影,我所有的注意點(diǎn)好像都是側(cè)面。最動(dòng)容的點(diǎn)是男女主第二次做愛(ài),飽滿到溢...
    留迎閱讀 285評(píng)論 0 0
  • 喜迎我黨十九大,深感祖國(guó)漸發(fā)達(dá)。 百載之前亂軍閥,國(guó)似枯木苦無(wú)涯。 幸得我黨救華夏,枯樹(shù)逢春再發(fā)芽。 今日放眼觀萬(wàn)...
    逆天妖猴王柳閱讀 237評(píng)論 0 0

友情鏈接更多精彩內(nèi)容