使用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

作者:Heng

出处:https://www.cnblogs.com/bianheng/p/17130852.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   时光之末  阅读(832)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示