从 ReactiveRedisOperations 得到一个 key/keys 总是 return 空结果
Getting a key/keys from ReactiveRedisOperations always return empty result
我正在将传统的 Redis 缓存迁移到 Spring Data Reactive Redis。迁移后,我想测试我的新集成是否按预期工作,但我遇到了从特定 Redis Db 获取 key/keys 的问题,即:
我的 redisConfiguration
class 看起来像这样:
import java.time.Duration;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializationContext.RedisSerializationContextBuilder;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfiguration {
private static final String REDIS_PROPERTIES = "redis.properties";
private final Properties redisProperties = readConfigurationFile(REDIS_PROPERTIES);
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Value("${redis.timeout}")
private String timeout;
@Bean(name = "reactiveRedisConnectionFactory")
@Primary
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean(name ="reactiveRedisTemplate")
public ReactiveRedisOperations<String, Object> reactiveRedisTemplate(
@Qualifier(value = "reactiveRedisConnectionFactory") ReactiveRedisConnectionFactory factory) {
return prepareRedisTemplate(factory);
}
@Bean(name = "reactiveRedisUserConnectionFactory")
public ReactiveRedisConnectionFactory reactiveRedisUserConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String userDb = getProperty(redisProperties, RedisDb.USER_DB);
setRedisProperties(redisConfiguration, userDb);
LettuceClientConfiguration clientConfiguration =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration, clientConfiguration);
return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
}
@Bean(name = "reactiveUserRedisTemplate")
public ReactiveRedisOperations<String, Object> userRedisTemplate(
@Qualifier(value = "reactiveRedisUserConnectionFactory")
ReactiveRedisConnectionFactory connectionFactory) {
return prepareRedisTemplate(connectionFactory);
}
@Bean(name = "redisRegistrationTokenConnectionFactory")
public ReactiveRedisConnectionFactory reactiveRedisRegistrationTokenConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String registrationTokenDb = getProperty(redisProperties, RedisDb.REGISTRATION_TOKEN_DB);
setRedisProperties(redisConfiguration, registrationTokenDb);
LettuceClientConfiguration clientConfiguration =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration, clientConfiguration);
return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
}
@Bean(name = "reactiveRegistrationTokenRedisTemplate")
public ReactiveRedisOperations<String, Object> registrationTokenRedisTemplate(
@Qualifier(value = "redisRegistrationTokenConnectionFactory")
ReactiveRedisConnectionFactory connectionFactory) {
return prepareRedisTemplate(connectionFactory);
}
@Bean(name = "reactiveRedisWhitelistingConnectionFactory")
public ReactiveRedisConnectionFactory redisWhitelistingConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String whitelistingDb = getProperty(redisProperties, RedisDb.WHITELISTING_DB);
setRedisProperties(redisConfiguration, whitelistingDb);
LettuceClientConfiguration clientConfiguration =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration, clientConfiguration);
return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
}
@Bean(name = "reactiveWhitelistingRedisTemplate")
public ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate(
@Qualifier(value = "reactiveRedisWhitelistingConnectionFactory")
ReactiveRedisConnectionFactory connectionFactory) {
return prepareRedisTemplate(connectionFactory);
}
@Bean(name = "redisSerializer")
public Jackson2JsonRedisSerializer<Object> redisSerializer() {
return new Jackson2JsonRedisSerializer<>(Object.class);
}
private ReactiveRedisOperations<String, Object> prepareRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) {
Jackson2JsonRedisSerializer<Object> redisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
RedisSerializationContextBuilder<String, Object> serializationContext =
RedisSerializationContext.newSerializationContext(new StringRedisSerializer());
RedisSerializationContext<String, Object> context =
serializationContext
.value(redisSerializer)
.hashKey(redisSerializer)
.hashValue(redisSerializer)
.build();
return new ReactiveRedisTemplate<>(connectionFactory, context);
}
private void setRedisProperties(RedisStandaloneConfiguration redisConfiguration, String redisDb) {
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(Integer.parseInt(redisDb));
redisConfiguration.setPassword(RedisPassword.of(password));
}
private void logRedisConnectionDetails(
RedisStandaloneConfiguration redisConfiguration,
LettuceClientConfiguration clientConfiguration) {
log.info(
"Connected to Redis host: {}, port: {}, database: {}, commandTimeout: {}",
redisConfiguration.getHostName(),
redisConfiguration.getPort(),
redisConfiguration.getDatabase(),
clientConfiguration.getCommandTimeout().toSeconds());
}
}
我的“测试”class 看起来像:
@SpringBootApplication
@Slf4j
public class ApiGatewayApplication implements CommandLineRunner {
private final ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate;
private final ReactiveRedisOperations<String, Object> reactiveUserRedisTemplate;
public ApiGatewayApplication(
@Qualifier(value = "reactiveWhitelistingRedisTemplate") ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate,
@Qualifier(value = "reactiveUserRedisTemplate") ReactiveRedisOperations<String, Object> reactiveUserRedisTemplate) {
this.reactiveWhitelistingRedisTemplate = reactiveWhitelistingRedisTemplate;
this.reactiveUserRedisTemplate = reactiveUserRedisTemplate;
}
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
@Override
public void run(String... args) {
log.info("CASE1");
log.info(
String.valueOf(
reactiveWhitelistingRedisTemplate
.keys("*")
.flatMap(reactiveWhitelistingRedisTemplate.opsForValue()::get)));
log.info("CASE2");
log.info(String.valueOf(reactiveWhitelistingRedisTemplate.scan()));
log.info("CASE3");
log.info(String.valueOf(reactiveUserRedisTemplate.keys("*")));
log.info("CASE4");
log.info(reactiveWhitelistingRedisTemplate.randomKey() + "RANDOM");
log.info("CASE5");
log.info(String.valueOf(reactiveWhitelistingRedisTemplate.opsForValue().get("whitelisting:zenon112")));
}
}
在获取 key/keys 时,我总是收到空的 Mono/Flux 结果如下:
CASE1
FluxFlatMap
CASE2
FluxMap
CASE3
FluxMap
CASE4
MonoMapRANDOM
CASE5
MonoNext
我确信 Redis 不是空的,Redis 中的示例键是 whitelisting:ranomuser112
老实说,我对自己做错了什么很困惑,对于如何从反应式 Redis 获取特定密钥的建议,我将不胜感激。干杯!
我忽略了 .subscribe()
方法调用。没有它,反应结果将被忽略。问题已解决。
我正在将传统的 Redis 缓存迁移到 Spring Data Reactive Redis。迁移后,我想测试我的新集成是否按预期工作,但我遇到了从特定 Redis Db 获取 key/keys 的问题,即:
我的 redisConfiguration
class 看起来像这样:
import java.time.Duration;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializationContext.RedisSerializationContextBuilder;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfiguration {
private static final String REDIS_PROPERTIES = "redis.properties";
private final Properties redisProperties = readConfigurationFile(REDIS_PROPERTIES);
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Value("${redis.timeout}")
private String timeout;
@Bean(name = "reactiveRedisConnectionFactory")
@Primary
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean(name ="reactiveRedisTemplate")
public ReactiveRedisOperations<String, Object> reactiveRedisTemplate(
@Qualifier(value = "reactiveRedisConnectionFactory") ReactiveRedisConnectionFactory factory) {
return prepareRedisTemplate(factory);
}
@Bean(name = "reactiveRedisUserConnectionFactory")
public ReactiveRedisConnectionFactory reactiveRedisUserConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String userDb = getProperty(redisProperties, RedisDb.USER_DB);
setRedisProperties(redisConfiguration, userDb);
LettuceClientConfiguration clientConfiguration =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration, clientConfiguration);
return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
}
@Bean(name = "reactiveUserRedisTemplate")
public ReactiveRedisOperations<String, Object> userRedisTemplate(
@Qualifier(value = "reactiveRedisUserConnectionFactory")
ReactiveRedisConnectionFactory connectionFactory) {
return prepareRedisTemplate(connectionFactory);
}
@Bean(name = "redisRegistrationTokenConnectionFactory")
public ReactiveRedisConnectionFactory reactiveRedisRegistrationTokenConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String registrationTokenDb = getProperty(redisProperties, RedisDb.REGISTRATION_TOKEN_DB);
setRedisProperties(redisConfiguration, registrationTokenDb);
LettuceClientConfiguration clientConfiguration =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration, clientConfiguration);
return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
}
@Bean(name = "reactiveRegistrationTokenRedisTemplate")
public ReactiveRedisOperations<String, Object> registrationTokenRedisTemplate(
@Qualifier(value = "redisRegistrationTokenConnectionFactory")
ReactiveRedisConnectionFactory connectionFactory) {
return prepareRedisTemplate(connectionFactory);
}
@Bean(name = "reactiveRedisWhitelistingConnectionFactory")
public ReactiveRedisConnectionFactory redisWhitelistingConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
String whitelistingDb = getProperty(redisProperties, RedisDb.WHITELISTING_DB);
setRedisProperties(redisConfiguration, whitelistingDb);
LettuceClientConfiguration clientConfiguration =
LettuceClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(Long.parseLong(timeout)))
.build();
logRedisConnectionDetails(redisConfiguration, clientConfiguration);
return new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
}
@Bean(name = "reactiveWhitelistingRedisTemplate")
public ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate(
@Qualifier(value = "reactiveRedisWhitelistingConnectionFactory")
ReactiveRedisConnectionFactory connectionFactory) {
return prepareRedisTemplate(connectionFactory);
}
@Bean(name = "redisSerializer")
public Jackson2JsonRedisSerializer<Object> redisSerializer() {
return new Jackson2JsonRedisSerializer<>(Object.class);
}
private ReactiveRedisOperations<String, Object> prepareRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) {
Jackson2JsonRedisSerializer<Object> redisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
RedisSerializationContextBuilder<String, Object> serializationContext =
RedisSerializationContext.newSerializationContext(new StringRedisSerializer());
RedisSerializationContext<String, Object> context =
serializationContext
.value(redisSerializer)
.hashKey(redisSerializer)
.hashValue(redisSerializer)
.build();
return new ReactiveRedisTemplate<>(connectionFactory, context);
}
private void setRedisProperties(RedisStandaloneConfiguration redisConfiguration, String redisDb) {
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(Integer.parseInt(redisDb));
redisConfiguration.setPassword(RedisPassword.of(password));
}
private void logRedisConnectionDetails(
RedisStandaloneConfiguration redisConfiguration,
LettuceClientConfiguration clientConfiguration) {
log.info(
"Connected to Redis host: {}, port: {}, database: {}, commandTimeout: {}",
redisConfiguration.getHostName(),
redisConfiguration.getPort(),
redisConfiguration.getDatabase(),
clientConfiguration.getCommandTimeout().toSeconds());
}
}
我的“测试”class 看起来像:
@SpringBootApplication
@Slf4j
public class ApiGatewayApplication implements CommandLineRunner {
private final ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate;
private final ReactiveRedisOperations<String, Object> reactiveUserRedisTemplate;
public ApiGatewayApplication(
@Qualifier(value = "reactiveWhitelistingRedisTemplate") ReactiveRedisOperations<String, Object> reactiveWhitelistingRedisTemplate,
@Qualifier(value = "reactiveUserRedisTemplate") ReactiveRedisOperations<String, Object> reactiveUserRedisTemplate) {
this.reactiveWhitelistingRedisTemplate = reactiveWhitelistingRedisTemplate;
this.reactiveUserRedisTemplate = reactiveUserRedisTemplate;
}
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
@Override
public void run(String... args) {
log.info("CASE1");
log.info(
String.valueOf(
reactiveWhitelistingRedisTemplate
.keys("*")
.flatMap(reactiveWhitelistingRedisTemplate.opsForValue()::get)));
log.info("CASE2");
log.info(String.valueOf(reactiveWhitelistingRedisTemplate.scan()));
log.info("CASE3");
log.info(String.valueOf(reactiveUserRedisTemplate.keys("*")));
log.info("CASE4");
log.info(reactiveWhitelistingRedisTemplate.randomKey() + "RANDOM");
log.info("CASE5");
log.info(String.valueOf(reactiveWhitelistingRedisTemplate.opsForValue().get("whitelisting:zenon112")));
}
}
在获取 key/keys 时,我总是收到空的 Mono/Flux 结果如下:
CASE1
FluxFlatMap
CASE2
FluxMap
CASE3
FluxMap
CASE4
MonoMapRANDOM
CASE5
MonoNext
我确信 Redis 不是空的,Redis 中的示例键是 whitelisting:ranomuser112
老实说,我对自己做错了什么很困惑,对于如何从反应式 Redis 获取特定密钥的建议,我将不胜感激。干杯!
我忽略了 .subscribe()
方法调用。没有它,反应结果将被忽略。问题已解决。