Spring Redis -主条目过期后不删除索引

ldioqlga  于 2023-10-15  发布在  Redis
关注(0)|答案(3)|浏览(122)

我正在使用Spring Data Repository保存新条目。我为每个条目设置了10秒的TTL。
当我保存一个带有索引的条目时,这是我在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。
他们为什么不删除自己?我怎么能这么做

gtlvzcf8

gtlvzcf81#

Spring Data Redis Repositories使用多个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订阅key-events(设置@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP)来监听到期事件。一旦原始散列过期,Spring Data Redis就会加载幻影散列以执行清理(从二级索引中删除引用)。
未执行数据清理的原因可能有多种:
1.如果您运行控制台应用程序只是为了插入数据并终止,那么到期将删除哈希值,但不会执行索引清理,因为您的应用程序不再运行。Redis发布的任何事件都是暂时的,如果你的应用程序没有监听,那么这些事件就会丢失
1.如果您仅使用@EnableRedisRepositories启用了repository支持(未启用keyspace-events),则Keyspace事件侦听器不活动,并且Spring Data Redis未订阅任何到期事件。

s3fp2yjn

s3fp2yjn2#

主条目过期后索引未被删除的另一个可能原因是在键空间中使用了双冒号(:):

@RedisHash(value = "app-name:entity-name")

根据以下主题,键空间中不支持双冒号:

  1. https://github.com/spring-projects/spring-data-redis/issues/2096
  2. https://github.com/spring-projects/spring-data-redis/pull/2100#issuecomment-881256388
    您还可以通过查看keyspace事件处理方法org.springframework.data.redis.core.RedisKeyValueAdapter.MappingExpirationListener#onMessageorg.springframework.data:spring-data-redis:3.1.0)的实现来验证这一点。
w1e3prcc

w1e3prcc3#

如果不设置删除时间,则不会自动删除任何键/值。
因此,要自动删除数据,您必须设置删除时间。

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

参考号:https://redis.io/commands/expire
下面是Spring代码片段,用于向redis添加数据并设置过期时间

@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;
    }
}

相关问题