首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为Redis Spring缓存设置特定于键的TTL和@TimeToLive不会触发无效

为Redis Spring缓存设置特定于键的TTL和@TimeToLive不会触发无效
EN

Stack Overflow用户
提问于 2022-08-08 09:19:17
回答 1查看 1.2K关注 0票数 3

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

在此春红文献之后,我尝试实现关键的特定TTL,但它不起作用。没有事件发生,我使用一个侦听器来检查它,当缓存ttl运行完时,只有一个事件发生。

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

缓存对象

代码语言:javascript
复制
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BrandResponse {

    @TimeToLive
    private Long ttl;

    @NotBlank
    private String id;
}

使用依赖项

代码语言:javascript
复制
<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>

启用关键空间事件

代码语言:javascript
复制
@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))

缓存设置

代码语言:javascript
复制
@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缓存不一起工作。

EN

回答 1

Stack Overflow用户

发布于 2022-08-16 17:12:45

根据文件

TimeToLive在聚合根上标记一个数字属性,用于设置Redis中的过期值。带注释的属性取代任何其他超时配置。 RedisHash将对象标记为要存储在Redis散列中的聚合根。

默认的ttl单位是第二。@TimeToLive(unit = TimeUnit.SECONDS)您可以使用其他值,比如分钟。

在BrandResponse上使用@RedisHash。

下面是我的工作代码

代码语言:javascript
复制
@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。

代码语言:javascript
复制
@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);
    }

}

单元测试

代码语言:javascript
复制
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"));
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73275520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档