Spring Redis - 主条目过期后未删除索引
Spring Redis - Indexes not deleted after main entry expires
我正在使用 Spring 数据存储库保存新条目。每个条目的 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。
他们为什么不删除自己?我该怎么做?
否key/values如果不设置过期时间会自动删除
因此要自动删除数据,您必须设置过期时间。
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;
}
}
Spring Data Redis Repositories 使用多个 Redis 功能来持久化 Redis 中的域对象。
域对象主要存储在哈希中 (job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be
)。任何过期都直接应用于哈希,因此 Redis 可以使密钥过期。 Spring Data Redis 还维护二级索引(job:campaignId:aa
、job:recipient:dd
)以提供按特定字段值的查找。集合中的单个元素不能过期。只有整个数据结构可以过期,但这不是您想要做的事情,因为所有 non-expired 元素都会那样消失。
因此 Spring Data Redis 将原始散列的副本保留为幻影散列 (job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:phantom
),TTL 稍长。
Spring Data Redis 订阅key-events(设置@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP
)来监听过期事件。一旦原始哈希过期,Spring Data Redis 加载幻影哈希以执行清理(从二级索引中删除引用)。
未执行数据清理的原因可能有多种:
- 如果您 运行 控制台应用程序只是为了插入数据并终止,则过期会删除哈希但不会执行索引清理,因为您的应用程序不再 运行ning。 Redis 发布的任何事件都是暂时的,如果您的应用程序没有监听,那么这些事件就会丢失
- 如果您仅使用
@EnableRedisRepositories
启用了存储库支持(未启用 keyspace-events),则 Keyspace 事件侦听器未激活,并且 Spring Data Redis 未订阅任何到期事件。
我正在使用 Spring 数据存储库保存新条目。每个条目的 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。
他们为什么不删除自己?我该怎么做?
否key/values如果不设置过期时间会自动删除
因此要自动删除数据,您必须设置过期时间。
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;
}
}
Spring Data Redis Repositories 使用多个 Redis 功能来持久化 Redis 中的域对象。
域对象主要存储在哈希中 (job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be
)。任何过期都直接应用于哈希,因此 Redis 可以使密钥过期。 Spring Data Redis 还维护二级索引(job:campaignId:aa
、job:recipient:dd
)以提供按特定字段值的查找。集合中的单个元素不能过期。只有整个数据结构可以过期,但这不是您想要做的事情,因为所有 non-expired 元素都会那样消失。
因此 Spring Data Redis 将原始散列的副本保留为幻影散列 (job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:phantom
),TTL 稍长。
Spring Data Redis 订阅key-events(设置@EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP
)来监听过期事件。一旦原始哈希过期,Spring Data Redis 加载幻影哈希以执行清理(从二级索引中删除引用)。
未执行数据清理的原因可能有多种:
- 如果您 运行 控制台应用程序只是为了插入数据并终止,则过期会删除哈希但不会执行索引清理,因为您的应用程序不再 运行ning。 Redis 发布的任何事件都是暂时的,如果您的应用程序没有监听,那么这些事件就会丢失
- 如果您仅使用
@EnableRedisRepositories
启用了存储库支持(未启用 keyspace-events),则 Keyspace 事件侦听器未激活,并且 Spring Data Redis 未订阅任何到期事件。