概述
对于每个与服务器连接的客户端,服务器都为它创建相应的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加载完成后,伪客户端就关闭连接。