MST
星途 面试题库

面试题:Redis中EXPIRE命令如何实现键的过期管理及常见应用场景

请详细阐述Redis的EXPIRE命令是怎样实现对键的过期管理的,并举例说明至少两个在实际项目中使用EXPIRE命令实现过期管理的常见场景。
40.6万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

Redis的EXPIRE命令实现键的过期管理原理

  1. 设置过期时间EXPIRE key seconds 命令用于为指定的键设置过期时间,单位为秒。当执行该命令时,Redis会在内部数据结构中记录该键的过期时间戳(当前时间 + seconds)。
  2. 过期检查机制:Redis使用惰性删除和定期删除两种策略来处理过期键。
    • 惰性删除:当客户端尝试访问一个键时,Redis会首先检查该键是否过期。如果过期,则删除该键并返回相应的结果(例如 nil)。这种方式不会主动去扫描所有键来删除过期键,只有在访问时才检查,减少了额外的性能开销。
    • 定期删除:Redis会定期(默认每秒10次)随机抽取一定数量的键进行检查,删除其中过期的键。这个定期操作是为了防止惰性删除导致大量过期键长时间占用内存。每次抽取的键数量和执行频率可以通过配置参数调整。

实际项目中使用EXPIRE命令实现过期管理的常见场景

  1. 缓存数据过期
    • 场景描述:在Web应用中,经常会缓存数据库查询结果。例如,一个新闻网站会缓存热门新闻的详情页面数据。由于新闻内容可能会更新,缓存的数据不能永久保存。
    • 代码示例(Python + Redis)
import redis

r = redis.Redis(host='localhost', port=6379, db=0)
news_id = 123
news_detail = get_news_detail_from_db(news_id)  # 假设从数据库获取新闻详情
r.set(f'news:{news_id}', news_detail)
r.expire(f'news:{news_id}', 3600)  # 设置缓存1小时过期
  1. 限时令牌桶
    • 场景描述:在API限流场景中,使用令牌桶算法来控制请求频率。每个请求需要消耗一个令牌,而令牌以固定的速率生成。可以利用Redis的过期键机制来模拟令牌桶。
    • 代码示例(Java + Redis)
import redis.clients.jedis.Jedis;

public class RateLimiter {
    private Jedis jedis;
    private String key;
    private int capacity;
    private int refillRate;

    public RateLimiter(Jedis jedis, String key, int capacity, int refillRate) {
        this.jedis = jedis;
        this.key = key;
        this.capacity = capacity;
        this.refillRate = refillRate;
    }

    public boolean tryAcquire() {
        long now = System.currentTimeMillis();
        jedis.watch(key);
        Long tokens = jedis.get(key) == null? 0 : Long.parseLong(jedis.get(key));
        long lastRefill = jedis.get(key + ":lastRefill") == null? 0 : Long.parseLong(jedis.get(key + ":lastRefill"));
        long newTokens = Math.min(capacity, tokens + (now - lastRefill) / 1000 * refillRate);
        jedis.multi();
        jedis.setex(key, 3600, String.valueOf(newTokens));  // 设置过期时间,保证令牌桶的持续运行
        jedis.setex(key + ":lastRefill", 3600, String.valueOf(now));
        jedis.exec();
        if (newTokens > 0) {
            jedis.decr(key);
            return true;
        }
        return false;
    }
}

在上述代码中,setex 命令设置了键的过期时间,确保令牌桶的持续运行和重置,实现了限时令牌桶的功能。