Redis學習筆記(十一) 伺服器

来源:https://www.cnblogs.com/xtt321/archive/2020/05/19/12920310.html
-Advertisement-
Play Games

Redis伺服器負責與多個客戶端建立網路通信,處理客戶端發送的命令請求,在資料庫中保存客戶端執行命令所產生的數據,並通過資源管理來維持伺服器自身的運轉。 命令請求過程(以set命令為例) 1、客戶端向伺服器發送命令請求 SET KEY VALUE。 Redis伺服器的命令請求來自於Redis客戶端, ...


Redis伺服器負責與多個客戶端建立網路通信,處理客戶端發送的命令請求,在資料庫中保存客戶端執行命令所產生的數據,並通過資源管理來維持伺服器自身的運轉。

 

命令請求過程(以set命令為例)

 

1、客戶端向伺服器發送命令請求 SET KEY VALUE。

 

Redis伺服器的命令請求來自於Redis客戶端,當用戶從客戶端鍵入一個命令請求時,客戶端會將這個命令命令請求請求轉換成協議格式,然後通過連接到伺服器的套接字,將協議格式的命令請求發送給伺服器。

 

 

 2、伺服器接收並處理客戶端發送來的命令請求 SET KEY VALUE,在資料庫中進行設置操作,並產生命令回覆OK。

讀取套接字中的協議格式命令請求,並將其保存在客戶端狀態的輸入緩衝區中。

對輸入緩衝區中的命令請求進行解析,提取出命令請求中包含的命令參數,以及命令參數的格式,分別將參數和參數個數保存到客戶端狀態的argv和argc屬性中

調用命令執行器,執行客戶端指定的命令。

命令執行器:

1、查找命令。2、執行預備操作。(檢查命令、命令參數、客戶端身份驗證、檢查伺服器記憶體占用情況、事務、伺服器狀態、是否監聽等)3、調用命令實現函數,產生命令回覆函數,保存在客戶端狀態的輸出緩存區4、執行後續工作:(慢查詢檢查記錄日誌;根據命令耗時更新redisCommand結構的milliseconds屬性、calls計數器加1;如果開啟了AOF,如果是寫命令則寫入到AOF緩衝區;如果有其他從伺服器正在複製當前的伺服器,那麼伺服器會將剛剛執行的命令傳播給所有從伺服器。)

3、伺服器將命令回覆OK發送為客戶端。

 

當客戶端套接字變為可寫狀態時,伺服器會執行命令回覆處理器,將保存在客戶端緩衝區的命令回覆發送給客戶端。

 

4、客戶端接收伺服器返回的命令回覆OK,並將這個回覆列印給用戶觀看。客戶端收到協議格式的命令回覆後,將其轉換為人類可讀的格式,並列印。

 

 

 

 

serverCron函數

 

 

Redis伺服器中的serverCron函數每100毫秒執行一次,這個函數負責管理伺服器的資源,並保持伺服器自身的良好運轉。

 

1、更新伺服器緩存時間,為減少系統調用獲取當前時間的次數,伺服器狀態中的unixtime和mstime屬性被用作當前時間的緩存:

struct redisServer{
    //保存了秒級精度的當前unix時間戳
    time_t unixtime;
    //保存了毫秒級精度的系統當前unix時間戳
    long long mstime;
    //預設每10秒更新一次事件緩存,用於計算鍵的空轉時間。
    unsigned lruclock:22
}

伺服器只會在列印日誌、更新伺服器LRU始終、決定是否執行持久化任務、計算伺服器上線時間這類對事件精度不高的功能上用;對於為鍵設置過期事件、添加慢日誌這種需要高精度事件的功能來說,伺服器還是會再次執行系統調用,從而獲得更準確的系統當前事件。

 

每個Redis對象都有一個lru屬性,這個lru屬性保存了對象最後一次被命令訪問的時間:

typedef struct redisObject{
    unsigned lru:22'
} robj;

serverCron函數中的trackOperationsPerSecond函數會以每100毫秒一次的頻率執行,這個函數的功能以抽樣計算的方式,估算並記錄伺服器在最近一秒鐘處理的命令請求數量,這個值通過INFO status命令的instantaneous_ops_per_sec域查看。

2、更新伺服器記憶體峰值記錄:伺服器狀態中的stat_peak_memory屬性記錄伺服器的記憶體峰值大小:

struct redisServer{
    //已使用記憶體峰值
    size_t stat_peak_memory;
}

3、處理sigterm信號

static void sigtermHandler(int sig){
    //列印日誌
    redisLogFromHandler(REDIS_WARNING,"received sigterm,scheduling shutdown...");
    //打開關閉標識
    server.shutdown_asap=1;
}
struct redisServer{
    //serverCron函數運行時,程式灰度伺服器狀態的shutdown_asap屬性進行檢查,並根據屬性值決定是否關閉伺服器。
    //關閉伺服器的標識
    //值為1時,關閉伺服器
    //值為0時,不做動作
    int shutdown_asap;
}

4、管理客戶端資源

serverCron函數每次執行都會調用clientCron函數,clientsCron函數會對一定數量的客戶端進行檢查:如果客戶端與伺服器之間的連接已經超時,那麼程式釋放這個客戶端;如果客戶端在上一次執行命令請求後,輸入緩衝區的大小超過了一定的長度,那麼程式會釋放客戶端當前的輸入緩衝區,重新創建一個迷人大小的輸入緩衝區,防止客戶端的輸入緩衝區耗費過多的資源。

5、管理資料庫資源 :刪除過期鍵,如有需要,對字典進行收縮操作。

6、執行被延遲的BGREWRITEAOF

如果BGSAVE執行期間,客戶端發來BGREWRITEAOF命令,則需要延遲到BGSAVE命令執行完成後。

7、檢查持久化操作運行狀態

伺服器狀態使用rdb_child_pid\aof_child_pid屬性記錄執行BGSAVe命令和BGREWRITEAOF命令的子進程ID,用於檢查命令是否正在執行

struct redisServer{
    //記錄執行BGSAVE命令的紫禁城,如果沒有執行則為-1
    pid_t rdb_child_pid;
    //記錄執行BGREWRITEAOF命令的子進程ID,沒執行則為-1
    pid_t aof_child_pid;
}

 

 

8、將AOF緩衝區中的內容寫入AOF文件

9、關閉非同步客戶端(檢查輸出緩衝區大小)

10、增加cronloops計數器的值(沒執行serverCron函數N次就執行一次指定的代碼)

 

初始化伺服器

 

1、初始化伺服器狀態結構,創建一個struct redisServer類型的實例變數server作為伺服器的狀態。

initServerConfig函數完成的主要工作:

設置伺服器運行ID

設置伺服器的預設運行頻率

設置伺服器的預設配置文件路徑

設置伺服器的運行架構

設置伺服器的預設埠號

設置伺服器預設RDB持久化條件和APF持久化條件

初始化伺服器LRU時鐘

創建命令表

2、載入配置項修改預設的配置。

3、初始化伺服器數據結構

在執行initServerConfig函數初始化server狀態時,程式只創建命令表一個數據結構,伺服器在次數初始化其他數據結構:

server.clients鏈表,記錄所有與伺服器相連接的客戶端狀態

erver.db數組,包含伺服器的所有資料庫。

保存頻道訂閱信息的server.pubsub_channels字典以及保存模式訂閱信息的server_publsub_patterns鏈表。

執行Lua腳本的Lua環境 server.lua;

用於保存慢查詢日誌的server.slwlog鏈表

除了初始化數據結構之外,initServer還進行了一些非常重要的設置操作:

為伺服器設置進程信號處理器。

創建共用對象。

打開伺服器的監聽端,並未監聽套接字關聯連接應答事件處理時,等待伺服器正式運行時接收客戶端連接。

為serverCron函數創建時間事件,等待伺服器正式運行時,執行serverCron函數。

如果AOF持久化功能打開,那麼打開現有的AOF文件,如果文件不存在則創建新的AOF文件

初始化伺服器的後臺I/O模塊,為將來的I/O操作做準備。

 

執行完以上內容那麼你就看到了熟悉的畫面:

 

 

4、還原資料庫裝填

在完成對伺服器狀態server變數的初始化後,伺服器需要載入RDB文件或者AOF文件,並根據文件記錄的內容還原資料庫狀態

5、執行事件迴圈

到此伺服器的初始化工作圓滿完成,伺服器現在開始可以接收客戶端的連接請求,並處理客戶端發來的命令請求。

 


 

寫到這裡,非常有衝動寫一下.net 程式初始化以及運行過程服務端做了那些事情,著手準備!


每天學一點,總會有收穫。

 

說明:尊重作者知識產權,文中內容參考《Redis設計與實現》,僅在此做學習與大家分享。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近看到vmlinux大神介紹了一款網路查看工具,感覺很好用,下麵進行簡要摘錄: iptraf-ng 可以方便查看當前伺服器網路狀況:CentOS 7.0,採用了衍生版本iptraf-ng 。 iptraf-ng -h usage: iptraf-ng [options] or: iptraf-ng ...
  • 1. 目的 簡化SSH登陸過程, 實現從機器A登陸機器B只需要運行 即可, 即不需要輸入用戶名和密碼。 2. 配置host 配置host的作用是ssh登陸機器時用hostname代替IP, 在機器很多的集群環境中hostname比IP容易記的多, 編輯 文件, 配置需要登陸的機器IP和hostnam ...
  • linux下c編程特點 typeof 取變數類型 GNU c對比ANSI c做了很多擴展,例如動態數組 第7章 Linux設備驅動中的併發控制 造成竟態的原因 多核 進程和中斷形成的多路徑(linux2.6以後,禁止了中斷嵌套) 編譯亂序 執行亂序 解決竟態的辦法 中斷屏蔽:只能屏蔽本核的 原子操作 ...
  • 1、重啟tomcat 使用命令:ps: 查詢tomcat進程號 kill:殺死tomcat進程 步驟: 1)ps -ef | grep tomcat 查詢tomcat進程號, 2)kill -9 進程號 強制殺死該進程2 3)ps -ef | grep tomcat 再次查詢進程是否已經被殺死 4) ...
  • 問題:supervisorctl restart 服務名 失敗 案例: [root@node203 ~]# supervisorctl statusetcd-server-97-203 RUNNING pid 7706, uptime 14:29:46kube-apiserver-97-203 FA ...
  • 資料庫 1.1 資料庫基礎 1.1.1 選擇 1.1.1.1 Having 子句的作用是(C )。 A.查詢結果的分組條件 B.組的篩選條件 C.限定返回的行的判斷條件 D.對結果集進行排序 1.1.1.2 最常用的一種基本數據模型是關係數據模型,它的表示採用(D) A.樹 B.網路 C.圖 D.二 ...
  • 在Oracle和SQL Server資料庫中,可以設置一些複雜的賬號密碼策略,例如在失敗登錄超過N次即可鎖定賬號,那麼在MySQL中能否也有這樣的功能呢?答案是MySQL也有類似這樣的功能,只不過在MySQL中是在其登錄失敗超過閥值後,延遲響應時間,而不是鎖定賬號,在MySQL 5.7.17 以後提... ...
  •  JDBC基本使用方法 JDBC固定步驟: 載入驅動 連接資料庫,代表資料庫 向資料庫發送SQL的對象Statement: CRUD 編寫SQL (根據業務, 不同的SQL) 執行SQL 遍歷結果集 關閉連接 補充: statement.executeQuery(); //執行查詢操作 state ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...