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)。

相关推荐
嘉伟桑1 小时前
Python调用电价API返回JSON示例:分时电价、现货电价和字段解析
后端
武子康1 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
我叫黑大帅1 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试
AskHarries2 小时前
文件上传系统
后端
止语Lab3 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活3 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困3 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn3 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530143 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908403 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端