17 Redis Key Expiration Operations

17 Redis Key Expiration Operations #

Expiration Setting #

Redis mainly provides four ways to set expiration time for keys:

  • expire key seconds: Set the key to expire after n seconds;
  • pexpire key milliseconds: Set the key to expire after n milliseconds;
  • expireat key timestamp: Set the key to expire after a specific timestamp in seconds;
  • pexpireat key millisecondsTimestamp: Set the key to expire after a specific timestamp in milliseconds;

Let’s look at the specific implementation of these commands one by one.

expire: Expire after N seconds #

127.0.0.1:6379> set key value
OK
127.0.0.1:6379> expire key 100
(integer) 1
127.0.0.1:6379> ttl key
(integer) 97

The command ttl stands for Time To Live, which indicates that the key will expire after n seconds. For example, the result 97 means that the key will expire after 97 seconds.

pexpire: Expire after N milliseconds #

127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> pexpire key2 100000
(integer) 1
127.0.0.1:6379> pttl key2
(integer) 94524

The command pexpire key2 100000 means that key2 will expire after 100000 milliseconds (100 seconds).

expireat: Expiration timestamp in seconds #

127.0.0.1:6379> set key3 value3
OK
127.0.0.1:6379> expireat key3 1573472683
(integer) 1
127.0.0.1:6379> ttl key3
(integer) 67

The command expireat key3 1573472683 means that key3 will expire after the timestamp 1573472683 (in seconds). Using the ttl command, we can see that key3 will expire after 67 seconds.

Tip: In Redis, you can use the time command to query the current timestamp (in seconds). For example:

127.0.0.1:6379> time

  1. “1573472563”

  2. “248426”

pexpireat: Expiration timestamp in milliseconds #

127.0.0.1:6379> set key4 value4
OK
127.0.0.1:6379> pexpireat key4 1573472683000
(integer) 1
127.0.0.1:6379> pttl key4
(integer) 3522

The command pexpireat key4 1573472683000 means that key4 will expire after the timestamp 1573472683000 (in milliseconds). Using the pttl command, we can see that key4 will expire after 3522 milliseconds.

Expiration Operations in Strings #

Several methods directly manipulate the expiration time of strings, as listed below:

  • set key value ex seconds: Set the key value pair and specify the expiration time (in seconds) at the same time;
  • set key value px milliseconds: Set the key value pair and specify the expiration time (in milliseconds) at the same time;
  • setex key seconds value: Set the key value pair and specify the expiration time (in seconds) at the same time.

Here are the implementations.

1. set key value ex seconds

127.0.0.1:6379> set k v ex 100
OK
127.0.0.1:6379> ttl k
(integer) 97

2. set key value ex milliseconds

127.0.0.1:6379> set k2 v2 px 100000
OK
127.0.0.1:6379> pttl k2
(integer) 92483

3. setex key seconds value

127.0.0.1:6379> setex k3 100 v3
OK
127.0.0.1:6379> ttl k3
(integer) 91

Removing Expiration Time #

The command persist key can be used to remove the expiration time of a key, as shown in the following code.

127.0.0.1:6379> ttl k3
(integer) 97
127.0.0.1:6379> persist k3
(integer) 1
127.0.0.1:6379> ttl k3
(integer) -1

It can be seen that after the first ttl query, k3 will expire after 97 seconds. After using the persist command and querying the survival time of k3 again, the result is -1, which means that k3 will never expire.

Implementing Expiration Operations in Java #

In this article, Jedis framework will be used to implement expiration time operations in Redis, as shown in the following code:

public class TTLTest {
    public static void main(String[] args) throws InterruptedException {
        // Create a Redis connection
        Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
        // Set the Redis password (can be omitted if there is no password)
        jedis.auth("xxx");
        // Store key value pair (by default, it never expires)
jedis.set("k", "v");
// Get TTL (time to live)
Long ttl = jedis.ttl("k");
// Print expiration log
System.out.println("Time to live: " + ttl);
// Set expiration to 100 seconds
jedis.expire("k", 100);
// Wait for 1 second before executing
Thread.sleep(1000);
// Print expiration log
System.out.println("TTL after expire: " + jedis.ttl("k"));

The program’s execution result is:

Time to live: -1 TTL after expire: 99

It can be seen that using Jedis to operate on expiration time in Redis is very convenient. You can directly use jedis.ttl("k") to query the time-to-live of a key-value pair, and use jedis.expire("k", seconds) to set the expiration time (accurate to seconds).

Tip: Before using Jedis, make sure to import it into your program. If you are using a Maven project, simply add the following dependency to your pom.xml file:

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>version</version>
</dependency>

More expiration operations are as follows:

  • pexpire(String key, long milliseconds): Set expiration time to n milliseconds later;
  • expireAt(String key, long unixTime): Set expiration time to a specific timestamp (in seconds);
  • pexpireAt(String key, long millisecondsTimestamp): Set expiration time to a specific timestamp (in milliseconds);
  • persist(String key): Remove the expiration time.

Here is the complete sample code:

public class TTLTest {
    public static void main(String[] args) throws InterruptedException {
        // Create Redis connection
        Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
        // Set Redis password (if there is no password, this line can be omitted)
        jedis.auth("xxx");
        // Store the key-value pair (by default, it never expires)
        jedis.set("k", "v");
        // Query TTL (time to live)
        Long ttl = jedis.ttl("k");
        // Print expiration log
        System.out.println("Time to live: " + ttl);
        // Set expiration to 100 seconds
        jedis.expire("k", 100);
        // Wait for 1 second before executing
        Thread.sleep(1000);
        // Print expiration log
        System.out.println("TTL after expire: " + jedis.ttl("k"));
        // Set expiration to n milliseconds later
        jedis.pexpire("k", 100000);
        // Set expiration time to a specific timestamp (in seconds)
        jedis.expireAt("k", 1573468990);
        // Set expiration time to a specific timestamp (in milliseconds)
        jedis.pexpireAt("k", 1573468990000L);
        // Remove expiration time
        jedis.persist("k");
    }
}

Expiring Keys in Persistence #

In the previous section, we discussed some use cases of expiring keys in Redis during normal operation. Now, let’s take a look at how expired keys are handled during persistence in Redis.

Redis persistence has two formats: RDB (Redis Database) and AOF (Append Only File). Let’s see how expired keys are represented in these two formats.

Expired Keys in RDB #

The RDB file generation process consists of two stages: RDB file generation and RDB file loading.

1. RDB file generation

When persisting the in-memory state to an RDB file, expired keys are not saved to the new RDB file. Therefore, expired keys in Redis do not have any effect on generating a new RDB file.

2. RDB file loading

RDB loading has the following two cases:

  • If Redis is running as a master server, when loading an RDB file, the program checks the keys in the file and expired keys are not loaded into the database. Therefore, expired keys do not affect the master server when loading an RDB file.
  • If Redis is running as a slave server, when loading an RDB file, expired keys are loaded into the database regardless of whether they are expired. However, since the data on the slave server is cleared during data synchronization with the master server, expired keys generally do not affect loading an RDB file on the slave server.

You can find the source code for RDB file loading in the rdbLoad() function in the rdb.c file. Here is the relevant code snippet:

/* Check if the key already expired. This function is used when loading
* an RDB file from disk, either at startup, or when an RDB was
* received from the master. In the latter case, the master is
* responsible for key expiry. If we would expire keys here, the
* snapshot taken by the master may not be reflected on the slave. 
*
* If the server is a master node,
* when the key has expired, it will not be associated with the database
*/
if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {
    decrRefCount(key);
    decrRefCount(val);
    // Skip
    continue;
}

Expired Keys in AOF #

1. AOF file writing

When Redis persists in AOF mode, if a key in the database has not been deleted when it expires, the AOF file keeps this expired key. When this key is deleted, Redis appends a DEL command to the AOF file to explicitly delete the key-value pair.

2. AOF rewriting

During AOF rewriting, expired keys are not saved to the rewritten AOF file after checking the key-value pairs in Redis. Therefore, expired keys do not have any effect on AOF rewriting.

Expired Keys in Slave Servers #

When Redis is running in master-slave mode, the slave server does not perform expiration scanning. The expiration handling in the slave server is passive. Even if a key in the slave server has expired, if a client accesses the slave server, it will return the value of the key as if it were an unexpired key.

The expiration handling in the slave server depends on the master server. When a key in the master server expires, it adds a DEL command to the AOF file, and this command is synchronized to all the slave servers. The slave servers execute this DEL command to delete the expired key.

Conclusion #

In this article, we have learned the four ways to set expiration time in Redis: expire, pexpire, expireat, and pexpireat. Among them, expire is the most commonly used method to set an expiration time of n seconds.

You can set the expiration time while adding a key-value pair in a string, and you can use the persist command to remove the expiration time. We have also learned that expired keys are not recorded during RDB writing and AOF rewriting.

In master-slave mode, the slave server relies entirely on the master server to handle expired keys. When a key expires in the master server, it adds a DEL command to the AOF file, which is then sent to all the slave servers.

Here is a summary of the knowledge points covered in this article:

image.png