Skip to content

Java性能优化战术-压缩对象

About 793 wordsAbout 3 min

性能新书

2026-11-5

压缩

微服务调用或者存储对象时候,尽量是对象序列化后提交较小。这样能提高传输的速度,节省带宽。同时,压缩有利于存储空间,比如,存储在redis的缓存对象,存在elastic search中的JSON对象。 不同的序列化方案会有不同的大小,选择压缩方案使得容量能存储更多的对象。

在一个项目中,缓存的业务信息的Redis,本来能存储5千万条,经过压缩改造后,能促成2亿条业务缓存信息,如果采用扩容Redis来解决,需要每年额外投入几十万服务器资源。

​ 压缩对象总的来说有3种办法

  • 序列化的对象属性名或者属性值做调整。比如属性orderId,序列化时候改成oid
  • 使用二进制格式代替通常的JSON序列化方式,比如TLV或者MesssagePack等序列化协议代替JSON的序列化
  • 采用ZIP工具进行压缩。

​ 在传输对象的属性名字上做调整,尽量减少传输报文大小,这比较适合传输的是JSON或者XML,比如

public class OrderRequest{
  private String orderId;
  private String userId;

}

如果使用JSON传输,内容是

{"orderId":xxx,"userId":yyyyy}

可以调整为

public class OrderRequest{
  private String oid;
  private String uid;
}

或者,序列化的时候,改变属性输出

public class OrderRequest{
  @JsonProperty (value = "oid")
  private String orderId;
  @JsonProperty (value = "uid")
  private String userId;

}

使用JSON传输

 {"oid":xxx,"uid":yyyyy}

这种调整,显然传输报文大小体积小一点。也可以对传输对象的一些字段做合并,比如“订单状态“,"用户状态","是否是测试订单"合并成一个int类型,通过“位“来区分状态。如下OrderRequest可以参考6.7来修改,使用一个int字段同时表示userStatus,orderStatus ,testFlag

public class OrderRequest{
  //用户状态
  private int userStatus;
  //订单状态
  private int orderStatus;
  //测试订单
  private int testFlag
  
  //private int status  使用位来代替上面3个属性
}

在物联网行业,使用位来传输信息常见,比如物联网协议MQTT协议,被认为是一个轻量,简单的协议。MQTT消息头的第一个字节的4到7位表示MQTT数据包类型,而0到3位根据不同数据类型有不同的值。

除了序列化JSON过程进行属性和值的压缩外,还可以采用二进制压缩方式整体代替JSON文本序列化方式,可以选择序列化工具,比如MessagePack,Fury,Protobuf 、Thrift 、Avro等格式。 这些压缩方式普遍采用TLV式编码,较JSON有更小的报文和更快的序列化&反序列化性能。

二进制序列化通常较JSON工具,体积会减少30-50%(需要参考序列化工具官网的评测),但缺点是不宜观察,比如把JSON存放到redis或者数据库里,就比把二进制格式存放到redis和数据库里更容易阅

知行合一