当前位置:   article > 正文

Redis缓存过期策略_redistemplate.expire

redistemplate.expire

Redis缓存是一种常用的缓存技术,可以提高系统性能和响应速度。然而,如果不采取适当的过期策略,缓存可能会占据大量内存,并且数据也可能会过期并失效。

一、Redis缓存过期策略的基础知识

了解Redis缓存过期策略的前提是必须掌握Redis内存模型以及数据结构,在此我们不再赘述。Redis缓存过期策略的核心思想是根据key的过期时间来决定key是否被删除的。当一个key的过期时间到达指定时间后,Redis会自动将其删除。这个过程是由Redis内部负责的,程序员只需要设定好key的过期时间即可。

二、Redis缓存过期策略常见的类型以及如何实现

1)TTL(Time-To-Live)

TTL是Redis最简单的过期策略之一,它需要程序员手动为每个key设置过期时间。当key的过期时间到达后,Redis会自动将其删除。我们可以使用TTL命令获取key的剩余时间或者使用EXPIRE命令设置key的过期时间。例如:

  1. # 设置 key 为 value, 并将过期时间设置为 10 秒钟
  2. SET key value EX 10 # 获取 key 的剩余过期时间 TTL key

2)惰性删除

惰性删除策略也是Redis默认的过期策略之一。它不会把所有的过期 key 都删除掉,而是等到有客户端来查询这个 key 的时候才检查该 key 是否已过期,并在发现过期的情况下删除该 key。因此惰性删除存在缺陷:如果有大量的过期 key 没有被查询,就会占用过多的内存空间。所以在某些场景中,需要结合其他策略来使用惰性删除。

3)定期删除

定期删除是与惰性删除相对应的一种过期策略,它会每隔一段时间主动检查过期 key,并删除过期的 key 。Redis会启动一个专门负责删除过期 key 的线程,并且可以通过配置文件指定清除频率(redis.conf文件中,default-db-deletion-size配上db * rows-per-second * 3600 )。与惰性删除不同,定期删除会消耗一定的CPU资源和IO资源,但相对惰性删除而言,它可以更快的将大量过期 key 删除掉。

二、Redis如何处理超时key

当一个key过期后,程序员无需干预,Redis会自动开始进行以下两个操作:

1)简单地将该key打上过期标记,并不立即从内存中删除;

2)通过惰性删除或定期删除策略,在之后的某个时间从内存中清除带有过期标记的key。

需要注意的是,Redis并不能保证所有过期的key都能在第一时间被后台线程清理掉。为了避免缓存泄漏和数据更新问题,应用程序在使用Redis缓存时,最好添加逻辑判断,比如在获取value之前先检查key是否存在或者手动删减过期key 。

三、基于时间的过期策略

1. 设置过期时间

在Redis中,可以使用EXPIRE和PEXPIRE命令为键设置生存时间,以秒或毫秒为单位。例如:
// 设置键为mykey的值,确保它在30秒之后过期
 

  1. redisTemplate.opsForValue().set("mykey", "Hello, Redis!");
  2. redisTemplate.expire("mykey", 30, TimeUnit.SECONDS);

2. 查看剩余生存时间

可以使用TTL命令或PTTL命令来查看键的剩余生存时间(以秒或毫秒为单位)。例如:

 

  1. // 查看mykey的生存时间(以秒为单位)
  2. redisTemplate.ttl("mykey");
  3. // 查看mykey的生存时间(以毫秒为单位)
  4. redisTemplate.pttl("mykey");

3. 取消过期时间

可以使用PERSIST命令来取消键的生存时间,使其永久保存。例如:

  1. // 取消mykey的生存时间
  2. redisTemplate.persist("mykey");

四、基于LRU算法的淘汰机制

1. 设置最大内存

可以使用maxmemory和maxmemory-policy两个配置参数设置Redis的最大内存和相应的淘汰策略。例如:

  1. # 设置Redis最大内存为100MB
  2. maxmemory 100mb
  3. # 设置淘汰策略为LRU
  4. maxmemory-policy allkeys-lru

2. 修改默认淘汰策略

除了使用maxmemory-policy命令来设置全局的淘汰策略外,也可以通过将某些键标记为VOLATILE来单独设置LRU淘汰策略。例如:

  1. // 将mykey的生存时间设置为10秒,并标记为VOLATILE
  2. redisTemplate.expire("mykey", 10, TimeUnit.SECONDS);
  3. redisTemplate.execute(new RedisCallback<Boolean>() {
  4.     @Override
  5.     public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
  6.         // 将mykey标记为VOLATILE
  7.         connection.setEx(redisTemplate.getKeySerializer().serialize("mykey"), 10000L,
  8.                 redisTemplate.getValueSerializer().serialize("Hello, Redis!"));
  9.         return true;
  10.     }
  11. });

3. 查看Redis内存使用情况

可以使用INFO命令或redis-cli工具来查看Redis的内存使用情况。例如:
# 使用INFO命令查看Redis内存使用情况

  1. redisTemplate.execute(new RedisCallback<String>() {
  2.     @Override
  3.     public String doInRedis(RedisConnection connection) throws DataAccessException {
  4.         return connection.info();
  5.     }
  6. });
  7. # 使用redis-cli工具查看Redis内存使用情况
  8. $ redis-cli info memory

五、通过Java代码演示实操

以下是一个通过Java Redis API演示基于时间的过期策略和LRU淘汰机制的示例程序。

  1. public class CacheDemo {
  2.     private static finalStringRedisTemplate redisTemplate = new StringRedisTemplate();
  3.     static {
  4.         // 设置Redis服务器的主机名和端口号
  5.         RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("localhost", 6379);
  6.         // 创建连接池
  7.         LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
  8.         factory.afterPropertiesSet();
  9.         // 设置RedisTemplate的连接工厂
  10.         redisTemplate.setConnectionFactory(factory);
  11.         redisTemplate.afterPropertiesSet();
  12.     }
  13.     public static void main(String[] args) {
  14.         // 设置键值对缓存
  15.         redisTemplate.opsForValue().set("key1", "value1");
  16.         redisTemplate.opsForValue().set("key2", "value2");
  17.         // 设置key1的生存时间为10秒,并标记为VOLATILE
  18.         redisTemplate.expire("key1", 10, TimeUnit.SECONDS);
  19.         redisTemplate.execute(new RedisCallback<Boolean>() {
  20.             @Override
  21.             public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
  22.                 connection.setEx(redisTemplate.getKeySerializer().serialize("key1"), 10000L,
  23.                         redisTemplate.getValueSerializer().serialize("value1"));
  24.                 return true;
  25.             }
  26.         });
  27.         // 查看key1的剩余生存时间
  28.         System.out.println(redisTemplate.getExpire("key1"));
  29.         // 设置Redis的最大内存为10MB,淘汰策略为LRU
  30.         redisTemplate.execute(new RedisCallback<String>() {
  31.             @Override
  32.             public String doInRedis(RedisConnection connection) throws DataAccessException {
  33.                 connection.getConfig("maxmemory");
  34.                 connection.getConfig("maxmemory-policy", "allkeys-lru");
  35.                 return null;
  36.             }
  37.         });
  38.         // 查看Redis内存使用情况
  39.         System.out.println(redisTemplate.execute(RedisServerCommands::info).get("used_memory"));
  40.     }
  41. }

六、总结

Redis缓存的过期策略是保证缓存可靠性和性能的关键之一。基于时间的过期策略通过设置生存时间来实现,而基于LRU算法的淘汰机制则根据访问频率和时间排序来删除最近没有使用的key。在实际使用中,可以结合两种策略来避免出现缓存占据大量内存和过期失效等问题。在Java中,可以使用RedisTemplate来对Redis进行操作。通过设置键值对缓存、设置过期时间、取消过期时间、修改默认淘汰策略和查看Redis内存使用情况等操作,可以实现对缓存的控制和管理。

需要注意的是,在设置缓存过期时间和淘汰机制时,应根据业务场景和数据类型来选择合适的时间和策略。如果需要缓存的数据变化频繁,建议采用基于LRU算法的淘汰机制;如果数据比较固定或重要性较高,可以使用基于时间的过期策略。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/466860
推荐阅读
相关标签
  

闽ICP备14008679号