笔者曾经对redis键值使用了不同类型的序列化方法
用过默认值、JdkSerializationRedisSerializer、StringRedisSerializer还用改以下自定类型的序列化工具类(据说这个比Spring RedisTemplate的序列化、反序列化快)
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class ProtostuffSerializer implements RedisSerializer<Object> {
private boolean isEmpty(byte[] data) {
return (data == null || data.length == 0);
}
private final Schema<ProtoWrapper> schema;
private final ProtoWrapper wrapper;
private final LinkedBuffer buffer;
public ProtostuffSerializer() {
this.wrapper = new ProtoWrapper();
this.schema = RuntimeSchema.getSchema(ProtoWrapper.class);
this.buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
}
@Override
public byte[] serialize(Object t) throws SerializationException {
if (t == null) {
return new byte[0];
}
wrapper.data = t;
try {
return ProtostuffIOUtil.toByteArray(wrapper, schema, buffer);
} finally {
buffer.clear();
}
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
if (isEmpty(bytes)) {
return null;
}
ProtoWrapper newMessage = schema.newMessage();
ProtostuffIOUtil.mergeFrom(bytes, newMessage, schema);
return newMessage.data;
}
private static class ProtoWrapper {
public Object data;
}
}
遇到过以下异常:
hash操作:java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String,然后这次又换另外一个Hash的序列化类
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
序列化后的缓存如下:
因为上次使用ProtostuffSerializer对Hash值进行序列化,进行以下操作报错了
HashOperations<String,String,T> hashOperations = redisTemplate.opsForHash();
if(value instanceof Long || value instanceof Integer|| value instanceof Short||value instanceof Byte)
{
long longValue = ((Number) value).longValue();
hashOperations.increment(key,field,longValue);
}
if(value instanceof Float ||value instanceof Double)
{
double doubleValue = ((Number) value).doubleValue();
Double returned = hashOperations.increment(key, field, -0.005);
}
return
报错如下:io.lettuce.core.RedisCommandExecutionException: ERR hash value is not a valid float
,因为经过ProtostuffSerializer序列化的hash值会变形,编程、\X0A=\X5A\X43\XC格式的数据,进行数值运算报错。
注意事项:redis端increment操作,只支持double和long,所以数据要进行相关转换。
比如笔者代码如下,就会报错:
public <T> T getCacheHashValue(String key, String field, Class<T> targetClass) {
HashOperations<String,String,T> hashOperations = redisTemplate.opsForHash();
return hashOperations.get(key, field);
}
传入
Float balance = cacheService.getCacheHashValue(cacheKey, "balance", Float.class);
报错:
Caused by: java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float
redisTemplate相关文章:
springboot项目中使用spring-data-Redis对map序列化时报错
使用redisTemplate存储数据,出现\xAC\xED\x00\x05t\x00
参考:
Spring-data-redis @Cacheable java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String