婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Redis學習教程之命令的執(zhí)行過程詳解

Redis學習教程之命令的執(zhí)行過程詳解

熱門標簽:小紅書怎么地圖標注店 地圖標注如何即時生效 地圖標注費用 竹間科技AI電銷機器人 玄武湖地圖標注 太原營銷外呼系統(tǒng) 百度商家地圖標注怎么做 最簡單的百度地圖標注 西藏教育智能外呼系統(tǒng)價格

前言

之前寫了一系列文章,已經(jīng)很深入的探討了 Redis 的數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)庫的實現(xiàn),key的過期策略以及 Redis 是怎么處理事件的。所以距離 Redis 的單機實現(xiàn)只差最后一步了,就是 Redis 是怎么處理 client 發(fā)來的命令并返回結(jié)果的,所以我們就仔細討論一下 Redis 是怎么執(zhí)行命令的。

閱讀這篇文章你將會了解到:

  • Redis 是怎么執(zhí)行遠程客戶端發(fā)來的命令的

Redis client(客戶端)

Redis 是單線程應(yīng)用,它是如何與多個客戶端簡歷網(wǎng)絡(luò)鏈接并處理命令的?
由于 Redis 是基于 I/O 多路復用技術(shù),為了能夠處理多個客戶端的請求,Redis 在本地為每一個鏈接到 Redis 服務(wù)器的客戶端創(chuàng)建了一個 redisClient 的數(shù)據(jù)結(jié)構(gòu),這個數(shù)據(jù)結(jié)構(gòu)包含了每個客戶端各自的狀態(tài)和執(zhí)行的命令。 Redis 服務(wù)器使用一個鏈表來維護多個 redisClient 數(shù)據(jù)結(jié)構(gòu)。

在服務(wù)器端用一個鏈表來管理所有的 redisClient。

struct redisServer {
 //...
 list *clients;  /* List of active clients */
 //...
}

所以我就看看 redisClient 包含的數(shù)據(jù)結(jié)構(gòu)和重要參數(shù):

typedef struct redisClient {

 // 客戶端狀態(tài)標志
 int flags;  /* REDIS_SLAVE | REDIS_MONITOR | REDIS_MULTI ... */
 
 // 套接字描述符
 int fd;

 // 當前正在使用的數(shù)據(jù)庫
 redisDb *db;

 // 當前正在使用的數(shù)據(jù)庫的 id (號碼)
 int dictid;

 // 客戶端的名字
 robj *name;  /* As set by CLIENT SETNAME */

 // 查詢緩沖區(qū)
 sds querybuf;

 // 查詢緩沖區(qū)長度峰值
 size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size */

 // 參數(shù)數(shù)量
 int argc;

 // 參數(shù)對象數(shù)組
 robj **argv;

 // 記錄被客戶端執(zhí)行的命令
 struct redisCommand *cmd, *lastcmd;

 // 請求的類型:內(nèi)聯(lián)命令還是多條命令
 int reqtype;

 // 剩余未讀取的命令內(nèi)容數(shù)量
 int multibulklen; /* number of multi bulk arguments left to read */

 // 命令內(nèi)容的長度
 long bulklen;  /* length of bulk argument in multi bulk request */

 // 回復鏈表
 list *reply;

 // 回復鏈表中對象的總大小
 unsigned long reply_bytes; /* Tot bytes of objects in reply list */

 // 已發(fā)送字節(jié),處理 short write 用
 int sentlen;  /* Amount of bytes already sent in the current
    buffer or object being sent. */

 // 回復偏移量
 int bufpos;
 // 回復緩沖區(qū)
 char buf[REDIS_REPLY_CHUNK_BYTES];
 // ...
}

這里需要特別的注意,redisClient 并非指遠程的客戶端,而是一個 Redis 服務(wù)本地的數(shù)據(jù)結(jié)構(gòu),我們可以理解這個 redisClient 是遠程客戶端的一個映射或者代理。

flags

flags 表示了目前客戶端的角色,以及目前所處的狀態(tài)。他比較特殊可以單獨表示一個狀態(tài)或者多個狀態(tài)。

querybuf

querybuf 是一個 sds 動態(tài)字符串類型,所謂 buf 說明是它只是一個緩沖區(qū),用于存儲沒有被解析的命令。

argc argv

上文的 querybuf 是一個沒有處理過的命令,當 Redis 將 querybuf 命令解析以后,會將得出的參數(shù)個數(shù)和以及參數(shù)分別保存在 argc 和 argv 中。argv 是一個 redisObject 的數(shù)組。

cmd

Redis 使用一個字典保存了所有的 redisCommand。key 是 redisCommand 的名字,值就是一個 redisCommand 結(jié)構(gòu),這個結(jié)構(gòu)保存了命令的實現(xiàn)函數(shù),命令的標志,命令應(yīng)該給定的參數(shù)個數(shù),命令的執(zhí)行次數(shù)和總消耗時長等統(tǒng)計信息,cmd 是一個 redisCommand。

當 Redis 解析出 argv 和 argc 后,會根據(jù)數(shù)組 argv[0],到字典中查詢出對應(yīng)的 redisCommand。上文的例子中 Redis 就會去字典去查找 SET 這個命令對應(yīng)的 redisCommand。redis 會執(zhí)行 redisCommand 中命令的實現(xiàn)函數(shù)。

buf bufpos reply

buf 是一個長度為 REDIS_REPLY_CHUNK_BYTES 的數(shù)組。Redis 執(zhí)行相應(yīng)的操作以后,就會將需要返回的返回的數(shù)據(jù)存儲到 buf 中,bufpos 用于記錄 buf 中已用的字節(jié)數(shù)數(shù)量,當需要恢復的數(shù)據(jù)大于 REDIS_REPLY_CHUNK_BYTES 時,redis 就會是用 reply 這個鏈表來保存數(shù)據(jù)。

其他參數(shù)

其他參數(shù)大家看注釋就能明白,就是字面的意思。省略的參數(shù)基本上涉及 Redis 集群管理的參數(shù),在之后的文章中會繼續(xù)講解。

客戶端的鏈接和斷開

上文說過 redisServer 是用一個鏈表來維護所有的 redisClient 狀態(tài),每當有一個客戶端發(fā)起鏈接以后,就會在 Redis 中生成一個對應(yīng)的 redisClient 數(shù)據(jù)結(jié)構(gòu),增加到clients這個鏈表之后。

一個客戶端很可能被多種原因斷開。

總體分為幾種類型:

  • 客戶端主動退出或者被 kill。
  • timeout 超時。
  • Redis 為了自我保護,會斷開發(fā)的數(shù)據(jù)超過限制大小的客戶端。
  • Redis 為了自我保護,會斷需要返回的數(shù)據(jù)超過限制大小的客戶端。

調(diào)用總結(jié)

當客戶端和服務(wù)器端的嵌套字變得可讀的時候,服務(wù)器將會調(diào)用命令請求處理器來執(zhí)行以下操作:

  1. 讀取嵌套字中的數(shù)據(jù),寫入 querybuf。
  2. 解析 querybuf 中的命令,記錄到 argc 和 argv 中。
  3. 根據(jù) argv[0] 查找對應(yīng)的 recommand。
  4. 執(zhí)行 recommand 對應(yīng)的實現(xiàn)函數(shù)。
  5. 執(zhí)行以后將結(jié)果存入 buf bufpos reply 中,返回給調(diào)用方。

Redis Server (服務(wù)端)

上文是從 redisClient 的角度來觀察命令的執(zhí)行,文章接下來的部分將會從 Redis 的代碼層面,微觀的觀察 Redis 是怎么實現(xiàn)命令的執(zhí)行的。

redisServer 的啟動

在了解redisServer 的工作機制的工作機制之前,需要了解 redisServer 的啟動做了什么:

可以繼續(xù)觀察 Redis 的 main() 函數(shù)。

int main(int argc, char **argv) {
 //...
 // 創(chuàng)建并初始化服務(wù)器數(shù)據(jù)結(jié)構(gòu)
 initServer();
 //...
}

我們只關(guān)注 initServer() 這個函數(shù),他負責初始化服務(wù)器的數(shù)據(jù)結(jié)構(gòu)。繼續(xù)跟蹤代碼:

void initServer() {
 //...
 //創(chuàng)建eventLoop
 server.el = aeCreateEventLoop(server.maxclients+REDIS_EVENTLOOP_FDSET_INCR);
 /* Create an event handler for accepting new connections in TCP and Unix
 * domain sockets. */
 // 為 TCP 連接關(guān)聯(lián)連接應(yīng)答(accept)處理器
 // 用于接受并應(yīng)答客戶端的 connect() 調(diào)用
 for (j = 0; j  server.ipfd_count; j++) {
 if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,
  acceptTcpHandler,NULL) == AE_ERR)
  {
  redisPanic(
   "Unrecoverable error creating server.ipfd file event.");
  }
 }

 // 為本地套接字關(guān)聯(lián)應(yīng)答處理器
 if (server.sofd > 0  aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
 acceptUnixHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.sofd file event.");
 //...
}

篇幅限制,我們省略了很多與本編文章無關(guān)的代碼,保留了核心邏輯代碼。

在上一篇文章中 《Redis 中的事件驅(qū)動模型》 我們講解過,redis 使用不同的事件處理器,處理不同的事件。

在這段代碼里面:

  • 初始化了事件處理器的 eventLoop
  • 向 eventLoop 中注冊了兩個事件處理器 acceptTcpHandler 和 acceptUnixHandler,分別處理遠程的鏈接和本地鏈接。

redisClient 的創(chuàng)建

當有一個遠程客戶端連接到 Redis 的服務(wù)器,會觸發(fā) acceptTcpHandler 事件處理器.

acceptTcpHandler 事件處理器,會創(chuàng)建一個鏈接。然后繼續(xù)調(diào)用 acceptCommonHandler。

acceptCommonHandler 事件處理器的作用是:

  • 調(diào)用 createClient() 方法創(chuàng)建 redisClient
  • 檢查已經(jīng)創(chuàng)建的 redisClient 是否超過 server 允許的數(shù)量的上限
  • 如果超過上限就拒絕遠程連接
  • 否則創(chuàng)建 redisClient 創(chuàng)建成功
  • 并更新連接的統(tǒng)計次數(shù),更新 redisClinet 的 flags 字段

這個時候 Redis 在服務(wù)端創(chuàng)建了 redisClient 數(shù)據(jù)結(jié)構(gòu),這個時候遠程的客戶端就在 redisServer 中創(chuàng)建了一個代理。遠程的客戶端就與 Redis 服務(wù)器建立了聯(lián)系,就可以向服務(wù)器發(fā)送命令了。

處理命令

在 createClient() 行數(shù)中:

// 綁定讀事件到事件 loop (開始接收命令請求)
if (aeCreateFileEvent(server.el,fd,AE_READABLE,readQueryFromClient, c) == AE_ERR)

向 eventLoop 中注冊了 readQueryFromClient。 readQueryFromClient 的作用就是從client中讀取客戶端的查詢緩沖區(qū)內(nèi)容。

然后調(diào)用函數(shù) processInputBuffer 來處理客戶端的請求。在 processInputBuffer 中有幾個核心函數(shù):

  • processInlineBuffer 和 processMultibulkBuffer 解析 querybuf 中的命令,記錄到 argc 和 argv 中。
  • processCommand 根據(jù) argv[0] 查找對應(yīng)的 recommen,執(zhí)行 recommend 對應(yīng)的執(zhí)行函數(shù)。在執(zhí)行之前還會驗證命令的正確性。將結(jié)果存入 buf bufpos reply 中

返回數(shù)據(jù)

萬事具備了,執(zhí)行完了命令就需要把數(shù)據(jù)返回給遠程的調(diào)用方。調(diào)用鏈如下

processCommand -> addReply -> prepareClientToWrite

在 prepareClientToWrite 中我們有見到了熟悉的代碼:

aeCreateFileEvent(server.el, c->fd, AE_WRITABLE,sendReplyToClient, c) == AE_ERR) return REDIS_ERR;

向 eventloop 綁定了 sendReplyToClient 事件處理器。

在 sendReplyToClient 中觀察代碼發(fā)現(xiàn),如果 bufpos 大于 0,將會把 buf 發(fā)送給遠程的客戶端,如果鏈表 reply 的長度大于0,就會將遍歷鏈表 reply,發(fā)送給遠程的客戶端,這里需要注意的是,為了避免 reply 數(shù)據(jù)量過大,就會過度的占用資源引起 Redis 相應(yīng)慢。為了解決這個問題,當寫入的總數(shù)量大于 REDIS_MAX_WRITE_PER_EVENT 時,Redis 將會臨時中斷寫入,記錄操作的進度,將處理時間讓給其他操作,剩余的內(nèi)容等下次繼續(xù)。這樣的套路我們一路走來看過太多了。

總結(jié)

  1. 遠程客戶端連接到 redis 后,redis服務(wù)端會為遠程客戶端創(chuàng)建一個 redisClient 作為代理。
  2. redis 會讀取嵌套字中的數(shù)據(jù),寫入 querybuf 中。
  3. 解析 querybuf 中的命令,記錄到 argc 和 argv 中。
  4. 根據(jù) argv[0] 查找對應(yīng)的 recommand。
  5. 執(zhí)行 recommend 對應(yīng)的執(zhí)行函數(shù)。
  6. 執(zhí)行以后將結(jié)果存入 buf bufpos reply 中。
  7. 返回給調(diào)用方。返回數(shù)據(jù)的時候,會控制寫入數(shù)據(jù)量的大小,如果過大會分成若干次。保證 redis 的相應(yīng)時間。

Redis 作為單線程應(yīng)用,一直貫徹的思想就是,每個步驟的執(zhí)行都有一個上限(包括執(zhí)行時間的上限或者文件尺寸的上限)一旦達到上限,就會記錄下當前的執(zhí)行進度,下次再執(zhí)行。保證了 Redis 能夠及時響應(yīng)不發(fā)生阻塞。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • 利用yum安裝Redis的方法詳解
  • Redis中scan命令的深入講解
  • Redis不使用 keys 命令獲取鍵值信息的方法
  • redis禁止幾個危險命令的方法
  • 詳解centos7 yum安裝redis及常用命令

標簽:揚州 贛州 澳門 唐山 林芝 香港 廣東 景德鎮(zhèn)

巨人網(wǎng)絡(luò)通訊聲明:本文標題《Redis學習教程之命令的執(zhí)行過程詳解》,本文關(guān)鍵詞  Redis,學習教程,之,命令,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Redis學習教程之命令的執(zhí)行過程詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于Redis學習教程之命令的執(zhí)行過程詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    久久99国内精品| 午夜精品123| 欧美日韩在线免费视频| 99精品久久免费看蜜臀剧情介绍| 色噜噜久久综合| 狠狠色丁香久久婷婷综合_中| 亚洲国产成人高清精品| 一区二区在线观看不卡| 午夜私人影院久久久久| 日韩高清不卡一区二区三区| 亚洲成人在线免费| 男女男精品网站| 国产成人在线视频播放| 91美女在线看| 久久嫩草精品久久久精品一| 国产精品免费看片| 偷窥国产亚洲免费视频| 国产美女在线精品| 99精品欧美一区| 精品剧情在线观看| 一区二区不卡在线播放| 久久99国产乱子伦精品免费| 99久久精品99国产精品| 91麻豆精品国产91久久久使用方法 | 一区二区三区日韩| 精品在线亚洲视频| 免费成人美女在线观看.| 国产经典欧美精品| 欧美日韩一区视频| 久久在线免费观看| 丁香网亚洲国际| 国产成人精品一区二区三区四区| 婷婷综合久久一区二区三区| 国产精品理论在线观看| 亚洲美女区一区| 国产盗摄视频一区二区三区| 欧美男男青年gay1069videost| 日韩欧美一二区| 婷婷成人综合网| 午夜视频在线观看一区二区 | 中文字幕一区日韩精品欧美| 五月天中文字幕一区二区| 91麻豆蜜桃一区二区三区| 日本一区二区三区dvd视频在线| 亚洲综合区在线| av综合在线播放| 中文字幕一区二区三区色视频| 黄色日韩三级电影| 欧美精品一区二区三区视频| 美女脱光内衣内裤视频久久网站 | 亚洲欧美日韩国产综合在线| 国产成人av一区二区三区在线| 久久久久久电影| av中文字幕亚洲| 午夜精品福利在线| 在线不卡中文字幕| 国产在线视频精品一区| 1024国产精品| 69精品人人人人| 亚洲国产色一区| 3d成人动漫网站| 成人动漫一区二区| 亚洲成人一区二区| 国产精品网站导航| 91精品国产综合久久久久久| 国产成人自拍网| 日韩国产在线一| 樱桃国产成人精品视频| 国产欧美一区二区三区在线老狼| 99久久久久久99| 国产精品资源站在线| 亚洲国产欧美在线人成| 国产日本亚洲高清| 精品久久久三级丝袜| 欧美日韩不卡一区二区| 99v久久综合狠狠综合久久| 国产传媒一区在线| 久久国产福利国产秒拍| 亚洲一区二区黄色| 亚洲国产综合91精品麻豆| 综合在线观看色| 亚洲久草在线视频| 亚洲精品你懂的| 一个色妞综合视频在线观看| 国产午夜久久久久| 国产蜜臀av在线一区二区三区| 久久综合色天天久久综合图片| 51精品视频一区二区三区| 欧美日免费三级在线| 777xxx欧美| 久久九九全国免费| 国产精品久久久久影院| 亚洲人成网站色在线观看| 18成人在线观看| 美日韩一区二区| 国产精选一区二区三区| 91污在线观看| 精品对白一区国产伦| 国产欧美精品一区aⅴ影院| 一区二区在线观看视频| 蜜臀av性久久久久蜜臀aⅴ流畅| 韩国av一区二区三区在线观看 | 久久超级碰视频| 懂色av一区二区三区蜜臀| 99免费精品视频| 国产婷婷色一区二区三区四区| 成人欧美一区二区三区视频网页| 午夜久久久久久久久| 丰满白嫩尤物一区二区| 欧美日韩一区不卡| 亚洲欧美自拍偷拍色图| 日本视频在线一区| 一本久久精品一区二区| 久久蜜桃香蕉精品一区二区三区| 亚洲综合图片区| 色综合天天综合色综合av| 久久久久国产精品厨房| 亚洲第一会所有码转帖| 色婷婷综合久久| 成人免费视频在线观看| 国产毛片精品国产一区二区三区| 欧美色综合网站| 午夜在线电影亚洲一区| 91久久奴性调教| 亚洲电影一级片| 欧美一卡二卡三卡| 日日噜噜夜夜狠狠视频欧美人| 99re热这里只有精品免费视频| 日韩欧美电影一区| 日韩在线一二三区| 欧美午夜寂寞影院| 午夜国产精品一区| 欧美日韩成人综合天天影院| 日本一区二区三区dvd视频在线| 亚洲成人一区二区在线观看| 欧美日韩精品三区| 久久精品噜噜噜成人88aⅴ| 精品乱人伦小说| 一本大道久久a久久精二百| 伊人性伊人情综合网| 日韩欧美电影一二三| 国产一区二区三区久久悠悠色av| 国产亚洲一区二区三区| 色综合天天在线| 麻豆精品精品国产自在97香蕉| 精品国产青草久久久久福利| www.欧美.com| 高清不卡一区二区在线| 久久精品国产99国产| 亚洲精品五月天| 国产精品护士白丝一区av| 日韩免费看的电影| 欧美麻豆精品久久久久久| 99久久国产综合色|国产精品| 精品一区二区在线观看| 天堂午夜影视日韩欧美一区二区| 亚洲国产精品成人久久综合一区| 91麻豆精品国产91久久久| 欧美亚洲国产bt| 在线这里只有精品| 91成人看片片| 欧美视频在线一区| 欧美午夜精品久久久| 91成人免费电影| 欧美在线观看视频在线| 91麻豆精品在线观看| 99久久精品免费| 欧美区一区二区三区| 正在播放亚洲一区| 欧美mv日韩mv国产网站| 欧美va亚洲va| 国产三级一区二区三区| 国产精品高清亚洲| 国产精品国产精品国产专区不蜜| 亚洲国产岛国毛片在线| 中文字幕日本不卡| 亚洲午夜激情av| 麻豆久久一区二区| 东方欧美亚洲色图在线| 欧美最猛性xxxxx直播| 精品理论电影在线| 亚洲电影视频在线| 欧美嫩在线观看| 成人精品国产免费网站| 午夜一区二区三区在线观看| 91国内精品野花午夜精品| 性久久久久久久久久久久| 亚洲精品一区二区三区蜜桃下载 | 在线观看www91| 国产精品沙发午睡系列990531| 国产精品亲子伦对白| 亚洲视频一区二区在线观看| 三级久久三级久久久| 国产福利电影一区二区三区| 91黄色免费版| 国产人成一区二区三区影院| 亚洲无线码一区二区三区| 成人晚上爱看视频| 精品日韩欧美在线| 欧美精品777|