Redis 中的客戶端

Redis 是一個客戶端服務端的程序,服務端提供數據存儲等等服務,客戶端鏈接服務端並經過向服務端發送命令,讀取或寫入數據,簡單來講,客戶端就是某種工具,咱們經過它與 Redis 服務端進行通信並完成數據操做。java

客戶端並非 Redis 的核心,Redis 的核心是它的服務端程序,服務端程序纔是完成數據存、取,持久化等等咱們使用頻繁的各類操做的執行者。但也不是說客戶端就沒什麼做用,客戶端在整個 Redis 服務體系中也是很是重要的一環。本篇先來看看 Redis 客戶端的一些特性以及實現原理。git

1、客戶端的基本屬性

redis 中爲客戶端抽象的數據結構是,server.h/client 結構,我這裏是 redis-4.0.x 版本,不一樣版本或許稍有不一樣,每個 redis 客戶端成功的鏈接上服務端以後,服務端就會建立一個 client 結構實例,並以鏈表的形式連接全部鏈接成功的客戶端。程序員

這個結構最主要做用就是存儲當前客戶端的大量屬性,套接字、名字、標誌,狀態等等信息,這些信息很是的重要,當服務端爲客戶端服務時,不少的信息例如當前要執行的命令、參數都會從這裏獲取。咱們一個一個來了解。github

一、客戶端名稱redis

默認狀況下,全部鏈接成功的客戶端都是沒有名字的,這一點你能夠經過向服務發送 client list 命令驗證,它會返回當前服務端成功創建的客戶端以及他們的基本信息。例如:緩存

image

能夠看到,name 字段默認是空,若是你想讓你的客戶端辨識度更高,你能夠向服務端發送 client setname 爲你的客戶端命名,這裏我就不作演示了,客戶端名稱這個信息保存在 client 結構中的 name 字段裏。服務器

typedef struct client {
    .........
    robj *name;             /* As set by CLIENT SETNAME. */           
    .........
} client;

二、標誌微信

標誌用於描述當前 redis 客戶端的一些狀態或者角色,對應的到數據結構中就是一個整型字段。數據結構

typedef struct client {
    .........
    int flags;              /* Client flags: CLIENT_* macros. */
    .........
} client;

Redis 中定義了不少的客戶端標誌,函數

image

一個整型的 flags 字段,能夠經過二進制或(|) 的方式同時存儲過個狀態,好比:

flags = 0000 0110 = CLIENT_MASTER | CLIENT_MONITOR

固然了,上面那個 flages 的值只是舉了個例子,描述了當前客戶端是一個主節點的 server(當進行主從節點複製的時候,主節點會做爲客戶端鏈接從節點發送 RDB 文件給客戶端),又正在執行 MONITOR 命令。前者描述了客戶端角色,後者描述客戶端狀態。

總而言之,redis 客戶端 flags 字段能夠描述當前客戶端的角色,也能夠記錄當前客戶端各類狀態信息,是服務端了解客戶端信息的一個很是重要的字段。

三、輸入/輸出緩衝區

redis 服務端收到客戶端發來的命令請求須要不少步驟來處理和調用相關命令的實現,並最終將數據返回給客戶端,那麼輸入緩衝區其實就是一小塊內存,用於存儲客戶端發送過來的命令,包括參數,這塊內存空間默認不能超過 1GB,不然 redis 服務端就會強制關閉與該客戶端的鏈接。

typedef struct client {
    .........
    sds querybuf;           /* Buffer we use to accumulate client queries. */
    .........
} client;

querybuf 就是客戶端緩衝區,它是一個 SDS 類型的字段,那麼說明這是一個能夠動態擴充輸入緩衝區。

固然咱們也能夠經過 client list 看看當前客戶端的的 querybuf 分配和使用狀況。

image

其中 qbuf 和 qbuf-free 用於描述客戶端輸入緩衝區狀態。我這裏的這個沒有寫入過大的命令,因此這裏的 querybuf 只分配了 32768 個字節。

ps:儘可能不要使用過大的 KEY,這樣會致使客戶端 querybuf 佔用過多內存,這樣會致使 redis 服務端程序佔用太高內存,若是超過 maxmemory 限制,會觸發 KEY 的 LRU 淘汰或程序異常。

除此以外,redis 客戶端還有一個輸出緩衝區,用於緩存服務端響應的回覆。

輸出緩衝區有兩種,一種是固定大小的,用於存儲服務端簡單的響應,例如:OK,錯誤信息等。還有一種是非固定長度的緩衝區,它的長度是可動態擴展的,用於存儲一些較長的響應內容。

typedef struct client {
    .........
    /* Response buffer */
    int bufpos;
    char buf[PROTO_REPLY_CHUNK_BYTES];
    .........
} client;

PROTO_REPLY_CHUNK_BYTES 等於 16*1024,也就是默認固定輸出緩衝區只有 16K,bufpos 記錄當前固定緩衝區已經使用的字節數。

typedef struct client {
    .........
    list *reply;            /* List of reply objects to send to the client. */
    .........
} client;

動態緩衝區用鏈表實現,能夠爲咱們返回較大的 key,例如一些 set、list 集合等等。咱們能夠經過 client list 命令查看輸出緩衝區的使用狀況。

image

obl 表示固定緩衝區長度,oll 表明動態緩衝區長度,omem 表示固定緩衝區和動態緩衝區總共佔用了多少字節。

ps:輸出緩衝區能夠經過配置 client-output-buffer-limit 限制最大內存上限,一樣若是濫用,同樣會致使 redis 服務器內存飆升,建議儘可能配置小一點的輸出緩存區大小。

2、客戶端三種類型

redis 客戶端主要分爲三種,普通客戶端、發佈訂閱客戶端、slave 客戶端。普通客戶端咱們不用多說,也是咱們用的最多的客戶端。

redis 客戶端能夠訂閱任意數量的頻道,若是你訂閱了某個服務器頻道,那麼你的客戶端就也是一個發佈訂閱客戶端,當頻道中有新消息,服務器會向你推送,關於 redis 的發佈訂閱功能,咱們後續會詳細介紹。

當 redis 集羣中部署了主從節點的時候,全部的從節點服務器又稱爲 slave 客戶端,他們會向 master 按期拉取最新數據,詳細的內容後續介紹。

下一篇咱們分析 redis 的服務端程序實現,以及神祕的 serverCron 定時函數實現。


關注公衆不迷路,一個愛分享的程序員。

公衆號回覆「1024」加做者微信一塊兒探討學習!

每篇文章用到的全部案例代碼素材都會上傳我我的 github

https://github.com/SingleYam/overview_java

歡迎來踩!

YangAM 公衆號

相關文章
相關標籤/搜索