Redis压缩方案设计--各种压缩方案单机的比较(CPU)

[原创]个人理解,请批判接受,有误请指正。转载请注明出处: https://heyfl.gitee.io/design/Redis-compress-design.html

1、 CPU性能对比(通过对比CPU时间)

各压缩方案CPU时间对比
各压缩方案CPU时间对比
对比论证:
  1. 选择序列化CPU使用率最低,约原来的16%~73%,其中FST序列化方式为原来的16%,速度最快
  2. 选择纯字符串压缩的方式因为是在原toJSON和parseObject的逻辑之间,再加入压缩逻辑,故性能比原生JSON会略差一些
  3. (对比序列化&压缩方案)每轮十万次测试
    • 压缩方案单轮测试耗时最高,为0.42s,约每次使用该方案消耗0.04ms,对比原方案单次多次0.01ms的CPU时间,故认为以上方案对性能的损耗问题可忽略
    • 序列化方案单论测试耗时最低,为0.05s,约每次使用该方案可节约0.027ms的CPU时间,对比压缩方案,可节约0.037ms的CPU时间,故认为序列化对性能提升不高
总结

纯序列化方案占用CPU时间少,纯压缩方案占用CPU时间稍多,但是都对整体性能影响极小


2、使用序列化实践的方案(速度快,压缩度高)

2.0 简要

核心参考资料

FST @Version官方文档
序列化总结

背景

发送给下游与Redis存储的对象为同一个对象

原理

对象通过直接序列化转byte,考虑到对象后续需要新增字段,可通过添加注解的形式进行扩展(必须给每个字段都加上唯一注解,包括原有字段)


2.1 FST方案设计(只针对大对象)

方案1描述
  1. 直接在需要存入Redis的对象中为每个新增字段加入新注解,新字段顺序有要求得放在其他字段之后
  2. 在自己相关工程,升级下游依赖到的相关包的版本号(需要梳理)
  3. 存取Redis时,进行序列化反序列化操作
方案1优点

一劳永逸,改动小

方案1缺陷
  1. 下游引入新的额外无用依赖
  2. 需要梳理自己项目,有哪些jar包给下游依赖到了,得逐个进行升级(容易疏漏?)
  3. 存到Redis的对象,如果想阉割属性,比较困难(比较简单有效的方案还是得新建类)
方案2描述
  1. copy一个和原来的类(称为A类)一致的类(称为A’类),在A’类上添加注解
  2. 保存redis前,通过属性copy,把A对象Copy到A’对象中,最终序列化保存A’对象
  3. 读取Redis时,同理把反序列化读到的A’对象,Copy给A对象
方案2
方案2优点
  1. 容易存储Redis的对象阉割字段(如:我们对于对于A类里有个大属性:jsonObject,我们不想存,那么只需要在A’上去掉这个字段)
  2. 下游无感知
方案2缺陷
  1. 对于每个需要扩展字段的对象对应的类,都得存在2份,可能会导致新建了非常多的类(如订单里引用的所有类型 都可能需要被扩展。。。)
  2. 每次存取都需要进行copy操作
  3. 在添加字段时,容易把A’类给忘了
序列化方案其他缺陷(核心难点)
  • 被序列化的类,其涉及到的相关所有类,都得注册到serializer中;且序列化反序列化得用同一个serializer
  • 改造较为复杂容易出错,需要嵌入到目前项目的RedisCache工具类中
  • 少注册类时,反序列化会出错,且难以排查
  • 切换新方案后,以前的key无法匹配到了,需要重新cache一次

2.2、Snappy方案设计(速度比原来略慢约增加,压缩度较高可减少约50%(实际存到redis可减少到75%左右))(只针对大对象)

方案描述(Snappy压缩字符串)
  1. 存Redis前,先通过JsonUtil.toJsonString得到Json字符串后,然后对json进行Snappy压缩后,再存入Redis;
  2. 取Redis时,先通过Snappy解压,再通过JsonUtil.parseObject转回对象
方案优点
  1. 简单,说白了其实就是存取加入了进行压缩解压操作
  2. 下游无感知
  3. 对老数据可做兼容,业务开发时字段增减不会影响 Redis<–>对象 的读写与转换
方案缺点
  1. 增加的压缩逻辑导致耗时在原来基础上增加30%左右的CPU时间,但10w次读写也就+1s的处理时间,影响

Redis压缩方案设计--各种压缩方案单机的比较(CPU)

https://heyfl.gitee.io/design/Redis-compress-design.html

作者

神奇宝贝大师

发布于

2021-03-20

更新于

2021-03-20

许可协议

评论