1 Set a key with an expiration time

Expire Key seconds time complexity: O (1)Copy the code

Set the expiration time of the key. After the timeout, the key is automatically deleted. In Redis terminology, the associated timeout for a key is volatile.

The key is cleared only when DEL, SET, and GETSET are executed on the key. This means that, conceptually, all operations that change the key without replacing it with a new value will remain timed out. For example, incrementing the key with INCR, performing LPUSH to push the new value into the list, or changing the hash field with HSET all leave the timeout unchanged.

  • usePERSISTThe timeout command clears it, making it permanentkey
  • ifkeyRENAMECommand modification, the related timeout period will be transferred to the newkey
  • ifkeyRENAMECommand modification, such as existingKey_AAnd then callRENAME Key_B Key_ACommand, then regardless of the originalKey_AWhether it’s permanent or set to timeout, will be determinedKey_BOverrides the validity period status

Note that calling EXPIRE/PEXPIRE with a non-positive timeout or EXPIREAT/PEXPIREAT with a past time will cause the key to be deleted rather than expired (therefore, the key event emitted will be del, not expired).

1.1 Refreshing the expiration time

An EXPIRE operation on a key that already has an expiration time will update its expiration time. There are many applications that have this business scenario, such as a session that records sessions.

1.2 Differences of 2.1.3 before Redis

Prior to Redis version 2.1.3, changing a key with an expired set using the command to change its value had the effect of deleting the key completely. This semantics is required because of limitations in the replication layer now being repaired.

EXPIRE returns 0 and does not change the timeout for keys with a timeout set.

1.3 the return value

  • 1If the expiration time is set successfully.
  • 0ifkeyDoes not exist or cannot set expiration time.

1.4 the sample

Suppose you have a Web service that is interested in the last N pages a user visited, such that each adjacent page view is no more than 60 seconds after the previous page. Conceptually, this set of page views can be thought of as a user’s navigation session that might contain interesting information about the products he or she is currently looking for so that you can recommend related products.

This pattern can be easily modeled in Redis using the following strategy: Each time a user executes a page view, you invoke the following command:

MULTI
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
EXEC
Copy the code

If the user is idle for more than 60 seconds, the key is removed and only subsequent page views whose differences are less than 60 seconds are logged. This schema is easily modified to use INCR instead of RPUSH lists.

1.5 Key with expiration time

Typically, the Redis key is created with no associated lifetime. The key persists unless the user explicitly removes it (such as the DEL command). Commands in the EXPIRE family can associate expired items with a given key at the cost of extra memory used by the key. When a key has an expiration set, Redis ensures that the key is deleted after the specified time has passed. Live critical times can be updated or completely removed using EXPIRE and PERSIST commands (or other strict commands).

1.6 Expiration Accuracy

In Redis 2.4, expiration may be inaccurate and may be between 0 and 1 second. Due to Redis 2.6, the expiration error ranges from 0 to 1 ms.

1.7 Expiration and Persistence

The key store for expiration information is an absolute Unix timestamp (milliseconds in Redis 2.6 or later). This means that even when the Redis instance is not active, time is flowing. For expiration to work well, computer time must be stabilized. If you move an RDB file from two computers with large desync in the clock, interesting things can happen (such as loading all expired keys at load time). Even run-time instances always check the computer clock, for example, if you set a key to 1000 seconds and then set the computer time to 2000 seconds in the future, the key will expire immediately instead of lasting 1000 seconds.

2 How does Redis make a key expire

There are two expiration modes for keys: passive – lazy deletion and active – periodic deletion.

2.1 Lazy Deletion

When a client tries to access a key, the key is passively expired, that is, Redis checks to see if the key has an expiration date, and if it does, it is deleted without returning anything. Note that the key is not automatically deleted when it expires, but rather that Redis lazily checks to see if it is deleted when the key is queried. This is similar to Spring’s lazy initialization.

Of course, this is not enough because there are expired keys that will never be accessed again. These keys are due to expire anyway, so periodically Redis tests a few keys randomly between keys with expiration sets. All expired keys are removed from the key space.

2.2 Deleting files Periodically

Specifically, the following Redis is 10 times per second:

  1. Test 20 random keys with expiration dates
  2. Delete all expired keys found
  3. If more than 25% of the keys have expired, start again from Step 1

This is a trivial probabilistic algorithm that basically assumes that our sample represents the entire key space and continues to expire until the percentage of keys that are likely to expire is less than 25%. This means that the maximum number of expired keys using memory at any given moment is equal to the maximum number of write operations per second divided by 4.

2.3 How to handle expiration in replication links and AOF files

In order to get the correct behavior without sacrificing consistency, when the key expires, the DEL operation synthesizes and acquires all additional slave nodes simultaneously in the AOF file. In this way, the expired process is concentrated in the master node without the possibility of consistency errors.

However, while the slave nodes connected to the master will not expire keys independently (but will wait for dels from the master), they will still use the full state of the existing expired keys in the data set, so when the slave is selected as master, it will be able to expire keys independently and act completely as master.

However, many expired keys, you did not timely check, regular deletion also missed, a large number of expired keys accumulated memory, Redis memory almost exhausted!

So also need to have memory elimination mechanism!

3 Memory Elimination

3.1 Memory Elimination Policy

Noeviction (Redis Default Policy)

Write requests will not continue to be served (DEL requests can continue to be served) and read requests can continue. This ensures that data will not be lost, but the online business will not continue.

  • config.c
createEnumConfig("maxmemory-policy".NULL, 
	MODIFIABLE_CONFIG, maxmemory_policy_enum, 
		server.maxmemory_policy, 
			MAXMEMORY_NO_EVICTION, NULL.NULL),
Copy the code

allkeys-random

When the memory is insufficient to hold new data, a key is removed randomly from the key space. At least delete the least recently used key.

allkeys-lru(Least Recently Used)

When the memory is insufficient to accommodate new data, the least recently used key is removed from the key space, and keys that have not been set to expire are also eliminated.

allkeys-lfu(Least Frequently Used)

The key of LRU is to look at the length of time between the last time a page was used and the occurrence of scheduling, while the key of LFU is to look at the frequency of page use within a certain period of time.

volatile-lru

The least used key is discarded first. Keys that do not have an expiration date are not obsolete, which ensures that data that needs to be persisted is not suddenly lost. Unlike Allkey-LRU, this strategy will weed out key collections that are just expired.

volatile-lfu

volatile-random

An obsolete key is a random key in an expired key set.

volatile-ttl

The elimination policy is not LRU, but the TTL value of the remaining life of the key. The smaller the TTL, the priority is eliminated.

Volatile – XXX eliminates only expired keys, whereas allkeys-xxx eliminates allkeys.

  • If you only use Redis as a cache, you should use allkeys-xxx. Clients write to the cache without carrying an expiration date.
  • If you want to use Redis persistence as well, use volatile- XXX. This will keep keys that are not set to expire. They are permanent and cannot be eliminated by the LRU algorithm.

3.2 handwritten LRU

Indeed sometimes ask this, because some candidates if really through the five passes, the previous questions are answered very well, then in fact let him write LRU algorithm, you can check the coding skills

You can hand-write the original LRU algorithm in the field, which is too much code to be practical

public class LRUCache<K.V> extends LinkedHashMap<K.V> {
    
private final int CACHE_SIZE;

    // This is the maximum amount of data that can be cached when passed in
    public LRUCache(int cacheSize) {
    	// True means that the linkedhashMap sorts elements by access order
        super((int) Math.ceil(cacheSize / 0.75) + 1.0.75 f.true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
    	 // The oldest data is automatically deleted when the number of KV data exceeds the specified cache number
        returnsize() > CACHE_SIZE; }}Copy the code

reference

  • Redis. IO/commands# ge…