This is the 10th day of my participation in the August More Text Challenge. For details, see:August is more challenging

The database in Redis is briefly introduced above

One, the database key space operation and characteristics

Redis is a key-value pair database server. Each database in the server is represented by a redis.h/redisDb structure, where the dict dictionary of the redisDb structure holds all the key-value pairs in the database. We call this dictionary the key space:

typedef struct redisDb {
    //....
    // The database key space, which holds all the key-value pairs in the database
    dict *dict;
    / /...
} redisDb;
Copy the code

The key space corresponds directly to the database as the user sees it: 1. The key of the key space is also the database key, each key is a string object. 2. The value of the key space is the value of the database. Each value can be a String object, a list object, a hash table object, a collection object, or an ordered collection object.

The database key space contains list object, hash object, and string object examples

1. Add a new key

  • Adding a new key-value pair to the database is essentially adding a new key-value pair to the key-space dictionary, where the keys are string objects and the values are any type of Redis object.

2. Delete key

  • Deleting a key in the database actually deletes the key-value pair object corresponding to the key in the key space.

3. Update key

  • Updating a database is actually updating the corresponding value object of the key in the key space. Depending on the type of the value object, the specific method of updating will vary.

3. The value of the pair key

  • To value a database, in fact, is to fetch the corresponding value object of the key in the key space, according to the type of the value object, the specific value method will be different.

In addition to the above operations, there are many Redis commands for the database itself, also by processing the key space. For example, to FLUSHDB the entire database, delete all key pairs in the key space. The RANDOMKEY command, used to randomly return a key in the database, is implemented by randomly returning a key in the key space. Similar commands include EXISTS, RENAME, and KEYS.

1.1 Maintenance Operations for reading and writing key Space

When using the Redis command to read and write to the database, the server not only performs the specified read and write operations to the key space, but also performs some additional maintenance operations, including the following: 1. After reading a key (read and write), the server updates the number of hits or misses based on the presence or absence of the key. These two values can be viewed in the keyspace_hits and keyspace_misses properties of the INFO stats command. After reading a key, the server updates the LRU (last used) time of the key. This value can be used to calculate the idletime of the key. Use the OBJECT idletime

command to see the idletime of the key. 3. If the server reads a key and finds that it has expired, the server will delete the expired key before performing the rest of the operation.

Set the lifetime or expiration time of the key

Using the EXPIRE or PEXPIRE command, the client can set the Time To Live (TTL) for a key in the database in seconds or milliseconds. After the specified number of seconds or milliseconds, the server will automatically delete the key with a lifetime of 0. The client can also use the EXPIREAT or PEXPIREAT command to set an expire time in seconds or milliseconds for a key in the database. The expire time is a UNIX timestamp that the server automatically deletes when the key expires. The TTL and PTTL commands take a key with a lifetime or expiration time and return the remaining lifetime of the key.

2.1 Setting the Expiration Time

Redis has four different commands that you can use to set the lifetime (how long the key can be stored) or expiration time:

  • The EXPIRE

    < TTL > command is used to set the lifetime of a key to TTL seconds.
  • The PEXPIRE

    < TTL > command is used to set the lifetime of a key to TTL milliseconds.
  • The EXPIREAT

    command is used to set the expiration time of a key to the second timestamp specified by timesamp.
  • The PEXPIREAT

    command is used to set the expiration time of a key to the millisecond timestamp specified by timesamp.

All of the above commands will eventually be converted to the PEXPIREAT command. (Kind of polymorphic)

Conversion between commands that set the time to live and the time to expire

2.2 Saving the expiration time

The Expires dictionary of the redisDb structure holds the expiration times of all the keys in the database. We call this dictionary an expiration dictionary:

  • The key of an expired dictionary is a pointer to some key object in the key space.
  • The value of the expiration dictionary is a long Long integer that holds the expiration time of the database key to which the key points ———— a UNIX timestamp of millisecond precision.
typedef struct redisDb {
    // ...
    // The expiration dictionary, which holds the expiration time of the key
    dict *expires;
    // ...
} redisDb;
Copy the code

Here is the pseudocode definition of the PEXPIREAT command:

def PERPIREAT(key, expire_time_in_ms)If the given key does not exist in the key space, then the expiration time cannot be setif key not in redisDb.dict
        returnRedisdb.expires [key] redisdb.expires [key]= expire_time_in_msreturn 1
Copy the code

2.3 Removing the Expiration Time

The PERSIST command removes the expiration time of a key.

Here is the pseudo-code definition of the PERSIST command

def PERSIST(key): # If the given key does not exist, or if the expiration time is not set, then return directlyif key not in redisDb.expires:
        return0 # Remove the key-value pair association reddisdb.expires for the given key in the expired dictionary.remove(key)# Expiration time removed successfullyreturn 1
Copy the code

2.4 Calculate and return the remaining lifetime

The TTL command returns the remaining lifetime of the key in seconds, while the PTTL command returns the remaining lifetime of the key in milliseconds. Both of these are implemented by calculating the difference between the expiration time of the key and the current time. Here is a pseudo-code implementation of the two commands:

def PTTL(key): # key does not exist in databaseif key not in redisDb.dict:
        returnIf the expiration time is not set for the key, then expire_time_in_ms will be None expire_time_in_ms= redisdb.expires. Get (keyif expire_time_in_ms is None:
        return - 1Now_ms = get_CURRENT_UNIx_TIMEstamp_in_ms ()return(expire_time_in_ms-now_ms) def TTL(key):if ttl_in_ms < 0# processing returns a value of2 -- 1In the casereturn ttl_in_ms
    else: # Convert milliseconds to secondsreturn ms_to_sec(ttl_in_ms)
Copy the code

2.5 Determining the Expiration key

With an expiration dictionary, a program can check whether a given key is expired by the following steps:

  • Checks whether the given key exists in the expiration dictionary, and if so, gets the expiration time of the key.
  • Check whether the current UNIX timestamp is greater than the expiration time of the key: If so, the key has expired; Otherwise, the key is not expired.

Delete the expiration key policy

When a key expires, when is it deleted?

There are three possible answers to this question, which represent three different deletion strategies:

  • Periodic deletion: When the expiration time of a key is set, a timer is created to delete the key immediately when the expiration time comes.
  • Lazy delete: let a key expire, but every time you retrieve it from key space, check if it has expired and delete it if it has; If it is not expired, the key is returned.
  • Periodic deletion: Every once in a while, the program checks the database to remove the expired key. It is up to the algorithm to decide how many expired keys to delete and how many databases to check.