Redis 的缓存过期策略

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

惰性过期

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

源码概览

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

c 复制代码
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;
}

定期删除

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

源码概览

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

c 复制代码
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));
    }
}

过期策略选择

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

注意事项

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

Java代码演示使用 Jedis

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

java 复制代码
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();
        }
    }
}

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

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

相关推荐
-曾牛2 小时前
探索 Spring AI 的 ChatClient API:构建智能对话应用的利器
java·人工智能·spring boot·后端·spring·springai·ai指南
白露与泡影2 小时前
使用OAuth2保护Spring AI MCP服务!
java·后端·spring
橘猫云计算机设计3 小时前
基于springboot的金院银行厅预约系统的设计及实现(源码+lw+部署文档+讲解),源码可白嫖!
java·数据库·spring boot·后端·爬虫·spring·毕业设计
Aurora_NeAr3 小时前
Spring IoC容器的设计与实现
java·后端·spring
柚个朵朵4 小时前
自定义Dockerfile,发布springboot项目
java·spring boot·后端·docker·dockerfile
电商api接口开发9 小时前
ASP.NET MVC 入门与提高指南八
后端·asp.net·mvc
橘猫云计算机设计9 小时前
springboot基于推荐算法的景点推荐系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·毕业设计·推荐算法
颇有几分姿色12 小时前
Spring Boot 实现多种来源的 Zip 多层目录打包下载(本地文件&HTTP混合)
java·spring boot·后端
计算机毕设指导615 小时前
基于Springboot旅游网站系统【附源码】
java·开发语言·spring boot·后端·mysql·spring·旅游
caihuayuan515 小时前
关于vue+iview中tabs嵌套及实际应用
java·大数据·spring boot·后端·课程设计