日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis——命令请求的执行过程

發布時間:2023/12/13 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis——命令请求的执行过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

發送命令請求

當用戶在客戶端中鍵入一個命令請求時, 客戶端會將這個命令請求轉換成協議格式, 然后通過連接到服務器的套接字, 將協議格式的命令請求發送給服務器。

讀取命令請求

當客戶端與服務器之間的連接套接字因為客戶端的寫入而變得可讀時, 服務器將調用命令請求處理器來執行以下操作:

  • 讀取套接字中協議格式的命令請求, 并將其保存到客戶端狀態的輸入緩沖區里面。
  • 對輸入緩沖區中的命令請求進行分析, 提取出命令請求中包含的命令參數, 以及命令參數的個數, 然后分別將參數和參數個數保存到客戶端狀態的?argv?屬性和?argc?屬性里面。
  • 調用命令執行器, 執行客戶端指定的命令。
  • 命令執行器:查找命令實現

    命令執行器要做的第一件事就是根據客戶端狀態的?argv[0]?參數, 在命令表(command table)中查找參數所指定的命令, 并將找到的命令保存到客戶端狀態的?cmd?屬性里面。

    命令表是一個字典, 字典的鍵是一個個命令名字,比如?"set"?、?"get"?、?"del"?,等等; 而字典的值是一個個?redisCommand?結構, 每個?redisCommand?結構記錄了一個 Redis 命令的實現信息。

    命令名字的大小寫不影響命令表的查找結果

    因為命令表使用的是大小寫無關的查找算法, 無論輸入的命令名字是大寫、小寫或者混合大小寫, 只要命令的名字是正確的, 就能找到相應的 redisCommand 結構。

    比如說, 無論用戶輸入的命令名字是 "SET" 、 "set" 、 "SeT" 又或者 "sEt" , 命令表返回的都是同一個 redisCommand 結構。

    redis> SET msg "hello world" OKredis> set msg "hello world" OKredis> SeT msg "hello world" OKredis> sEt msg "hello world" OK

    命令執行器:執行預備操作

    到目前為止, 服務器已經將執行命令所需的命令實現函數(保存在客戶端狀態的?cmd?屬性)、參數(保存在客戶端狀態的?argv?屬性)、參數個數(保存在客戶端狀態的?argc?屬性)都收集齊了, 但是在真正執行命令之前, 程序還需要進行一些預備操作, 從而確保命令可以正確、順利地被執行, 這些操作包括:

    • 檢查客戶端狀態的?cmd?指針是否指向?NULL?, 如果是的話, 那么說明用戶輸入的命令名字找不到相應的命令實現, 服務器不再執行后續步驟, 并向客戶端返回一個錯誤。
    • 根據客戶端?cmd?屬性指向的?redisCommand?結構的?arity?屬性, 檢查命令請求所給定的參數個數是否正確, 當參數個數不正確時, 不再執行后續步驟, 直接向客戶端返回一個錯誤。 比如說, 如果?redisCommand?結構的?arity?屬性的值為?-3?, 那么用戶輸入的命令參數個數必須大于等于?3?個才行。
    • 檢查客戶端是否已經通過了身份驗證, 未通過身份驗證的客戶端只能執行?AUTH?命令, 如果未通過身份驗證的客戶端試圖執行除?AUTH?命令之外的其他命令, 那么服務器將向客戶端返回一個錯誤。
    • 如果服務器打開了?maxmemory?功能, 那么在執行命令之前, 先檢查服務器的內存占用情況, 并在有需要時進行內存回收, 從而使得接下來的命令可以順利執行。 如果內存回收失敗, 那么不再執行后續步驟, 向客戶端返回一個錯誤。
    • 如果服務器上一次執行?BGSAVE?命令時出錯, 并且服務器打開了?stop-writes-on-bgsave-error?功能, 而且服務器即將要執行的命令是一個寫命令, 那么服務器將拒絕執行這個命令, 并向客戶端返回一個錯誤。
    • 如果客戶端當前正在用?SUBSCRIBE?命令訂閱頻道, 或者正在用?PSUBSCRIBE?命令訂閱模式, 那么服務器只會執行客戶端發來的?SUBSCRIBE?、?PSUBSCRIBE?、?UNSUBSCRIBE?、?PUNSUBSCRIBE?四個命令, 其他別的命令都會被服務器拒絕。
    • 如果服務器正在進行數據載入, 那么客戶端發送的命令必須帶有?l?標識(比如?INFO?、?SHUTDOWN?、?PUBLISH?,等等)才會被服務器執行, 其他別的命令都會被服務器拒絕。
    • 如果服務器因為執行 Lua 腳本而超時并進入阻塞狀態, 那么服務器只會執行客戶端發來的?SHUTDOWN nosave?命令和?SCRIPT KILL?命令, 其他別的命令都會被服務器拒絕。
    • 如果客戶端正在執行事務, 那么服務器只會執行客戶端發來的?EXEC?、?DISCARD?、?MULTI?、?WATCH?四個命令, 其他命令都會被放進事務隊列中。
    • 如果服務器打開了監視器功能, 那么服務器會將要執行的命令和參數等信息發送給監視器。

    當完成了以上預備操作之后, 服務器就可以開始真正執行命令了。

    命令執行器:調用命令的實現函數

    在前面的操作中, 服務器已經將要執行命令的實現保存到了客戶端狀態的?cmd?屬性里面, 并將命令的參數和參數個數分別保存到了客戶端狀態的?argv?屬性和?argc?屬性里面, 當服務器決定要執行命令時, 它只要執行以下語句就可以了:

    // client 是指向客戶端狀態的指針client->cmd->proc(client);

    因為執行命令所需的實際參數都已經保存到客戶端狀態的?argv?屬性里面了, 所以命令的實現函數只需要一個指向客戶端狀態的指針作為參數即可。

    命令執行器:執行后續工作

    在執行完實現函數之后, 服務器還需要執行一些后續工作:

    • 如果服務器開啟了慢查詢日志功能, 那么慢查詢日志模塊會檢查是否需要為剛剛執行完的命令請求添加一條新的慢查詢日志。
    • 根據剛剛執行命令所耗費的時長, 更新被執行命令的?redisCommand?結構的?milliseconds?屬性, 并將命令的?redisCommand?結構的?calls?計數器的值增一。
    • 如果服務器開啟了 AOF 持久化功能, 那么 AOF 持久化模塊會將剛剛執行的命令請求寫入到 AOF 緩沖區里面。
    • 如果有其他從服務器正在復制當前這個服務器, 那么服務器會將剛剛執行的命令傳播給所有從服務器。

    當以上操作都執行完了之后, 服務器對于當前命令的執行到此就告一段落了, 之后服務器就可以繼續從文件事件處理器中取出并處理下一個命令請求了。

    將命令回復發送給客戶端

    前面說過, 命令實現函數會將命令回復保存到客戶端的輸出緩沖區里面, 并為客戶端的套接字關聯命令回復處理器, 當客戶端套接字變為可寫狀態時, 服務器就會執行命令回復處理器, 將保存在客戶端輸出緩沖區中的命令回復發送給客戶端。

    當命令回復發送完畢之后, 回復處理器會清空客戶端狀態的輸出緩沖區, 為處理下一個命令請求做好準備。

    客戶端接收并打印命令回復

    當客戶端接收到協議格式的命令回復之后, 它會將這些回復轉換成人類可讀的格式, 并打印給用戶觀看(假設使用的是 Redis 自帶的?客戶端)

    ?

    ?

    以上就是 Redis 客戶端和服務器執行命令請求的整個過程了。

    ?

    總結

    以上是生活随笔為你收集整理的redis——命令请求的执行过程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。