• Redis 的缓存过期策略


    Redis 的缓存过期策略是指当数据存储在 Redis 中时,如何处理到达特定生命周期末端的数据。Redis 主要使用两种策略来管理键的过期:惰性过期(Lazy Expiration)和定期删除(Periodic Deletion)。

    惰性过期

    当客户端访问一个键时,Redis 会检查这个键是否已经达到过期时间。如果已过期,Redis 就会删除它,然后返回一个错误。

    源码概览

    在 Redis 的源码中,expireIfNeeded 函数负责检查键是否过期。以下是一个简化的伪代码:

    int expireIfNeeded(redisDb *db, robj *key) {
        // 检查键是否有过期时间设置
        if (!key->expire) return 0;
    
        // 获取当前时间
        mstime_t now = mstime();
    
        // 判断键是否过期
        if (now > key->expire) {
            // 执行删除操作
            dbDelete(db, key);
            return 1;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    定期删除

    Redis 每隔一段时间执行一次自动清理操作。它会随机地选择一些键,并检查它们是否过期。过期的键会被删除。

    源码概览

    Redis 使用 activeExpireCycle 函数来定期检查和删除过期的键。以下是简化的伪代码:

    void activeExpireCycle(int type) {
        // 从数据库中随机抽取一部分键
        for (int i = 0; i < REDIS_EXPIRELOOKUPS_PER_CRON; i++) {
            // 随机选择数据库
            int db_id = rand() % server.dbnum;
            redisDb *db = server.db[db_id];
    
            // 随机选择键
            if (dictSize(db->expires) == 0) continue;
            dictEntry *de = dictGetRandomKey(db->expires);
            
            // 检查键是否过期
            expireIfNeeded(db, dictGetKey(de));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    过期策略选择

    Redis 的过期策略是折衷的。它不保证立即删除所有过期键,但保证过期键不会被永久访问到。

    注意事项

    • 内存使用:过期键可能在过期后不会立即被删除,因此可能会暂时占用更多内存。
    • 性能考量:定期删除策略避免了锁定 Redis 实例以删除大量的过期键,但它仍然需要使用一定的 CPU 资源来随机检查键。
    • 持久化:当 Redis 重启时,它会根据持久化文件(AOF 或 RDB)来恢复过期键的状态。

    Java代码演示使用 Jedis

    下面是使用 Java 和 Jedis 客户端库与 Redis 交互的代码示例。这个例子演示了如何设置键的过期时间以及如何检索它。

    import redis.clients.jedis.Jedis;
    
    public class RedisExpirationDemo {
        public static void main(String[] args) {
            // Connect to the Redis server
            Jedis jedis = new Jedis("localhost", 6379);
    
            try {
                // Set a key with a value and an expiration time in seconds (10 seconds in this case)
                String key = "myKey";
                String value = "Hello, Redis!";
                int expireTime = 10; // Key expires in 10 seconds
    
                jedis.setex(key, expireTime, value);
                System.out.println("Key set with expiration time.");
    
                // Get the value right away
                String currentValue = jedis.get(key);
                System.out.println("Value immediately after setting: " + currentValue);
    
                // Wait for the key to expire
                Thread.sleep(10000);
    
                // Try to get the value after expiration time
                currentValue = jedis.get(key);
                System.out.println("Value after expiration: " + (currentValue == null ? "null (key expired)" : currentValue));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // Close the connection
                jedis.close();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在上述代码中,我们使用 setex 方法设置了一个键,为其提供了一个过期时间(10秒)。随后,我们尝试立即获取该键,应该能够获取到值。然后程序休眠10秒,再次尝试获取该键时,由于键已经过期,所以应该获取不到值。

    请注意,为了简化代码,这里没有包含异常处理和资源管理的最佳实践,如在生产环境中应使用 try-with-resources 语句来自动关闭 Jedis 实例。此外,确保 Redis 服务在本地运行并监听默认端口(6379)。

  • 相关阅读:
    visual studio code(vs code)历史版本下载
    电脑软件:UPDF - 高效率高颜值的PDF编辑器
    豆瓣评分9.0,《Java核心技术与面试》神作,已帮助1374人拿到Offer
    瞎扯:修仙文明VS科技文明发展潜力
    Python --- 面向对象
    React中this.setState方法原理解析(详解)
    给Hexo添加说说功能
    机器学习 中数据是如何处理的?
    阿里云服务操作指南-个人购买版
    研发效能工程实践-代码评审
  • 原文地址:https://blog.csdn.net/qq_43012298/article/details/135841792