Redis的值居然清零了(redis的值变成0)

Redis的值居然清零了!

最近,我所在的团队在使用Redis进行缓存时出现了一件奇怪的事情——Redis中存储的某个值突然变成了0。

初步排查发现这个值是在一次应用重启后发生的。我们马上想到了一些可能的原因,包括程序在重启后没有正确地从Redis中读取数据等。

然而,我们代码中并没有发现这个问题的根源。于是,我们着手对Redis进行更深入的调查。

我们查看了Redis的日志,发现了以下的错误信息:

*ERR wrong number of arguments for ‘set’ command

这是由于我们使用的Jedis客户端传参错误导致的,具体原因是我们在Redis中存储的是一个自定义的Java对象。由于Jedis默认只支持将简单类型(如String、Integer等)存储到Redis中,因此我们需要通过序列化的方式将对象转换为字符串存储。

而我们在应用重启后没有及时更新对象的序列化方式,导致Jedis在存储对象时传入的参数个数错误,从而将这个值清零了。

针对这个问题,我们进行了以下的修复:

1. 修改序列化方式

我们采用了FastJson工具对Java对象进行序列化,这样就避免了Jedis在存储对象时传入参数个数错误的问题。具体代码如下:

public class RedisUtil {
private static final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

private static final FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
private RedisTemplate redisTemplate;
@Autowired
public RedisUtil(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
}
//...
}

2. 增加数据恢复机制

为了避免这种情况再次发生,我们还增加了一种数据恢复机制。当Jedis在存储对象时发生参数个数错误时,我们将自动从Redis中获取之前已经存储的数据,以避免出现数据丢失的情况。具体代码如下:

public class RedisUtil {
//...
public void setObject(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
} catch (Exception e) {
if (e.getCause() instanceof JedisException) {
String redisValue = redisTemplate.opsForValue().get(key);
if (redisValue != null) {
redisTemplate.opsForValue().set(key, redisValue);
} else {
throw e;
}
}
}
}
}

通过以上的修复和改进,我们成功地解决了这个问题。经过这件事情,我们也深刻认识到了在使用Redis时需要特别注意序列化的问题,尤其是在存储自定义的Java对象时。因此,我们很快在开发规范中增加了关于Redis缓存的标准,以避免类似的问题再次发生。


数据运维技术 » Redis的值居然清零了(redis的值变成0)