admin管理员组

文章数量:1401199

I am working on a reactive Spring Boot project using the spring-boot-starter-data-redis-reactive library to integrate Redis as a caching mechanism.

Before I used .springframework.cache.CacheManager, but as I use this within a spring-cloud-gateway project and this should be always non-blocking I try to switch to a reactive implementation of redis.

I want to configure a default Time-to-Live (TTL) for cache entries in Redis, but it seems that the property spring.cache.redis.time-to-live does not work with the reactive Redis configuration (which worked before).

Here are some details about my setup:

  • Spring Boot version: 3.4.3

  • Redis library: spring-boot-starter-data-redis-reactive

I tried the following steps:

Set the TTL property in application.yaml:

spring:
 cache:
   redis:
     time-to-live: 60000 # TTL in milliseconds

and write some key, value like:

@Component
@Slf4j
public class UserContextReactiveRedisCacheClient implements UserContextCachePort {

    public static final String CACHE_PREFIX = "core-gateway::cacheUserContext::";

    private final ReactiveRedisOperations<String, String> userContextOperations;
    
    public UserContextReactiveRedisCacheClient(
            final ReactiveRedisOperations<String, String> userContextOperations
    ) {
        this.userContextOperations = userContextOperations;
    }

    /**
     * Load a context of a user.
     *
     * @param ciamId Load user context based on provided ciamId.
     * @return The User Context.
     */
    public Mono<String> loadUserContext(final String ciamId) {
        log.debug("Loading from cache user context for ciamId {}.", ciamId);
        return userContextOperations.opsForValue().get(CACHE_PREFIX + ciamId);
    }

    /**
     * Puts as encoded user context as String in cache if absent.
     *
     * @param ciamId The ciamId for the user.
     * @param encodedUserContext The context as a String to put.
     * @return A Mono of Boolean representing success of the operation.
     */
    public Mono<Boolean> putUserContextIfAbsent(
            final String ciamId,
            final String encodedUserContext
    ) {
        return userContextOperations.keys(CACHE_PREFIX + ciamId)
                .collectList()
                .flatMap(keys -> {
                    if (keys.isEmpty()) {
                        log.debug("Putting into cache user context for ciamId {}.", ciamId);
                        return userContextOperations.opsForValue().set(
                                CACHE_PREFIX + ciamId,
                                encodedUserContext
                        );
                    }
                    return Mono.just(false);
                });
    }
}

This will provide in a key entry in redis:

127.0.0.1:6379> TTL "core-gateway::cacheUserContext::f3ac883e-f73f-40d7-b4a0-cd900755ed7d"
(integer) -1

So the configuration is not working properly which was before.

I need to set the expiration manually each time I write a key with value to take TTL into account like:


@Component
@Slf4j
public class UserContextReactiveRedisCacheClient implements UserContextCachePort {

    public static final String CACHE_PREFIX = "core-gateway::cacheUserContext::";

    private final ReactiveRedisOperations<String, String> userContextOperations;

    private Duration expiration;

    public UserContextReactiveRedisCacheClient(
            final ReactiveRedisOperations<String, String> userContextOperations,
            @Value("${spring.cache.redis.time-to-live}") final Duration expiration
    ) {
        this.userContextOperations = userContextOperations;
        this.expiration = expiration;
    }

    /**
     * Load a context of a user.
     *
     * @param ciamId Load user context based on provided ciamId.
     * @return The User Context.
     */
    public Mono<String> loadUserContext(final String ciamId) {
        log.debug("Loading from cache user context for ciamId {}.", ciamId);
        return userContextOperations.opsForValue().get(CACHE_PREFIX + ciamId);
    }

    /**
     * Puts as encoded user context as String in cache if absent.
     *
     * @param ciamId The ciamId for the user.
     * @param encodedUserContext The context as a String to put.
     * @return A Mono of Boolean representing success of the operation.
     */
    public Mono<Boolean> putUserContextIfAbsent(
            final String ciamId,
            final String encodedUserContext
    ) {
        return userContextOperations.keys(CACHE_PREFIX + ciamId)
                .collectList()
                .flatMap(keys -> {
                    if (keys.isEmpty()) {
                        log.debug("Putting into cache user context for ciamId {}.", ciamId);
                        return userContextOperations.opsForValue().set(
                                CACHE_PREFIX + ciamId,
                                encodedUserContext,
                                expiration
                        );
                    }
                    return Mono.just(false);
                });
    }
}

Is there a way to configure this so it only works with the application.yaml configuration?

Thanks in advance for your help

本文标签: