Redis as a cache software, in the Redis source code, everywhere embodies the idea of saving memory, the following first from 3 aspects of the Redis memory saving strategy to do a share. (The following code is Redis 3.0. Version 5)
1.redisObject is one of the most common data structures in Redis, and all of the keys and values of Redis storage are a redisobject, so you have to be willing to save redisobject size. Since Redis data types are only 5 common to us, and Redis has a total of 8 data encoding types, Redis is represented by 4Bit, which adds exactly 1 bytes.
typedef struct REDISOBJECT {
unsigned type:4;
unsigned encoding:4;
unsigned lru:redis_lru_bits; /* LRU time (relative to Server.lruclock) */
int refcount;
void *ptr;
} RobJ;
2.Redis for frequently used variables, set them as global variables, and use reference counting methods. The main purpose of this strategy is to avoid duplicate creation and improve performance. Memory-saving is only available when a sufficient number of data values are 0-9999. As the code shows, there is a variable integers in the struct that stores the object pointer of data 0-9999.
struct sharedobjectsstruct {robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *cnegone, *pong, *spac E, *colon, *nullbulk, *nullmultibulk, *queued, *emptymultibulk, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecte RR, *outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr, *masterdownerr, *roslaveerr, *execabort Err, *noautherr, *noreplicaserr, *busykeyerr, *oomerr, *plus, *messagebulk, *pmessagebulk, *subscribebulk, *unsubs Cribebulk, *psubscribebulk, *punsubscribebulk, *del, *rpop, *lpop, *lpush, *emptyscan, *minstring, *maxstring, *se LECT[REDIS_SHARED_SELECT_CMDS], *integers[redis_shared_integers], *mbulkhdr[redis_shared_bulkhdr_len],/* "*<va lue>\r\n "*/*bulkhdr[redis_shared_bulkhdr_len]; /* "$<value>\r\n" */};
3.Redis of 8 encoding types, Redis_encoding_int, Redis_encoding_embstr, Redis_encoding_raw is the basis for several other encoding types, in addition to Redis_encoding_ Intset, the objects stored in the corresponding object are based on the previous three encoding types, and each object is generated in detail. For example, in a REDIS list, each node stores an object whose encoding type can be either Redis_encoding_int, Redis_encoding_embstr, or Redis_encoding_raw.
/* Try to encode a string object in order to save space */RobJ *tryobjectencoding (RobJ *o) {Long value;
SDS s = o->ptr;
size_t Len; /* Make sure a string object with the only type of We encode * in this function. Other types use encoded memory efficient * Representations but is handled by the commands implementing * the Ty Pe.
*/redisassertwithinfo (Null,o,o->type = = redis_string); /* We Try some specialized encoding only for objects that is * RAW or EMBSTR encoded, in other words objects that AR
E still * in represented by an actually array of chars. */if (!sdsencodedobject (o)) return o; /* It's not safe to encode gkfx objects:shared objects can be shared * everywhere in the "object space" of the Redis A nd may end in places where * they is not handled. We handle them only as values in the Keyspace.
*/if (O->refcount > 1) return o; /* Check If we can represent this string as a long integer.
* Note that we were sure that a string larger than chars was not * representable as a + or-bit integer.
*/len = Sdslen (s); if (Len <= && string2l (s,len,&value)) {/* This object is encodable as a long.
Try to use a shared object. * Note that we avoid using gkfx integers when maxmemory are used * because every object needs to has a private LRU field for the LRU * algorithm to work well.
*/if ((Server.maxmemory = = 0 | | (Server.maxmemory_policy! = Redis_maxmemory_volatile_lru && Server.maxmemory_policy! = Redis_maxmemo
RY_ALLKEYS_LRU)) && value >= 0 && value < redis_shared_integers) {
Decrrefcount (o);
Incrrefcount (Shared.integers[value]);
return Shared.integers[value];
} else {if (o->encoding = = Redis_encoding_raw) sdsfree (O->PTR); o->encoding = Redis_encoding_int;
O->ptr = (void*) value;
return o;
}}/* If The string is small and are still RAW encoded, * Try the EMBSTR encoding which is more efficient. * In this representation the object and the SDS string is allocated * In the same chunk's memory to save space and cache misses.
*/if (len <= redis_encoding_embstr_size_limit) {robj *emb;
if (o->encoding = = redis_encoding_embstr) return o;
EMB = Createembeddedstringobject (S,sdslen (s));
Decrrefcount (o);
return EMB; }/* We can ' t encode the object ... * Do the last try, and at least optimize the SDS string inside * The string object to require little space, in case there * was more than 10% of free space at the end of the SDS Strin G. * * We do, only for relatively large strings as this branch * are only entered if the length of the s Tring is greater than * REdis_encoding_embstr_size_limit. */if (o->encoding = = Redis_encoding_raw && sdsavail (s) > LEN/10) {o->ptr = SdsR
Emovefreespace (O->PTR); }/* Return the original object.
*/return o;
}