SpringBoot2.X整合Redis缓存
SpringBoot2.x集成SpringCache+Redis
1. 如何实现自定义ProtostuffRedisSerializer
在SpringBoot2.x环境下,若想使用Redis作为缓存,我们势必要选择一种合适的序列化工具。Redis提供了一个公共接口org.springframework.data.redis.serializer.RedisSerializer<T>。来完成数据的序列化和反序列化。
public interface RedisSerializer<T> {
@Nullable
byte[] serialize(@Nullable T t) throws SerializationException;
@Nullable
T deserialize(@Nullable byte[] bytes) throws SerializationException;
static RedisSerializer<Object> java() {
return java(null);
}
static RedisSerializer<Object> java(@Nullable ClassLoader classLoader) {
return new JdkSerializationRedisSerializer(classLoader);
}
static RedisSerializer<Object> json() {
return new GenericJackson2JsonRedisSerializer();
}
static RedisSerializer<String> string() {
return StringRedisSerializer.UTF_8;
}
}
我们若想使用Protostuff作为Redis序列化数据的工具,那么就必须实现该接口。
引入依赖
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.6.0</version>
</dependency>
实现接口
public class ProtoStuffRedisSerializer implements RedisSerializer<Object> {
private static final Schema<ObjectWrapper> schema = RuntimeSchema.getSchema(ObjectWrapper.class);
@Override
public byte[] serialize(Object t) throws SerializationException {
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
byte[] bytes;
try {
bytes = ProtostuffIOUtil.toByteArray(new ObjectWrapper(t), schema, buffer);
} finally {
buffer.clear();
}
return bytes;
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length == 0) {
return null;
}
try {
ObjectWrapper objectWrapper = new ObjectWrapper();
ProtostuffIOUtil.mergeFrom(bytes, objectWrapper, schema);
return objectWrapper.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static class ObjectWrapper {
private Object object;
ObjectWrapper() {
}
ObjectWrapper(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
}
2. 性能比较
在Redis的包中,默认提供了几种序列化的工具,如JDK、Jackson、Fastjson等等,我们自定义实现序列化方式性能和官方默认的差距如何呢?
public void getAccInfoByTime(String customerId, String accType) {
//获取Bean对象
Account accInfo = getAccInfo(customerId, accType);
//JDK的序列化时间
JdkSerializationRedisSerializer jdk = new JdkSerializationRedisSerializer();
ProtoStuffRedisSerializer pro = new ProtoStuffRedisSerializer();
Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(Object.class);
byte[] jdkBytes = getSerializeTime("JDK序列化", () -> jdk.serialize(accInfo));
byte[] proBytes = getSerializeTime("PRO序列化", () -> pro.serialize(accInfo));
byte[] jacksonBytes = getSerializeTime("JACK序列化", () -> jackson.serialize(accInfo));
Object deserializeTime = getDeserializeTime("JDK反序列化时间:", () -> jdk.deserialize(jdkBytes));
Object deserializeTime1 = getDeserializeTime("PRO反序列化时间:", () -> pro.deserialize(proBytes));
Object deserializeTime2 = getDeserializeTime("JACK序列化时间:", () -> jackson.deserialize(jacksonBytes));
}
/**
* 计算序列化的耗时时间
*
* @param supplier
* @return
*/
private byte[] getSerializeTime(String desc, Supplier<byte[]> supplier) {
long startTime = System.currentTimeMillis();
byte[] bytes = supplier.get();
System.out.println(desc + "时间:" + (System.currentTimeMillis() - startTime) + " ms");
System.out.println(desc + "大小:" + bytes.length + " b");
return bytes;
}
/**
* 计算反的耗时时间
*
* @param supplier
* @return
*/
private Object getDeserializeTime(String desc, Supplier<Object> supplier) {
long startTime = System.currentTimeMillis();
Object obj = supplier.get();
System.out.println(desc + (System.currentTimeMillis() - startTime) + " ms");
return obj;
}
执行结果:
JDK序列化时间:0 ms
JDK序列化大小:865 b
PRO序列化时间:0 ms
PRO序列化大小:155 b
JACK序列化时间:15 ms
JACK序列化大小:447 b
JDK反序列化时间:1 ms
PRO反序列化时间:0 ms
JACK反序列化时间:2 ms
可以看到,protostuff在压缩时间,以及压缩后的大小上都是比较占优的。
