首页 文章

Spring Redis - 主条目到期后索引未删除

提问于
浏览
8

我正在使用Spring Data Repository保存新条目 . 每个条目我的TTL为10秒 .

当我保存带索引的条目时,这是我在Redis中得到的

127.0.0.1:6379> keys *
1) "job:campaignId:aa"
2) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be"
3) "job:recipient:dd"
4) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:phantom"
5) "job:listId:cc"
6) "job:accountId:bb"
7) "job"
8) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:idx"

到期后,我仍然有数据:

127.0.0.1:6379> keys *
1) "job:campaignId:aa"
2) "job:recipient:dd"
3) "job:listId:cc"
4) "job:accountId:bb"
5) "job"
6) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:idx"

没有任何TTL .

他们为什么不删除自己?我怎么能这样做?

2 回答

  • 10

    Spring Data Redis存储库使用多个Redis功能在Redis中保留域对象 .

    域对象主要存储在哈希( job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be )中 . 任何到期都直接应用于散列,因此Redis可以使密钥到期 . Spring Data Redis还维护二级索引( job:campaignId:aajob:recipient:dd )以提供特定字段值的查找 . 集合中的各个元素不能过期 . 只有整个数据结构可以过期,但这不是你想要做的事情,因为所有未过期的元素都会以这种方式消失 .

    因此,Spring Data Redis将原始哈希的副本保留为幻像哈希( job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:phantom ),并且TTL略长 .

    Spring Data Redis订阅密钥事件(设置为 @EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP )以监听到期事件 . 一旦原始哈希到期,Spring Data Redis就会加载幻像哈希以执行清理(从二级索引中删除引用) .

    没有执行数据清理的原因有多种:

    • 如果您运行控制台应用程序只是为了插入数据并终止,那么到期将删除哈希但不执行索引清理,因为您的应用程序不再运行 . Redis发布的任何事件都是暂时的,如果您的应用程序没有收听,那么这些事件就会丢失

    • 如果您仅使用 @EnableRedisRepositories 启用了存储库支持(不启用keyspace-events),则Keyspace事件侦听器不活动,并且Spring Data Redis未订阅任何到期事件 .

  • 0

    如果未设置“到期时间”,则不会自动删除任何键/值 .

    因此,要自动删除数据,您必须设置过期时间 .

    redis> SET mykey "Hello"
    "OK"
    redis> EXPIRE mykey 10
    (integer) 1
    

    参考:https://redis.io/commands/expire

    下面是将数据添加到redis并设置过期时间的Spring代码段

    @Component
    public class RedisUtil {
        @Autowired
        private RedisTemplate<String, String> template;
    
        @Resource(name = "redisTemplate")
        ValueOperations<String, String> ops;
    
        public boolean addValue(String key, String value) {
    
            if (template.hasKey(Constants.REDIS_KEY_PREFIX + key)) {
                // key is already there
                return false;
            } else {
                ops.set(Constants.REDIS_KEY_PREFIX + key, value);
                template.expireAt(Constants.REDIS_KEY_PREFIX + key, 10);
            }
            return true;
        }
    }
    

相关问题