SpringBoot数据压缩实践方案

 更新时间:2025年10月09日 08:48:25   作者:请叫我头头哥  
文章探讨了Redis中处理大key的压缩方案,包括拆分JSON结构、使用GZIP/Deflater压缩、优化体积(如移除空格、缩短键名)、流式处理及分段存储,旨在降低内存负担并提升性能,感兴趣的朋友跟随小编一起看看吧

最近在使用Redis的时候,经常遇到一些不常用的大key,对存储有一些负担。就想着把大key压缩一下。压缩可以分很多种,比如拆分JSON字符串​, ​​压缩JSON字符串​,优化JSON体积​,流式处理大型JSON​和分段存储。

拆分JSON字符串​

1.1按结构拆分​

数组拆分​​:若JSON包含大型数组,可将其拆分为多个小数组。

// 示例:将大数组拆分为多个子数组
JSONArray bigArray = new JSONArray(jsonString);
int chunkSize = 100;
for (int i = 0; i < bigArray.length(); i += chunkSize) {
    JSONArray chunk = new JSONArray();
    for (int j = i; j < Math.min(i + chunkSize, bigArray.length()); j++) {
        chunk.put(bigArray.get(j));
    }
    String chunkJson = chunk.toString();
    // 处理或保存chunkJson
}

​​对象拆分​​:若JSON是嵌套对象,可按层级拆分为子对象。

1.2按大小拆分(流式处理)​​

使用流式API(如Jackson的JsonParser)逐块读取JSON内容,避免一次性加载到内存:

JsonFactory factory = new JsonFactory();
try (JsonParser parser = factory.createParser(new File("large.json"))) {
    while (parser.nextToken() != null) {
        // 逐Token处理,如按特定条件拆分
    }
}

压缩JSON字符串​

2.1使用GZIP压缩​

import java.util.zip.GZIPOutputStream;
import java.io.ByteArrayOutputStream;
public static byte[] compress(String data) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
    try (GZIPOutputStream gzip = new GZIPOutputStream(bos)) {
        gzip.write(data.getBytes());
    }
    return bos.toByteArray();
}
// 压缩后的数据可用于传输或存储
byte[] compressed = compress(jsonString);

2.2使用Deflater压缩​

import java.util.zip.Deflater;
public static byte[] deflateCompress(String data) {
    Deflater deflater = new Deflater();
    deflater.setInput(data.getBytes());
    deflater.finish();
    byte[] buffer = new byte[1024];
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    while (!deflater.finished()) {
        int count = deflater.deflate(buffer);
        outputStream.write(buffer, 0, count);
    }
    deflater.end();
    return outputStream.toByteArray();
}

优化JSON体积​​

3.1移除无用空格​

使用紧凑格式(无缩进、换行):

new JSONObject(jsonString).toString(); // 默认紧凑格式

3.2​​缩短键名​

将长字段名替换为短名称:

{"n":"Alice","a":30} // 原始键名可能为"name"、"age"

流式处理大型JSON​​

使用流式API逐步解析,避免内存溢出:

// Jackson流式API示例
JsonFactory factory = new JsonFactory();
try (JsonParser parser = factory.createParser(new File("large.json"))) {
    JsonToken token;
    while ((token = parser.nextToken()) != null) {
        if (token == JsonToken.START_ARRAY) {
            while (parser.nextToken() != JsonToken.END_ARRAY) {
                // 逐条处理数组元素
                JsonNode node = parser.readValueAsTree();
                // 处理node...
            }
        }
    }
}

分页处理​

其实也是拆分,将数据拆成若干份

实践方案

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.StandardCharsets;
public class CompressHelper {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 方式1:去除JSON中的空格/换行等冗余字符(文本压缩)
     * @param formattedJson 格式化的JSON字符串(含空格换行)
     * @return 紧凑格式的JSON字符串
     * @throws IOException JSON解析异常
     */
    public static String compressJsonByRemovingSpaces(String formattedJson) throws IOException {
        JsonNode jsonNode = objectMapper.readTree(formattedJson);
        return objectMapper.writeValueAsString(jsonNode);
    }
    /**
     * 方式2:使用GZIP算法对JSON字符串进行二进制压缩(适合网络传输)
     * @param json 原始JSON字符串
     * @return Base64编码的压缩后字符串(可直接传输)
     * @throws IOException 压缩异常
     */
    public static String compressJsonByGzip(String json) throws IOException {
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
             GZIPOutputStream gzipOut = new GZIPOutputStream(byteOut)) {
            gzipOut.write(json.getBytes("UTF-8"));
            gzipOut.finish();
            return Base64.encodeBase64String(byteOut.toByteArray());
        }
    }
    public static String decompressJson(String source) throws IOException {
        byte[] compressedData = Base64.decodeBase64(source);
        try (ByteArrayInputStream byteIn = new ByteArrayInputStream(compressedData);
             GZIPInputStream gzipIn = new GZIPInputStream(byteIn);
             ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {
            // 读取压缩数据并解压缩
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gzipIn.read(buffer)) != -1) {
                byteOut.write(buffer, 0, len);
            }
            return byteOut.toString(StandardCharsets.UTF_8.name());
        }
    }
}

源码地址

https://github.com/toutouge/javademosecond/tree/master/hellolearn

到此这篇关于SpringBoot数据压缩实践方案的文章就介绍到这了,更多相关SpringBoot数据压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java JDK动态代理的基本原理详细介绍

    Java JDK动态代理的基本原理详细介绍

    这篇文章主要介绍了Java JDK动态代理的基本原理详细介绍的相关资料,这里对动态代理进行了详解并附简单实例代码,需要的朋友可以参考下
    2017-01-01
  • 浅谈Java线程间通信方式

    浅谈Java线程间通信方式

    这篇文章主要为大家详细介绍了Java线程间的通信方式,以代码结合文字的方式来讨论线程间的通信,感兴趣的朋友可以参考一下
    2021-11-11
  • 详解java中import的作用

    详解java中import的作用

    这篇文章主要介绍了java中import作用,import与package机制相关,这里先从package入手,再讲述import以及static import的作用。
    2021-04-04
  • java.lang.InterruptedException异常的问题解决

    java.lang.InterruptedException异常的问题解决

    本文主要介绍了java.lang.InterruptedException异常的问题解决,这种异常通常意味着 Jenkins 任务在执行过程中被中断,这可能会导致任务失败或中止,下面就来介绍一下解决方法,感兴趣的可以了解一下
    2024-07-07
  • 通过AOP拦截Spring Boot日志并将其存入数据库功能实现

    通过AOP拦截Spring Boot日志并将其存入数据库功能实现

    本文介绍了如何使用Spring Boot和AOP技术实现拦截系统日志并保存到数据库中的功能,包括配置数据库连接、定义日志实体类、定义日志拦截器、使用AOP拦截日志并保存到数据库中等步骤,感兴趣的朋友一起看看吧
    2023-08-08
  • java 与web服务器链接的实例

    java 与web服务器链接的实例

    这篇文章主要介绍了java 与web服务器链接的实例的相关资料,使用net.Socket类sock.getInetAddress()方法获得与Web服务器连接,需要的朋友可以参考下
    2017-07-07
  • MyBatis输入映射和输出映射的实现示例

    MyBatis输入映射和输出映射的实现示例

    本文详细介绍了MyBatis框架中resultMap的使用,包括其在Java对象与数据库表列映射中的作用,以及如何配置resultMap处理不同情况,具有一定的参考价值,感兴趣的可以了解一下
    2026-04-04
  • IDEA下lombok安装及找不到get,set的问题的解决方法

    IDEA下lombok安装及找不到get,set的问题的解决方法

    这篇文章主要介绍了IDEA下lombok安装及找不到get,set的问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • Java动态代理分析及理解

    Java动态代理分析及理解

    这篇文章主要介绍了Java动态代理分析及理解的相关资料,需要的朋友可以参考下
    2017-05-05
  • java单例模式实现面板切换

    java单例模式实现面板切换

    这篇文章主要为大家详细介绍了java单例模式实现面板切换,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11

最新评论