SpringBoot数据压缩实践方案
作者:请叫我头头哥
文章探讨了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数据压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!