文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

释放你九成的带宽和内存:GZIP在解决Redis大Key方面的应用

2024-11-29 19:14

关注

HTTP协议开启GZIP

HTTP协议标准中是直接支持GZIP压缩算法的,通过响应头Content-Encoding: gzip来表明响应内容使用了GZIP压缩,当客户端收到数据后会使用GZIP算法对Body内容进行解压。

RFC 1952 - IETF(互联网工程任务组)标准化的Gzip文件格式规范,

RFC 2616 - HTTP 1.1 协议规范,其中包括对 Content-Encoding 头的定义

在Nginx中可以通过 gzip on开启GZIP压缩功能:

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

在Springboot中可以通过server.compression.enabled开启GZIP压缩功能:

server:
  port: 80
  compression:
    enabled: true
    mime-types:  application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
    min-response-size: 2KB

测试GZIP

为了测试开启GZIP前后的对比效果我们写一个简单的接口:

@GetMapping("/list")
public ResponseEntity list() {
    return renderOk(getData());
}

我们返回1000条JSON格式的用户信息:

private List getData() {
    return IntStream.range(1, 1000).mapToObj(x -> new UserVo(x,x+"+email@q63.com",x+"_公众号",x+"_赵侠客")).collect(Collectors.toList());
}
@Data
@AllArgsConstructor
public class UserVo {
    private Integer id;
    private String username;
    private String email;
    private String trueName;
}

在未开启GZIP前接口返回数据的大小是92.8KB, Content-Encoding为空,在开启GZIP后接口返回的数据大小为11.5KB,Content-Encoding为gzip,接口返回数量降低了88%。

当然我们也可以在接口中通过手动添加content-encoding响应头,然后通过手动调用GZIPOutputStream对返回数据进行GZIP压缩:

@GetMapping("/gzip")
public void gzip(HttpServletResponse response) throws IOException {
    response.setContentType("application/json;charset=utf-8");
    response.setHeader("content-encoding", "gzip");
    try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(response.getOutputStream())) {
        IOUtils.write(JsonUtils.toJson(getData()), gzipOutputStream);
    }
}

Redis缓存压缩

为了增加接口的响应速度我们通常会使用Redis当缓存,基本逻辑是先查Redis有没有数据如果有直接返回,如果没有会查数据库,然后再存入Redis,以下是一个简单的使用Redis当缓存的接口:

@Resource
private RedissonClient redissonClient;
public static final String REDIS_KEY = "REDIS_KEY";

@GetMapping("/redis")
public void redis(HttpServletResponse response) throws IOException {
    RBucket bucket = redissonClient.getBucket(REDIS_KEY);
    String data = bucket.get();
    if (data == null) {
         data=JsonUtils.toJson(getData());
        redissonClient.getBucket(REDIS_KEY).set(data,100L, TimeUnit.SECONDS);
    }
    response.setContentType("application/json");
    IOUtils.write(data, response.getOutputStream());
}

我们分析一下这样个接口的基本数据流:

使用Redis当缓存加速接口

使用ZIP优化Redis缓存:

public static final String GZIP_REDIS_KEY = "GZIP_REDIS_KEY";

@GetMapping("/gzipRedis")
public void gzipRedis(HttpServletResponse response) throws IOException {
    RBucket bucket = redissonClient.getBucket(GZIP_REDIS_KEY);
    byte[] data = bucket.get();
    if (data == null) {
        String jsnotallow=JsonUtils.toJson(getData());
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
            IOUtils.write(json, gzipOutputStream, String.valueOf(StandardCharsets.UTF_8));
            gzipOutputStream.finish();
            data= byteArrayOutputStream.toByteArray();
            redissonClient.getBucket(GZIP_REDIS_KEY).set(data,100L, TimeUnit.SECONDS);
        }
    }
    response.setContentType("application/json");
    response.setHeader("content-encoding", "gzip");
    IOUtils.write(data, response.getOutputStream());
}

使用GZIP压缩后的缓存接口

我们再分析一下以上使用GZIP压缩后的数据传输:

GZIP压缩后的Redis缓存

单次接口请求好像感觉不到这个 GZIP压缩带来的好处,接下来我们压测一下看看会不会有差距。

压力测试

压测可以使用ab (Apache Benchmark) 工具,ab工具是 Apache HTTP server 的一部分,在 macOS使用Homebrew包管理器可以快速安装上ab :

brew install httpd
ab -V
ab -n 100 -c 10 http://localhost/list

其中:

未压缩走Redis压缩结果:

ab -n 100000 -c 10 http://localhost/redis

Finished 100000 requests
Document Length:        92476 bytes
Concurrency Level:      10
Time taken for tests:   194.917 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      9258100000 bytes
HTML transferred:       9247600000 bytes
Requests per second:    513.04 [#/sec] (mean)
Time per request:       19.492 [ms] (mean)
Time per request:       1.949 [ms] (mean, across all concurrent requests)
Transfer rate:          46384.34 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    8 249.5      0   19514
Processing:     4   12  19.8     10     754
Waiting:        4   11  19.8     10     754
Total:          4   19 250.4     10   19525
Percentage of the requests served within a certain time (ms)
  50%     10
  66%     11
  75%     11
  80%     12
  90%     12
  95%     15
  98%     27
  99%    134
 100%  19525 (longest request)

使用GZIP压缩后走Redis缓存压测结果:

ab -n 100000 -c 10 http://localhost/gzipRedis

Finished 100000 requests
Document Length:        11091 bytes
Concurrency Level:      10
Time taken for tests:   194.927 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      1122000000 bytes
HTML transferred:       1109100000 bytes
Requests per second:    513.01 [#/sec] (mean)
Time per request:       19.493 [ms] (mean)
Time per request:       1.949 [ms] (mean, across all concurrent requests)
Transfer rate:          5621.09 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   12 410.4      0   19608
Processing:     3    7  20.0      4     802
Waiting:        3    7  19.9      4     801
Total:          3   19 410.9      4   19613

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      9
  75%      9
  80%      9
  90%     10
  95%     10
  98%     11
  99%     19
 100%  19613 (longest request)

总结

对比使用GZIP压缩我们可以得出以下几点:

请求10万次数据传输流程

综合上所述如里你的Redis缓存中存在大量的大Key,可能先达到瓶颈的不是Redis的读写性能,很可能是你的带宽,此时只需要简单的使用GZIP压缩就能你给不仅节省88%的Redis内存空间还大大减少了数据的传输量和节省了带宽资源,而且还能使用的C端用户的资源来解压,这个ROI是非常高的。


来源:赵侠客内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯