欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文弄懂Redis 線(xiàn)程模型

 更新時(shí)間:2024年02月12日 09:47:26   作者:程序猿進(jìn)階  
使用Redis 時(shí),幾乎不存在 CPU 成為瓶頸的情況, Redis 主要受限于內(nèi)存和網(wǎng)絡(luò) 使用了單線(xiàn)程后,可維護(hù)性高,感興趣的可以了解一下

一、概述

【1】Redis 是基于 Reactor 模式開(kāi)發(fā)的網(wǎng)絡(luò)事件處理器:這個(gè)處理器被稱(chēng)為文件事件處理器(file event handler),這個(gè)文件事件處理器是單線(xiàn)程的,所以 Redis 才叫做單線(xiàn)程的模型:

  • 文件事件處理器使用 I/O 多路復(fù)用(multiplexing)機(jī)制監(jiān)聽(tīng)多個(gè)套接字 Socket,根據(jù) Socket 上的事件來(lái)選擇對(duì)應(yīng)的事件處理器進(jìn)行處理。
  • 當(dāng)被監(jiān)聽(tīng)的套接字準(zhǔn)備好執(zhí)行連接應(yīng)答(accept)、讀?。?code>read)、寫(xiě)入(write)、關(guān)閉(close)等操作時(shí)。與操作相對(duì)應(yīng)的文件事件就會(huì)產(chǎn)生,這時(shí)文件事件處理器就會(huì)調(diào)用套接字之前關(guān)聯(lián)好的事件處理器來(lái)處理這些事件。

【2】雖然文件事件處理器以單線(xiàn)程的方式運(yùn)行,但其使用 I/O 多路復(fù)用程序來(lái)監(jiān)聽(tīng)多個(gè)套接字,文件事件處理器既實(shí)現(xiàn)了高性能的網(wǎng)絡(luò)通信模型,又可以很好地與 Redis 服務(wù)器中其他同樣以單線(xiàn)程方式運(yùn)行的模塊進(jìn)行對(duì)接,這保持了 Redis 內(nèi)部單線(xiàn)程設(shè)計(jì)的簡(jiǎn)單性。

二、文件事件處理器的結(jié)構(gòu)

【1】文件事件處理器的結(jié)構(gòu)包含 4 個(gè)部分:

  • 多個(gè) socket
  •  IO 多路復(fù)用程序
  • 文件事件分派器
  • 事件處理器(連接應(yīng)答處理器、命令請(qǐng)求處理器、命令回復(fù)處理器)

img

【2】多個(gè) socket 可能會(huì)并發(fā)產(chǎn)生不同的操作,每個(gè)操作對(duì)應(yīng)不同的文件事件,但是 IO 多路復(fù)用程序會(huì)監(jiān)聽(tīng)多個(gè) socket,會(huì)將 socket 產(chǎn)生的事件放入隊(duì)列中排隊(duì),以有序(sequentially)、同步(synchronously)、每次一個(gè)套接字的方式向文件事件分派器傳送套接字。當(dāng)上一個(gè)套接字產(chǎn)生的事件被處理完畢之后(該套接字為事件所關(guān)聯(lián)的事件處理器執(zhí)行完畢), I/O 多路復(fù)用程序才會(huì)繼續(xù)向文件事件分派器傳送下一個(gè)套接字, 如圖:

img

文件事件分派器接收 I/O 多路復(fù)用程序傳來(lái)的套接字, 并根據(jù)套接字產(chǎn)生的事件的類(lèi)型, 調(diào)用相應(yīng)的事件處理器。服務(wù)器會(huì)為執(zhí)行不同任務(wù)的套接字關(guān)聯(lián)不同的事件處理器, 這些處理器是一個(gè)個(gè)函數(shù), 它們定義了某個(gè)事件發(fā)生時(shí), 服務(wù)器應(yīng)該執(zhí)行的動(dòng)作。

【3】I/O 多路復(fù)用程序的實(shí)現(xiàn): Redis 的 I/O 多路復(fù)用程序的所有功能都是通過(guò)包裝常見(jiàn)的 select、epollevport 和 kqueue 這些 I/O 多路復(fù)用函數(shù)庫(kù)來(lái)實(shí)現(xiàn)的, 每個(gè) I/O 多路復(fù)用函數(shù)庫(kù)在 Redis 源碼中都對(duì)應(yīng)一個(gè)單獨(dú)的文件, 比如 ae_select.c、ae_epoll.c、ae_kqueue.c , 諸如此類(lèi)。因?yàn)?nbsp;Redis 為每個(gè) I/O 多路復(fù)用函數(shù)庫(kù)都實(shí)現(xiàn)了相同的 API , 所以 I/O 多路復(fù)用程序的底層實(shí)現(xiàn)是可以互換的, 如下圖所示:

img

Redis 在 I/O 多路復(fù)用程序的實(shí)現(xiàn)源碼中用 #include 宏定義了相應(yīng)的規(guī)則, 程序會(huì)在編譯時(shí)自動(dòng)選擇系統(tǒng)中性能最高的 I/O 多路復(fù)用函數(shù)庫(kù)來(lái)作為 Redis 的 I/O 多路復(fù)用程序的底層實(shí)現(xiàn):

  /* 包括此系統(tǒng)支持的最佳復(fù)用層。
   * 以下應(yīng)按性能降序排列。 */
  #ifdef HAVE_EVPORT
  #include "ae_evport.c"
  #else
      #ifdef HAVE_EPOLL
      #include "ae_epoll.c"
      #else
          #ifdef HAVE_KQUEUE
         #include "ae_kqueue.c"
         #else
         #include "ae_select.c"
         #endif
     #endif
 #endif

【4】事件的類(lèi)型:I/O 多路復(fù)用程序可以監(jiān)聽(tīng)多個(gè)套接字的 ae.h/AE_READABLE 事件和 ae.h/AE_WRITABLE 事件, 這兩類(lèi)事件和套接字操作之間的對(duì)應(yīng)關(guān)系如下:

  • 當(dāng)套接字變得可讀時(shí)(客戶(hù)端對(duì)套接字執(zhí)行 write 操作,或者執(zhí)行 close 操作), 或者有新的可應(yīng)答(acceptable)套接字出現(xiàn)時(shí)(客戶(hù)端對(duì)服務(wù)器的監(jiān)聽(tīng)套接字執(zhí)行 connect 操作), 套接字產(chǎn)生 AE_READABLE 事件。
  • 當(dāng)套接字變得可寫(xiě)時(shí)(客戶(hù)端對(duì)套接字執(zhí)行 read 操作), 套接字產(chǎn)生 AE_WRITABLE 事件。

I/O 多路復(fù)用程序允許服務(wù)器同時(shí)監(jiān)聽(tīng)套接字的 AE_READABLE 事件和 AE_WRITABLE 事件, 如果一個(gè)套接字同時(shí)產(chǎn)生了這兩種事件, 那么文件事件分派器會(huì)優(yōu)先處理 AE_READABLE 事件, 等到 AE_READABLE 事件處理完之后, 才處理 AE_WRITABLE 事件。這也就是說(shuō), 如果一個(gè)套接字又可讀又可寫(xiě)的話(huà), 那么服務(wù)器將先讀套接字, 后寫(xiě)套接字。

【5】APIae.c/aeCreateFileEvent 函數(shù)接收一個(gè)套接字描述符、 一個(gè)事件類(lèi)型、 以及一個(gè)事件處理器作為參數(shù), 將給定套接字的給定事件加入到 I/O 多路復(fù)用程序的監(jiān)聽(tīng)范圍之內(nèi), 并對(duì)事件和事件處理器進(jìn)行關(guān)聯(lián)。ae.c/aeDeleteFileEvent 函數(shù)接收一個(gè)套接字描述符和一個(gè)監(jiān)聽(tīng)事件類(lèi)型作為參數(shù), 讓 I/O 多路復(fù)用程序取消對(duì)給定套接字的給定事件的監(jiān)聽(tīng), 并取消事件和事件處理器之間的關(guān)聯(lián)。ae.c/aeGetFileEvents 函數(shù)接收一個(gè)套接字描述符, 返回該套接字正在被監(jiān)聽(tīng)的事件類(lèi)型:

  • 如果套接字沒(méi)有任何事件被監(jiān)聽(tīng), 那么函數(shù)返回 AE_NONE ;
  • 如果套接字的讀事件正在被監(jiān)聽(tīng), 那么函數(shù)返回 AE_READABLE ;
  • 如果套接字的寫(xiě)事件正在被監(jiān)聽(tīng), 那么函數(shù)返回 AE_WRITABLE ;
  • 如果套接字的讀事件和寫(xiě)事件正在被監(jiān)聽(tīng), 那么函數(shù)返回 AE_READABLE | AE_WRITABLE ;

ae.c/aeWait 函數(shù)接受一個(gè)套接字描述符、一個(gè)事件類(lèi)型和一個(gè)毫秒數(shù)為參數(shù), 在給定的時(shí)間內(nèi)阻塞并等待套接字的給定類(lèi)型事件產(chǎn)生, 當(dāng)事件成功產(chǎn)生, 或者等待超時(shí)之后, 函數(shù)返回。
 

ae.c/aeApiPoll 函數(shù)接受一個(gè) sys/time.h/struct timeval 結(jié)構(gòu)為參數(shù), 并在指定的時(shí)間內(nèi), 阻塞并等待所有被 aeCreateFileEvent 函數(shù)設(shè)置為監(jiān)聽(tīng)狀態(tài)的套接字產(chǎn)生文件事件, 當(dāng)有至少一個(gè)事件產(chǎn)生, 或者等待超時(shí)后, 函數(shù)返回。
ae.c/aeProcessEvents 函數(shù)是文件事件分派器, 它先調(diào)用 aeApiPoll 函數(shù)來(lái)等待事件產(chǎn)生, 然后遍歷所有已產(chǎn)生的事件, 并調(diào)用相應(yīng)的事件處理器來(lái)處理這些事件。
 

ae.c/aeGetApiName 函數(shù)返回 I/O 多路復(fù)用程序底層所使用的 I/O 多路復(fù)用函數(shù)庫(kù)的名稱(chēng): 返回 "epoll" 表示底層為 epoll 函數(shù)庫(kù), 返回"select" 表示底層為 select 函數(shù)庫(kù), 諸如此類(lèi)。

【6】文件事件的處理器:Redis 為文件事件編寫(xiě)了多個(gè)處理器, 這些事件處理器分別用于實(shí)現(xiàn)不同的網(wǎng)絡(luò)通訊需求, 比如:

  • 為了對(duì)連接服務(wù)器的各個(gè)客戶(hù)端進(jìn)行應(yīng)答, 服務(wù)器要為監(jiān)聽(tīng)套接字關(guān)聯(lián)連接應(yīng)答處理器;
  • 為了接收客戶(hù)端傳來(lái)的命令請(qǐng)求, 服務(wù)器要為客戶(hù)端套接字關(guān)聯(lián)命令請(qǐng)求處理器;
  • 為了向客戶(hù)端返回命令的執(zhí)行結(jié)果, 服務(wù)器要為客戶(hù)端套接字關(guān)聯(lián)命令回復(fù)處理器;
  • 當(dāng)主服務(wù)器和從服務(wù)器進(jìn)行復(fù)制操作時(shí), 主從服務(wù)器都需要關(guān)聯(lián)特別為復(fù)制功能編寫(xiě)的復(fù)制處理器;

在這些事件處理器里面, 服務(wù)器最常用的要數(shù)與客戶(hù)端進(jìn)行通信的連接應(yīng)答處理器、 命令請(qǐng)求處理器和命令回復(fù)處理器。

【7】連接應(yīng)答處理器:networking.c/acceptTcpHandler 函數(shù)是 Redis 的連接應(yīng)答處理器, 這個(gè)處理器用于對(duì)連接服務(wù)器監(jiān)聽(tīng)套接字的客戶(hù)端進(jìn)行應(yīng)答, 具體實(shí)現(xiàn)為sys/socket.h/accept 函數(shù)的包裝。當(dāng) Redis 服務(wù)器進(jìn)行初始化的時(shí)候, 程序會(huì)將這個(gè)連接應(yīng)答處理器和服務(wù)器監(jiān)聽(tīng)套接字的 AE_READABLE 事件關(guān)聯(lián)起來(lái), 當(dāng)有客戶(hù)端用sys/socket.h/connect 函數(shù)連接服務(wù)器監(jiān)聽(tīng)套接字的時(shí)候, 套接字就會(huì)產(chǎn)生 AE_READABLE 事件, 引發(fā)連接應(yīng)答處理器執(zhí)行, 并執(zhí)行相應(yīng)的套接字應(yīng)答操作, 如圖 IMAGE_SERVER_ACCEPT_CONNECT 所示。

img

【8】命令請(qǐng)求處理器:networking.c/readQueryFromClient 函數(shù)是 Redis 的命令請(qǐng)求處理器, 這個(gè)處理器負(fù)責(zé)從套接字中讀入客戶(hù)端發(fā)送的命令請(qǐng)求內(nèi)容, 具體實(shí)現(xiàn)為 unistd.h/read 函數(shù)的包裝。當(dāng)一個(gè)客戶(hù)端通過(guò)連接應(yīng)答處理器成功連接到服務(wù)器之后, 服務(wù)器會(huì)將客戶(hù)端套接字的 AE_READABLE 事件和命令請(qǐng)求處理器關(guān)聯(lián)起來(lái), 當(dāng)客戶(hù)端向服務(wù)器發(fā)送命令請(qǐng)求的時(shí)候, 套接字就會(huì)產(chǎn)生 AE_READABLE 事件, 引發(fā)命令請(qǐng)求處理器執(zhí)行, 并執(zhí)行相應(yīng)的套接字讀入操作, 如圖 IMAGE_SERVER_RECIVE_COMMAND_REQUEST 所示。

img

當(dāng)命令回復(fù)發(fā)送完畢之后, 服務(wù)器就會(huì)解除命令回復(fù)處理器與客戶(hù)端套接字的 AE_WRITABLE 事件之間的關(guān)聯(lián)。

三、客戶(hù)端與 redis 的一次通信過(guò)程

img

【1】客戶(hù)端 socket01 向 redis 的 server socket 請(qǐng)求建立連接,此時(shí) server socket 會(huì)產(chǎn)生一個(gè) AE_READABLE 事件,IO 多路復(fù)用程序監(jiān)聽(tīng)到 server socket 產(chǎn)生的事件后,將該事件壓入隊(duì)列中。文件事件分派器從隊(duì)列中獲取該事件,交給連接應(yīng)答處理器。連接應(yīng)答處理器會(huì)創(chuàng)建一個(gè)能與客戶(hù)端通信的 socket01,并將該 socket01 的 AE_READABLE 事件與命令請(qǐng)求處理器關(guān)聯(lián)。

【2】假設(shè)此時(shí)客戶(hù)端發(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)求處理器來(lái)處理。命令請(qǐng)求處理器讀取 socket01 的 key value 并在自己內(nèi)存中完成 key value 的設(shè)置。操作完成后,它會(huì)將 socket01 的 AE_WRITABLE 事件與命令回復(fù)處理器關(guān)聯(lián)。

【3】如果此時(shí)客戶(hù)端準(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 單線(xiàn)程模型也能效率這么高

  • 純內(nèi)存操作
  • 核心是基于非阻塞的 IO多路復(fù)用機(jī)制
  • 單線(xiàn)程反而避免了多線(xiàn)程的頻繁上下文切換問(wèn)題

到此這篇關(guān)于一文弄懂Redis 線(xiàn)程模型的文章就介紹到這了,更多相關(guān)Redis 線(xiàn)程模型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Redis中AOF與RDB持久化策略深入分析

    Redis中AOF與RDB持久化策略深入分析

    Redis作為一款內(nèi)存數(shù)據(jù)庫(kù),因?yàn)槭莾?nèi)存讀寫(xiě),所以性能很強(qiáng),但內(nèi)存存儲(chǔ)是易失性的,斷電或系統(tǒng)奔潰都會(huì)導(dǎo)致數(shù)據(jù)丟失,因此Redis也需要將其數(shù)據(jù)持久化到磁盤(pán)上面,當(dāng)Redis服務(wù)重啟時(shí),會(huì)把磁盤(pán)上的數(shù)據(jù)再加載進(jìn)內(nèi)存,Redis提供了兩種持久化機(jī)制-RDB快照和AOF日志
    2022-11-11
  • 一文帶你了解Redis怎么啟動(dòng)以及使用

    一文帶你了解Redis怎么啟動(dòng)以及使用

    對(duì)于Redis我們一般會(huì)使用到三種啟動(dòng)方式:直接啟動(dòng)、指定配置文件啟動(dòng)、開(kāi)機(jī)自啟動(dòng),下面這篇文章主要給大家介紹了關(guān)于Redis怎么啟動(dòng)以及使用的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率的示例

    Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率的示例

    限流就是限制API訪(fǎng)問(wèn)頻率,當(dāng)訪(fǎng)問(wèn)頻率超過(guò)某個(gè)閾值時(shí)進(jìn)行拒絕訪(fǎng)問(wèn)等操作,本文主要介紹了Redis和Nginx實(shí)現(xiàn)限制接口請(qǐng)求頻率的示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 淺談Redis緩存有哪些淘汰策略

    淺談Redis緩存有哪些淘汰策略

    redis用做緩存是一種非常常見(jiàn)的手段,然而由于內(nèi)存大小的限制,會(huì)導(dǎo)致redis在內(nèi)存空間滿(mǎn)了以后需要處理繼續(xù)存入的數(shù)據(jù),所以就需要淘汰策略,本文就詳細(xì)的介紹一下
    2021-08-08
  • 詳解Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表

    詳解Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表

    這篇文章主要介紹了Redis數(shù)據(jù)結(jié)構(gòu)中的跳躍表的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • redis?key鍵過(guò)期刪除策略及淘汰機(jī)制探究

    redis?key鍵過(guò)期刪除策略及淘汰機(jī)制探究

    這篇文章主要為大家介紹了redis?key鍵過(guò)期刪除策略及淘汰機(jī)制探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 在Centos?8.0中安裝Redis服務(wù)器的教程詳解

    在Centos?8.0中安裝Redis服務(wù)器的教程詳解

    由于考慮到linux服務(wù)器的性能,所以經(jīng)常需要把一些中間件安裝在linux服務(wù)上,今天通過(guò)本文給大家介紹下在Centos?8.0中安裝Redis服務(wù)器的詳細(xì)過(guò)程,感興趣的朋友一起看看吧
    2022-03-03
  • 配置Redis序列化方式不生效問(wèn)題及解決

    配置Redis序列化方式不生效問(wèn)題及解決

    這篇文章主要介紹了配置Redis序列化方式不生效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 如何提高Redis服務(wù)器的最大打開(kāi)文件數(shù)限制

    如何提高Redis服務(wù)器的最大打開(kāi)文件數(shù)限制

    文章討論了如何提高Redis服務(wù)器的最大打開(kāi)文件數(shù)限制,以支持高并發(fā)服務(wù),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • Windows中redis設(shè)置密碼的兩種方法

    Windows中redis設(shè)置密碼的兩種方法

    之前寫(xiě)的一個(gè)項(xiàng)目,有項(xiàng)目代碼,有數(shù)據(jù)庫(kù),但是本地沒(méi)redis,沒(méi)法跑此項(xiàng)目,故思考在本地安裝一個(gè)redis做登錄session存儲(chǔ),所以開(kāi)始動(dòng)手實(shí)踐,下面這篇文章主要給大家介紹了關(guān)于Windows中redis設(shè)置密碼的兩種方法,需要的朋友可以參考下
    2023-04-04

最新評(píng)論