使用springboot cache + redis缓存时使用gzip压缩以提升性能

Posted 时光之末

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用springboot cache + redis缓存时使用gzip压缩以提升性能相关的知识,希望对你有一定的参考价值。

背景

在高并发的场景中,我们通常会使用缓存提升性能。在使用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

以上是关于使用springboot cache + redis缓存时使用gzip压缩以提升性能的主要内容,如果未能解决你的问题,请参考以下文章

spring-boot Cache redis 类型转换错误

spring boot redis 缓存(cache)集成

使用springboot cache + redis缓存时使用gzip压缩以提升性能

SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存

完整SpringBoot Cache整合redis缓存

springboot整合spring @Cache和Redis