java的setIfAbsent(K,V,ExpiryTimeout)在redis中是原子的吗?

carvr3hs  于 2022-12-11  发布在  Redis
关注(0)|答案(1)|浏览(645)

根据文档,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

ibps3vxo

ibps3vxo1#

3参数和4参数setIfAbsent()重载传递了一个arg SetOption.ifAbsent()connection.set()。这看起来像是将NX填充到redis SET命令上,类似于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

相关问题