背景
在高并发的场景中,我们通常会使用缓存提升性能。在使用springboot cache时,我们通常会使用基于JSON的序列化与反序列化。
JSON具有可读性强,结构简单的特点,使用灵活。
但是JSON体积大,占用redis内存,同时增加网络开销,使用gzip压缩可以将体积缩减到原来的十分之以下,取得媲美Protobuf的编码效率
使用springboot cache + redis并使用Gzip压缩
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Gzip压缩工具类
public class GzipUtil {
public static byte[] compress(byte[] data) throws IOException {
if (data == null || data.length == 0) {
return new byte[0];
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzOut = new GZIPOutputStream(out);
gzOut.write(data);
gzOut.close();
return out.toByteArray();
}
public static byte[] decompress(byte[] gzip) throws IOException {
if (gzip == null || gzip.length == 0) {
return new byte[0];
}
ByteArrayInputStream in = new ByteArrayInputStream(gzip);
GZIPInputStream gzIn = new GZIPInputStream(in);
return gzIn.readAllBytes();
}
}
继承GenericJackson2JsonRedisSerializer 并实现Gzip压缩
public class JacksonGzipSerializer extends GenericJackson2JsonRedisSerializer {
@Override
public byte[] serialize(@Nullable Object source) throws SerializationException {
byte[] raw = super.serialize(source);
try {
return GzipUtil.compress(raw);
} catch (IOException ioe) {
throw new SerializationException("Exception", ioe);
}
}
@Override
public Object deserialize(@Nullable byte[] source) throws SerializationException {
try {
byte[] raw = GzipUtil.decompress(source);
return deserialize(raw, Object.class);
} catch (IOException ioe) {
throw new SerializationException("Exception", ioe);
}
}
}
配置Config,使用上述自定义的序列化及反序列化机制
@Configuration
public class CacheConfig implements CachingConfigurer {
@Resource
private RedisConnectionFactory redisConnectionFactory;
@Override
@Bean
public CacheManager cacheManager() {
return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), redisCacheConfiguration());
}
public RedisCacheConfiguration redisCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new JacksonGzipSerializer()));
}
}
使用@EnableCaching开启缓存
@SpringBootApplication
@EnableCaching
public class RedisCacheApplication {
public static void main(String[] args) {
SpringApplication.run(RedisCacheApplication.class, args);
}
}
最后别忘了配置redis(具体格式和springboot版本有关)
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
效果
没用使用gzip的大小101KB
使用gzip压缩后的大小 14KB