Redis code structure Class 3 database-list
1. Type Library Overview
The following describes the core content of redis and supported data types and operations. First, let's take a look at the corresponding data structure:
Typedef char * SDS; // basically all the files returned are SDS, that is, char *, which is also the address of the actual storage content. Struct sdshdr {int Len; // space owned by the content, excluding the size of the structure itself or the Buf final Terminator '\ 0' int free; // The remaining available memory space, some of which may not be used in Buf. The length is the free value char Buf []; // The actual storage content = strlen (BUF) + free = Len };
This type is the most commonly used type in redis. It is similar to the string type in C ++. The corresponding functions include SDS sdsnewlen (const void * init, size_t initlen). It first applies for SH = zmalloc (sizeof (struct sdshdr) + initlen + 1); memory (note: sizeof (struct sdshdr) = 8), initlen is sdshdr-> Len, and init will be transferred to sdshdr-> Buf by memcpy, and sdshdr-> free is 0 at this time. Finally, return (char *) Sh-> Buf, that is, the actual content address. Others are similar to the string method.
typedef struct redisObject { unsigned type:4; unsigned storage:2; /* REDIS_VM_MEMORY or REDIS_VM_SWAPPING */ unsigned encoding:4; unsigned lru:22; /* lru time (relative to server.lruclock) */ int refcount; void *ptr;} robj;
This structure defines the abstract data type of the redis operation object.
Type: defines the data type. Currently, redis supports five data types: redis_string, redis_list, redis_set, redis_zset, and redis_hash.
Storage: defines whether the current data location is memory or hard disk swap.
Encoding: defines the encoding method or memory storage method used for data types. Currently, redis supports eight encoding types. For various types and supported codes, see the following table:
Type |
Redis_string (t_string.c) |
Redis_list (t_list.c, ziplist. c) |
Redis_set (t_set.c) |
Redis_zset (t_zset.c) |
Redis_hash (t_hash.c) |
Command |
Set, mset |
Lpush, rpush, lpop, rpop |
Sadd |
Zadd |
Hset, hmset |
Encoding |
Redis_encoding_raw, redis_encoding_int |
Redis_encoding_ziplist, redis_encoding_linkedlist |
Redis_encoding_ht, redis_encoding_intset |
Redis_encoding_ziplist, redis_encoding_skiplist |
Redis_encoding_ht, redis_encoding_zipmap |
The data type is determined by the user's command, in addition, all keys use the redis_string type (when dbadd is used, extract the actual content SDS copy = sdsdup (key-> PTR );, this is the key value actually saved to dict), and its encoding is only redis_encoding_raw; the encoding is selected by the server based on the configuration and current system conditions (this condition is described in each of the following types ).
LRU:
Refcount: number of references to this object
PTR: point to the actually stored content
When the server receives a client request, it always converts all the members of the command to type = redis_string, the robj type of encoding = redis_encoding_raw is saved to the client-> argv [] (0 is the command, 1 is the key, 2, 3 .. is the value [2 may be the expire value]. This process is completed in the processinlinebuffer or processmultibulkbuffer function ). At the same time, when calling the corresponding processing function of each command, most commands will first perform a tryobjectencoding command on the value, that is, to determine whether the value can be expressed as a long string2l (S, sdslen (s), & value), if possible, use shared. integers [value], or Encoding
= Redis_encoding_int. The Code is as follows:
If (! String2l (S, sdslen (s), & Value) return O ;... If (server. maxmemory = 0 & value> = 0 & value <redis_shared_integers & pthread_equal (pthread_self (), server. mainthread) {decrrefcount (o); incrrefcount (shared. integers [value]); Return shared. integers [value];} else {o-> encoding = redis_encoding_int; sdsfree (o-> PTR); O-> PTR = (void *) value; return O ;} the following describes the corresponding structures and operations of the five data types. 2. redis_string (t_string.c) commands of this type include: Set, setnx, setex, mset, incr, append, etc. Here we only introduce the SET command. The corresponding command callback function issetCommand(redisClient *c) { c->argv[2] = tryObjectEncoding(c->argv[2]); setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);}
Most commands of this type use the setgenericcommand function as the internal interface:
Void setgenericcommand (redisclient * C, int NX, robj * Key, robj * val, robj * expire) {long seconds = 0; /* initialized to avoid an harmness warning */If (expire) {// operation for setting the expiration time if (getlongfromobjectorreply (C, expire, & seconds, null )! = Redis_ OK) return; If (seconds <= 0) {addreplyerror (C, "invalid expire time in setex"); Return ;}// if the key exists, the command must be set only when the key does not exist. At this time, if (lookupkeywrite (c-> dB, key) is returned )! = NULL & Nx) {addreply (C, shared. czero); return;} setkey (c-> dB, key, Val); // append key, Val server to the dictionary. dirty ++; // set dirty persistence using if (expire) setexpire (c-> dB, key, time (null) + seconds ); // Add this event addreply (C, nx? Shared. Cone: Shared. OK );}
This is the set operation process, which is very simple. The internal setkey is the function that calls dB. C, dict. C.