说明
最近的项目中用到了两个定时任务,一个用于处理数据的一阶段处理,处理后的数据存入redis中,等待第二个任务运行,做第二阶段的处理。两个任务之间通过zSet中存储的id值关联。
奇怪的是第一个任务可以正常存储主键ID 到zSet 中,但第二个任务通过key 获取zSet中的值时,返回结果为空。
存值代码:
@Resource(name = "stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate;
private void setKey(){
redisTemplate.opsForZSet().add(CscConstants.TASK_KEY, monitorTask.getTaskNo(), monitorTask.getTaskEndTime().getTime());
}
取值代码
@Autowired
private RedisTemplate<String, String> redisTemplate;
private void setKey(){
Set<String> taskNoSet = redisTemplate.opsForZSet().rangeByScore(CscConstants.TASK_KEY, 0, System.currentTimeMillis());
}
原因说明
在spring 容器中,存在两个RedisTemplate :
@Configuration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
名称为 redisTemplate 的bean 内部 使用 JdkSerializationRedisSerializer 序列化 key和vaue。
名称为 stringRedisTemplate 的bean 内部使用 RedisSerializer 序列化 key 和value。
public RedisTemplate() {
}
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (this.defaultSerializer == null) {
this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
}
if (this.enableDefaultSerializer) {
if (this.keySerializer == null) {
this.keySerializer = this.defaultSerializer;
defaultUsed = true;
}
if (this.valueSerializer == null) {
this.valueSerializer = this.defaultSerializer;
defaultUsed = true;
}
if (this.hashKeySerializer == null) {
this.hashKeySerializer = this.defaultSerializer;
defaultUsed = true;
}
if (this.hashValueSerializer == null) {
this.hashValueSerializer = this.defaultSerializer;
defaultUsed = true;
}
}
if (this.enableDefaultSerializer && defaultUsed) {
Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
}
if (this.scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor(this);
}
this.initialized = true;
}
public class StringRedisTemplate extends RedisTemplate<String, String> {
public StringRedisTemplate() {
this.setKeySerializer(RedisSerializer.string());
this.setValueSerializer(RedisSerializer.string());
this.setHashKeySerializer(RedisSerializer.string());
this.setHashValueSerializer(RedisSerializer.string());
}
public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
this.setConnectionFactory(connectionFactory);
this.afterPropertiesSet();
}
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return new DefaultStringRedisConnection(connection);
}
}
在使用redisTemplate 实列,如果取数据失败,很有可能是存值和取值时使用不同的redisTemplate 实列。 @Resource(name = “stringRedisTemplate”)