前言
redis自带的StringSerializer性能相对较差,redis官方推荐kryo来提高序列化和反序列化速度,推荐snappy来节约redis内存和网络带宽,在springboot中可以通过配置快速实现这个功能
maven配置
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
<version>1.1.8.4</version>
</dependency>
配置KryoRedisSerializer
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.io.ByteArrayOutputStream;
/**
* @author 后厂村老司机
*/
@Slf4j
public class KryoRedisSerializer<T> implements RedisSerializer<T> {
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final ThreadLocal<Kryo> KYROS = ThreadLocal.withInitial(Kryo::new);
private Class<T> clazz;
public KryoRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return EMPTY_BYTE_ARRAY;
}
Kryo kryo = KYROS.get();
kryo.setReferences(false);
kryo.register(clazz);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos)) {
kryo.writeClassAndObject(output, t);
output.flush();
return baos.toByteArray();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return EMPTY_BYTE_ARRAY;
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
Kryo kryo = KYROS.get();
kryo.setReferences(false);
kryo.register(clazz);
try (Input input = new Input(bytes)) {
return (T) kryo.readClassAndObject(input);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
}
配置Snappy
import org.apache.commons.lang3.SerializationUtils;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.xerial.snappy.Snappy;
import java.io.Serializable;
/ ** @author 后厂村老司机*/
public class SnappyRedisSerializer<T> implements RedisSerializer<T> {
private RedisSerializer<T> innerSerializer;
public SnappyRedisSerializer() {
}
public SnappyRedisSerializer(RedisSerializer<T> innerSerializer) {
this.innerSerializer = innerSerializer;
}
/**
* Create a byte array by serialising and Compressing a java graph (object)
*/
@Override
public byte[] serialize(T object) throws SerializationException {
try {
byte[] bytes = innerSerializer != null ? innerSerializer.serialize(object)
: SerializationUtils.serialize((Serializable) object);
return Snappy.compress(bytes);
} catch (Exception e) {
throw new SerializationException(e.getMessage(), e);
}
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
try {
if (bytes == null || bytes.length <= 0) {
return null;
}
byte[] bos = Snappy.uncompress(bytes);
return (T) (innerSerializer != null ?
innerSerializer.deserialize(bos) : SerializationUtils.deserialize(bos));
} catch (Exception e) {
throw new SerializationException(e.getMessage(), e);
}
}
}
配置redis
public StringRedisTemplate createStringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate redisTemplate = new StringRedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setValueSerializer(new SnappyRedisSerializer<>(new KryoRedisSerializer<>(Object.class)));
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}