Redis uses objects to represent key pairs in the database. When a key-value is set to a Redis database, the database creates at least two objects, one for the key (key object) of the key-value pair and one for the value (value object) of the key-value pair. Each object in Redis is represented by a redisObject structure with three properties related to saving data: type, Encoding, and PTR. There is also a RefCount attribute for object reference counting, an LRU attribute that records how long an object has been idling.

typedef struct redisObject {
    / / type
    unsigned type:4;

    / / code
    unsigned encoding:4;

    // A pointer to the underlying implementation data structure
    void *ptr;

    // Reference count
    int refcount;

    // Record the idling duration of the object
    unsigned lru;
}
Copy the code

type

The type attribute of an object records the type of an object. Redis has five object types: string object, list object, hash object, collection object, and ordered collection object. In Redis key-value pairs, the key is always a string object, and the value can be any of five object types.

object Type constants Type Output of the type command
String object REDIS_STRING string
A list of objects REDIS_LIST list
The hash object REDIS_HASH hash
A collection of objects REDIS_SET set
Ordered set object REDIS_ZSET zset

coding

The Encoding property in the redisObject structure records the encoding of the object, which determines the underlying implementation data structure to which the PTR pointer points. Objects in Redis can be encoded in two or more ways, each of which has a corresponding data structure.

Code constants The underlying data structure corresponding to the encoding OBJECT ENCODING Command output
REDIS_ENCODING_INT An integer of type long int
REDIS_ENCODING_EMBSTR A simple dynamic string encoded by embstr embstr
REDIS_ENCODING_RAM Simple dynamic string raw
REDIS_ENCODING_HT The dictionary hashtable
REDIS_ENCODING_LINKEDLIST Double side list linkedlist
REDIS_ENCODING_ZIPLIST The compression table ziplist
REDIS_ENCODING_INTSET The integer set intset
REDIS_ENCODING_SKIPLIST Skip lists and dictionaries sliplist

Encoding for different object types

type coding object
REDIS_STRING REDIS_ENCODING_INT A string object implemented with an integer value
REDIS_STRING REDIS_ENCODING_EMBSTR A string object implemented using a simple dynamic string encoded by EMbstr
REDIS_STRING REDIS_ENCODING_RAW A string object implemented using a simple dynamic string
REDIS_LIST REDIS_ENCODING_ZIPLIST A list object implemented using a compressed list
REDIS_LIST REDIS_ENCODING_LINKEDLIST A list object implemented using a two-ended list
REDIS_HASH REDIS_ENCODING_ZIPLIST Implement hash objects using compressed lists
REDIS_HASH REDIS_ENCODING_HT Hash objects implemented using dictionaries
REDIS_SET REDIS_ENCODING_INTSET A collection object implemented using a collection of integers
REDIS_SET REDIS_ENCODING_HT A collection object implemented using a dictionary
REDIS_ZSET REDIS_ENCODING_ZIPLIST An ordered collection object implemented using a compressed list
REDIS_ZSET REDIS_ENCODING_SKIPLIST An ordered collection object implemented using skip lists and dictionaries

Type check and code check

The commands used to operate keys in Redis can be basically divided into two types. One TYPE of command can execute any TYPE of keys, such as DEL command and TYPE command. The other is for specific object types, such as the GET command for strings and a type error if used for List.

When the server receives a command, it checks its type; It also selects the correct implementation code to execute the command based on how it is encoded. Type checking is performed according to the Type attribute of the redisObject structure, and encoding checking is performed according to the Encoding attribute. Both type checking and code checking are ways to implement polymorphic commands, the former being type-based polymorphism and the latter coding based polymorphism.

Memory reclamation is shared with objects

The whole life cycle of an object can be divided into three stages: creating an object, manipulating an object and releasing an object. The underlying implementation of Redis uses C language, but C language does not have automatic memory reclamation function, so Redis uses reference counting technology in its own object system to achieve the memory reclamation mechanism. The reference count information for an object is stored in the RefCount property of a redisObject. The reference count information for an object changes with the state of use of the object.

  • When a new object is created, the reference count value is initialized to 1;
  • When an object is used by a new program, its reference-count value is increased by one;
  • When an object is no longer in use by a program, its reference count is reduced by one.
  • When the reference count of an object becomes zero, the memory occupied by the object is freed.

In addition to being used to implement reference counting reclaim memory, the refcount attribute is also used to share string objects encoded by REDIS_ENCODING_INT. When creating a key-value pair of integer value type, the database checks for the existence of an equal string object, points the key to the existing string object, and increments the refcount of the object by one.

When Redis initializes the server, it creates 10,000 string objects containing all integer values from 0 to 9999. When the server needs these values, the server uses these shared objects.

Redis does not share objects that contain strings because verifying that strings are identical is too complex and takes up too much CPU resources.

Object idle time and data elimination strategy

The LRU attribute in the redisObject structure records the last operation time of the OBJECT. Using the OBJECT IDLETIME command, you can obtain the idling duration of the specified key. The idle time can serve the data obsolescence policy. When the memory occupied by the database is greater than maxMemory and maxmomery-Policy is set to volatile- LRU or allkeys-lRU, the data with the highest idle time will be deleted.

Elimination strategies in Redis

  • Volatile – lRU (least recently used): indicates the algorithm that has been used least recently. The algorithm selects the key-value pair with the longest idle time from the key whose expiration time is set to clear it.
  • Volatile – LFU (least frequently used): The algorithm that is least frequently used is used recently. From the keys whose expiration time is set, the key-value pair that is least frequently used in a certain period is deleted.
  • Volatile – TTL: Deletes the value pair with the earliest expiration from the set key.
  • Volatile -random: The key whose expiration time is set is randomly selected for elimination.
  • Allkeys-lru: the least recently used algorithm, from all the keys to select the longest idle time key-value pair cleaning;
  • Allkeys-lfu: select the least frequently used key pair from allkeys in a certain period of time to remove;
  • Allkeys-random: deletes allkeys randomly.
  • Any write operations will return errors when Redis memory limit is exceeded. However, all read operations work normally.