Redis為什么這么快

Redis快的原因

  1. 內(nèi)存結(jié)構(gòu)
  2. 單線程
  3. IO多路復(fù)用

內(nèi)存結(jié)構(gòu)

Redis是KV結(jié)構(gòu)的內(nèi)存數(shù)據(jù)庫够傍,在內(nèi)存上操作數(shù)據(jù)才睹,而非磁盤亮垫。

單線程

Redis為什么是單線程的杆兵?

It's not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.
However, to maximize CPU usage you can start multiple instances of Redis in the same box and treat them as different servers. At some point a single box may not be enough anyway, so if you want to use multiple CPUs you can start thinking of some way to shard earlier.

因?yàn)閱尉€程已經(jīng)夠用了揪阿,CPU 不是 redis 的瓶頸疗我。Redis 的瓶頸最有可能是機(jī)器內(nèi)存 或者網(wǎng)絡(luò)帶寬咆畏。既然單線程容易實(shí)現(xiàn),而且 CPU 不會(huì)成為瓶頸吴裤,那就順理成章地采用單線程的方案了旧找。
這里的單線程指的只是在處理我們的網(wǎng)絡(luò)請(qǐng)求的時(shí)候只有一個(gè)線程來處理,一個(gè)正式的Redis Server運(yùn)行的時(shí)候肯定是不止一個(gè)線程的麦牺。而且我們使用單線程的方式是無法發(fā)揮多核CPU 性能钮蛛,不過我們可以通過在單機(jī)開多個(gè)Redis 實(shí)例來完善!

單線程為什么這么快?

首先要講一下內(nèi)存模型:
計(jì)算機(jī)主存(內(nèi)存)可看作一個(gè)由 M 個(gè)連續(xù)的字節(jié)大小的單元組成的數(shù)組剖膳,每個(gè)字 節(jié)有一個(gè)唯一的地址魏颓,這個(gè)地址叫做物理地址(PA)。早期的計(jì)算機(jī)中潮秘,如果 CPU 需要內(nèi)存琼开,使用物理尋址,直接訪問主存儲(chǔ)器枕荞。


直接操作內(nèi)存

這種方式有幾個(gè)弊端:

  1. 在多用戶多任務(wù)操作系統(tǒng)中柜候,所有的進(jìn)程共享主存,如果每個(gè)進(jìn)程都獨(dú)占一塊物理地址空間躏精,主存很快就會(huì)被用完渣刷。我們希望在不同的時(shí)刻,不同的進(jìn)程可以共用同一塊物理地址空間矗烛。
  2. 如果所有進(jìn)程都是直接訪問物理內(nèi)存辅柴,那么一個(gè)進(jìn)程就可以修改其他進(jìn)程的內(nèi)存數(shù)據(jù),導(dǎo)致物理地址空間被破壞瞭吃,程序運(yùn)行就會(huì)出現(xiàn)異常碌嘀。

為了解決這些問題,就出現(xiàn)了在 CPU 和主存之間增加一個(gè)中間層歪架。CPU 不再使用物理地址訪問股冗,而是訪問一個(gè)虛擬地址,由這個(gè)中間層把地址轉(zhuǎn)換成物理地址和蚪, 最終獲得數(shù)據(jù)止状。這個(gè)中間層就是虛擬內(nèi)存。


虛擬內(nèi)存

在每一個(gè)進(jìn)程開始創(chuàng)建的時(shí)候攒霹,都會(huì)分配一段虛擬地址怯疤,然后通過虛擬地址和物理
地址的映射來獲取真實(shí)數(shù)據(jù),這樣進(jìn)程就不會(huì)直接接觸到物理地址催束,甚至不知道自己調(diào)用的哪塊物理地址的數(shù)據(jù)集峦。

進(jìn)程切換

多任務(wù)操作系統(tǒng)是怎么實(shí)現(xiàn)運(yùn)行遠(yuǎn)大于 CPU 數(shù)量的任務(wù)個(gè)數(shù)的?當(dāng)然,這些任務(wù)實(shí)際上并不是真的在同時(shí)運(yùn)行,而是因?yàn)橄到y(tǒng)通過時(shí)間片分片算法少梁,在很短的時(shí)間內(nèi)洛口,將 CPU 輪流分配給它們,造成多任務(wù)同時(shí)運(yùn)行的錯(cuò)覺凯沪。為了控制進(jìn)程的執(zhí)行第焰,內(nèi)核必須有能力掛起正在 CPU 上運(yùn)行的進(jìn)程,并恢復(fù)以前掛起的某個(gè)進(jìn)程的執(zhí)行妨马。這種行為被稱為進(jìn)程切換挺举。

在每個(gè)任務(wù)運(yùn)行前,CPU 都需要知道任務(wù)從哪里加載烘跺、又從哪里開始運(yùn)行湘纵,也就是 說,需要系統(tǒng)事先幫它設(shè)置好 CPU 寄存器和程序計(jì)數(shù)器(ProgramCounter)滤淳,這個(gè)叫做 CPU 的上下文梧喷。
而這些保存下來的上下文,會(huì)存儲(chǔ)在系統(tǒng)內(nèi)核中脖咐,并在任務(wù)重新調(diào)度執(zhí)行時(shí)再次加 載進(jìn)來铺敌。這樣就能保證任務(wù)原來的狀態(tài)不受影響,讓任務(wù)看起來還是連續(xù)運(yùn)行屁擅。
在切換上下文的時(shí)候偿凭,需要完成一系列的工作,這是一個(gè)很消耗資源的操作派歌。

單線程的好處

  1. 沒有創(chuàng)建線程弯囊、銷毀線程帶來的消耗。
  2. 避免了上線文切換導(dǎo)致的 CPU 消耗胶果。
  3. 避免了線程之間帶來的競(jìng)爭(zhēng)問題匾嘱,例如加鎖釋放鎖死鎖等等。

IO多路復(fù)用

傳統(tǒng)IO模型

以讀操作為例:當(dāng)應(yīng)用程序執(zhí)行 read 系統(tǒng)調(diào)用讀取文件描述符(FD)的時(shí)候早抠,如果這塊數(shù)據(jù)已經(jīng)存在于用戶進(jìn)程的頁內(nèi)存中奄毡,就直接從內(nèi)存中讀取數(shù)據(jù)。如果數(shù)據(jù)不存在贝或,則先將數(shù)據(jù)從磁盤加載數(shù)據(jù)到內(nèi)核緩沖區(qū)中,再從內(nèi)核緩沖區(qū)拷貝到用戶進(jìn)程的頁內(nèi)存中锐秦。(兩次拷貝咪奖,兩次 user 和 kernel 的上下文切換)。


BlockingIO


當(dāng)使用 read 或 write 對(duì)某個(gè)文件描述符進(jìn)行過讀寫時(shí)酱床,如果當(dāng)前 FD 不可讀羊赵,系統(tǒng)就不會(huì)對(duì)其他的操作做出響應(yīng)。從設(shè)備復(fù)制數(shù)據(jù)到內(nèi)核緩沖區(qū)是阻塞的,從內(nèi)核緩沖區(qū) 拷貝到用戶空間昧捷,也是阻塞的闲昭,直到 copy complete,內(nèi)核返回結(jié)果靡挥,用戶進(jìn)程才解除 block 的狀態(tài)序矩。

IO多路復(fù)用

I/O 指的是網(wǎng)絡(luò) I/O。
多路指的是多個(gè) TCP 連接(Socket 或 Channel)跋破。 復(fù)用指的是復(fù)用一個(gè)或多個(gè)線程簸淀。 它的基本原理就是不再由應(yīng)用程序自己監(jiān)視連接,而是由內(nèi)核替應(yīng)用程序監(jiān)視文件
描述符毒返。
客戶端在操作的時(shí)候租幕,會(huì)產(chǎn)生具有不同事件類型的 socket。在服務(wù)端拧簸,I/O 多路復(fù) 用程序(I/O Multiplexing Module)會(huì)把消息放入隊(duì)列中劲绪,然后通過文件事件分派器(File event Dispatcher),轉(zhuǎn)發(fā)到不同的事件處理器中盆赤。



多路復(fù)用有很多的實(shí)現(xiàn)贾富,以 select 為例,當(dāng)用戶進(jìn)程調(diào)用了多路復(fù)用器弟劲,進(jìn)程會(huì)被 阻塞祷安。內(nèi)核會(huì)監(jiān)視多路復(fù)用器負(fù)責(zé)的所有 socket,當(dāng)任何一個(gè) socket 的數(shù)據(jù)準(zhǔn)備好了兔乞, 多路復(fù)用器就會(huì)返回汇鞭。這時(shí)候用戶進(jìn)程再調(diào)用 read 操作,把數(shù)據(jù)從內(nèi)核緩沖區(qū)拷貝到用戶空間庸追。

I/O 多路復(fù)用的特點(diǎn)是通過一種機(jī)制一個(gè)進(jìn)程能同時(shí)等待多個(gè)文件描述符霍骄, 而這些文件描述符(套接字描述符)其中的任意一個(gè)進(jìn)入讀就緒(readable)狀態(tài),select() 函數(shù)就可以返回淡溯。

采用多路 I/O 復(fù)用技術(shù)可以讓單個(gè)線程高效的處理多個(gè)連接請(qǐng)求(盡量減少網(wǎng)絡(luò) IO 的時(shí)間消耗)读整,且 Redis 在內(nèi)存中操作數(shù)據(jù)的速度非常快咱娶,也就是說內(nèi)存內(nèi)的操作不會(huì)成為影響Redis性能的瓶頸米间,主要由以上幾點(diǎn)造就了 Redis 具有很高的吞吐量。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膘侮,一起剝皮案震驚了整個(gè)濱河市屈糊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琼了,老刑警劉巖逻锐,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡昧诱,警方通過查閱死者的電腦和手機(jī)晓淀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盏档,“玉大人凶掰,你說我怎么就攤上這事∽鼻穑” “怎么了锄俄?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長勺拣。 經(jīng)常有香客問我奶赠,道長,這世上最難降的妖魔是什么药有? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任毅戈,我火速辦了婚禮,結(jié)果婚禮上愤惰,老公的妹妹穿的比我還像新娘苇经。我一直安慰自己,他們只是感情好宦言,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布扇单。 她就那樣靜靜地躺著,像睡著了一般奠旺。 火紅的嫁衣襯著肌膚如雪蜘澜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天响疚,我揣著相機(jī)與錄音鄙信,去河邊找鬼。 笑死忿晕,一個(gè)胖子當(dāng)著我的面吹牛装诡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播践盼,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼鸦采,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了咕幻?” 一聲冷哼從身側(cè)響起赖淤,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谅河,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绷耍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年吐限,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褂始。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诸典,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出崎苗,到底是詐尸還是另有隱情狐粱,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布胆数,位于F島的核電站肌蜻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏必尼。R本人自食惡果不足惜蒋搜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望判莉。 院中可真熱鬧豆挽,春花似錦、人聲如沸券盅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锰镀。三九已至娘侍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間互站,已是汗流浹背私蕾。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胡桃,地道東北人踩叭。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像翠胰,于是被迫代替她去往敵國和親容贝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 2019.9.16更新:增加了對(duì)緩存雪崩满力,緩存穿透焕参,緩存擊穿的描述。并附上本人對(duì)Redis單線程油额,多線程實(shí)現(xiàn)的理解...
    渡你眉間山河閱讀 372評(píng)論 0 0
  • Redis簡介 Redis是一個(gè)開源的內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng)叠纷,它可以用作:數(shù)據(jù)庫、緩存和消息中間件潦嘶。它支持多種類...
    MikeLue閱讀 371評(píng)論 0 0
  • Redis 單進(jìn)程單線程模型的基于內(nèi)存的KV 數(shù)據(jù)庫涩嚣,由C語言編寫 Memcached 是單進(jìn)程多線程的同樣基于內(nèi)...
    watermountain閱讀 386評(píng)論 0 1
  • 過年時(shí)候趁著活動(dòng)抽的,上學(xué)時(shí)候存了一百張左右藍(lán)票掂僵,全用了航厚,所以是非洲人還是歐洲人呢
    寰宇風(fēng)光閱讀 372評(píng)論 0 0
  • 獨(dú)醉嚴(yán)冬曉夢(mèng)寒。 人若無情锰蓬,思易尋難幔睬。 情殤閑奏寄青鸞。 雪下蹁躚互妓,晨夢(mèng)難宣溪窒。 書卷暗藏一世緣。 朝也默念冯勉,夕也思...
    北辰星海閱讀 377評(píng)論 2 7