根据文档,spring data redis的setIfAbsent(K, V)
使用了setNX
命令。然而,setIfAbsent(K, V, Expiry timeout)
似乎使用了set
命令,而不是setNX
。这是否意味着必须在一个键上设置超时,值使它不是原子的?
在我的用例中,我想为每一行设置TTL,并且我试图了解如果两个线程(或应用程序示例)同时调用setIfAbsent(K,V, sometimeoutinminutes)
,redis将如何表现?是只有一个请求更新密钥(setNX
行为)还是两个请求都更新密钥?
通过查看实现,我可以看到两者的代码路径略有不同,因此这让我怀疑后者是否真的是原子的。
我的代码如下所示:
@Bean
public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<?, ?> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
code that updates:
//try to get value for a given key from redis.
String value = redisTemplate.opsForValue().get(key);
//if present, return value to the caller.
if (value != null) {
return value;
}
//if not, fetch value from remote.
value = makeNetworkCallToGetValue(key);
if (value != null) {
// update redis. what happens if 2 threads/application instances call this at the same time?
redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofMinutes(1));
}
return value;
程式库版本:Spring-数据-红色:2.6.4
1条答案
按热度按时间ibps3vxo1#
3参数和4参数
setIfAbsent()
重载传递了一个argSetOption.ifAbsent()
到connection.set()
。这看起来像是将NX
填充到redisSET
命令上,类似于connection.setNX()
的操作。我猜他们想重构这种方法,以减少支持SET
的所有选项和参数组合所需的方法重载的数量。SetOption.ifAbsent()
:https://github.com/spring-projects/spring-data-redis/blob/2.6.4/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java#L379
LettuceConverters.toSetArgs(expiration, option)
:https://github.com/spring-projects/spring-data-redis/blob/2.6.4/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStringCommands.java#L139
args.nx()
:https://github.com/spring-projects/spring-data-redis/blob/2.6.4/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java#L800