gpt4 book ai didi

java - 使用 @TimeToLive 为 Redis Spring 缓存设置特定于 key 的 TTL 不会触发失效

转载 作者:行者123 更新时间:2023-12-05 05:36:36 29 4
gpt4 key购买 nike

我有一个用例,其中单个条目需要在特定时间从缓存中删除。 TTL 需要设置在键上而不是缓存级别

关注此spring redis documentation我试图实现特定于关键的 TTL,但它不起作用。没有事件发生,我使用了一个监听器来检查,当缓存 ttl 耗尽时只有一个事件发生。

缓存的对象有一个用@TimeToLive注解的字段来自org.springframework.data.redis.core.TimeToLive 查看文档这应该会在时间用完后触发过期事件

缓存对象

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BrandResponse {

@TimeToLive
private Long ttl;

@NotBlank
private String id;
}

使用的依赖项

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.3</version>
</dependency>

启用关键空间事件

@SpringBootApplication
@ServletComponentScan
@EnableAsync
@EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
public class KikaRestApiApplication {

public static void main(String[] args) {
SpringApplication.run(KikaRestApiApplication.class, args);
}
}

缓存的默认 TTL 为 5 分钟 .entryTtl(Duration.ofMinutes(5))

缓存设置

@Configuration
@EnableCaching
public class RedisCachingConfiguration {

private final KikaApiProperties kikaApiProperties;

@Value("${spring.redis.host}")
private String host;

@Value("${spring.redis.port}")
private Integer port;

public RedisCachingConfiguration(KikaApiProperties kikaApiProperties) {
this.kikaApiProperties = kikaApiProperties;
}

@Bean
public RedisCacheConfiguration cacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5))
.disableCachingNullValues()
.serializeValuesWith(
SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}

@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(host);
configuration.setPort(port);
return new JedisConnectionFactory(configuration);
}

@Bean
public RedisTemplate<String, Idmap> redisTemplate() {
RedisTemplate<String, Idmap> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}
}

@TimeToLive 是否不能与 spring-redis 缓存一起工作,我是否遗漏了什么?

最佳答案

根据文档

TimeToLive marks a single numeric property on aggregate root to beused for setting expirations in Redis. The annotated propertysupersedes any other timeout configuration.

RedisHash marks Objects as aggregate roots to be stored in a Redishash.

默认的ttl单位是秒。@TimeToLive(unit = TimeUnit.SECONDS)您可以使用其他值,例如 MINUTES。

在 BrandResponse 上使用@RedisHash。一切顺利

下面是我的工作代码

@RedisHash
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BrandResponse {

@TimeToLive(unit = TimeUnit.SECONDS )
private Long ttl;

@NotNull
@Id
private String id;
}

@Repository
public interface BrandRepository extends JpaRepository<BrandResponse, String> {
}

public interface CacheService {
void add(BrandResponse response);

boolean exists(String id);
}

@Service
public class RedisCacheServiceImpl implements CacheService {

@Autowired
private BrandRepository brandRepository;

@Override
public void add(BrandResponse response){
this.brandRepository.save(response);
}

@Override
public boolean exists(String id){
return !this.brandRepository.findById(id).isEmpty();
}
}

@Configuration
@EnableCaching
public class RedisCachingConfiguration {


private String host ="192.168.1.59";

private Integer port = 6379;

@Bean
public RedisCacheConfiguration cacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5))
.disableCachingNullValues()
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}

@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConFactory
= new JedisConnectionFactory();
jedisConFactory.setHostName(host);
jedisConFactory.setPort(port);
return jedisConFactory;
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
}

我使用了两个数据源,一个用于 Redis,另一个用于 db

@SpringBootApplication
@EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP,
basePackages = {"com.c4c.authn.core.repository.redis"})
@EnableJpaRepositories(basePackages = {"com.c4c.authn.core.repository.db"})
public class AuthApplication {

public static void main(String[] args) {

SpringApplication.run(AuthApplication.class, args);
}

}

单元测试

public class RedisCacheServiceImplTest extends BaseServiceTest {
@Autowired
private CacheService cacheService;

@Test
public void test_add_ok() throws InterruptedException {
this.cacheService.add(new BrandResponse(5l, "ID1"));
assertTrue(this.cacheService.exists("ID1"));

Thread.sleep(6000);

assertFalse(this.cacheService.exists("ID1"));
}
}

关于java - 使用 @TimeToLive 为 Redis Spring 缓存设置特定于 key 的 TTL 不会触发失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73275520/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com