1. 程式人生 > >Redis 設計與實現(第十三章) -- 客戶端

Redis 設計與實現(第十三章) -- 客戶端

腳本 ons listening last then red logs 可能 reply

概述

對於每個與服務器連接的客戶端,服務器都為它創建相應的redisClient的數據結構,並保持了相應的狀態。Redis Server通過一個鏈表來保存所有的客戶端連接。

本章包括:

  • 客戶端數據結構介紹;
  • 客戶端的創建與關閉

數據結構

先來看下redisClient中的數據結構:

* With multiplexing we need to take per-client state.
 * Clients are taken in a linked list. */
typedef struct redisClient {
    uint64_t id;            /* Client incremental unique ID. 
*/ int fd; //套接字描述符,大於1的整數,如果是偽客戶端則為-1 redisDb *db; //redisDB int dictid; robj *name; /* As set by CLIENT SETNAME 客戶端名字*/ sds querybuf; //輸入緩沖區,用於保存客戶端發送的命令請求 size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size */ int argc; //命令參數長度 robj **argv; //要執行的命令及命令參數
struct redisCommand *cmd, *lastcmd; //命令實現 int reqtype; int multibulklen; /* number of multi bulk arguments left to read */ long bulklen; /* length of bulk argument in multi bulk request */ list *reply; unsigned long reply_bytes; /* Tot bytes of objects in reply list */ int
sentlen; /* Amount of bytes already sent in the current buffer or object being sent. */ time_t ctime; /* Client creation time ,客戶端創建時間*/ time_t lastinteraction; /* time of the last interaction, used for timeout */ time_t obuf_soft_limit_reached_time; int flags; /* REDIS_SLAVE | REDIS_MONITOR | REDIS_MULTI ... 客戶端角色,一些狀態*/ int authenticated; /* when requirepass is non-NULL 認證*/ int replstate; /* replication state if this is a slave */ int repl_put_online_on_ack; /* Install slave write handler on ACK. */ int repldbfd; /* replication DB file descriptor */ off_t repldboff; /* replication DB file offset */ off_t repldbsize; /* replication DB file size */ sds replpreamble; /* replication DB preamble. */ long long reploff; /* replication offset if this is our master */ long long repl_ack_off; /* replication ack offset, if this is a slave */ long long repl_ack_time;/* replication ack time, if this is a slave */ long long psync_initial_offset; /* FULLRESYNC reply offset other slaves copying this slave output buffer should use. */ char replrunid[REDIS_RUN_ID_SIZE+1]; /* master run id if this is a master */ int slave_listening_port; /* As configured with: SLAVECONF listening-port */ int slave_capa; /* Slave capabilities: SLAVE_CAPA_* bitwise OR. */ multiState mstate; /* MULTI/EXEC state */ int btype; /* Type of blocking op if REDIS_BLOCKED. */ blockingState bpop; /* blocking state */ long long woff; /* Last write global replication offset. */ list *watched_keys; /* Keys WATCHED for MULTI/EXEC CAS */ dict *pubsub_channels; /* channels a client is interested in (SUBSCRIBE) */ list *pubsub_patterns; /* patterns a client is interested in (SUBSCRIBE) */ sds peerid; /* Cached peer ID. */ /* Response buffer,輸出緩沖區 */ int bufpos; //記錄了buf目前已使用的字節數 char buf[REDIS_REPLY_CHUNK_BYTES]; } redisClient;

客戶端創建與關閉

創建普通客戶端

當客戶端連接服務器時,服務器就會調用相應的連接事件處理器,將連接的客戶端狀態添加到redisServer數據結構中clients鏈表的末尾。

如下:

技術分享

關閉普通客戶端

一個普通客戶端可能因為多種原因被關閉:

1.如果客戶端進程退出或殺死,那麽客戶端與服務器間的網絡連接將會斷開,造成客戶端關閉;

2.如果客戶端向服務器發送了不符合協議格式的命令請求,那麽這個客戶端也會被服務器關閉;

3.如果客戶端成了client kill命令的目標,那麽客戶端也將會被關閉;

4.如果用戶為服務器設置了超時時間,那麽超時時間到後,客戶端也將會被關閉,在主從服務器裏面有一些例外;

5.如果客戶端發送的命令超過了緩沖區的大小(默認為1GB),那麽客戶端也將被關閉;

6.如果要發送給客戶端的回復命令超過了輸出緩沖區的大學,那麽這個客戶端也將被服務器關閉。

偽客戶端

1.Lua腳本的偽客戶端,在服務器運行期間一直存在,直到服務器關閉;

2.AOF加載的偽客戶端,在AOF加載完成後,偽客戶端就關閉連接。

Redis 設計與實現(第十三章) -- 客戶端