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

news2024/9/20 10:33:34

首发公众号:赵侠客

引用

目前主流HTTP协议接口都是使用JSON格式做数据交换的,JSON数据格式有着结构简单、可读性高、跨平台,易解析等优点,同时也存在着冗余数据会占用非常多的储存空间的问题,这大大增加了JSON格式数据在存储、传输过程中的性能消耗。所以对JSON格式数据压缩后再传输、存储就变的非常的有价值,如对JSON格式数据使用GZIP压缩算法可以实现90%左右的压缩率,更小的空间可以节省存储成本和降低传输带宽成本,本文介绍GZIP压缩算法在优化Redis使用大KEY字段中的应用,通过简单压缩可以节省88%的内存空间和带宽资源。

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
  • enabled,开启或关闭
  • mime-types,压缩的数据类型
  • min-response-size,最小压缩大小

测试GZIP

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

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

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


private List<UserVo> 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%。
开启GZIP前后对比

当然我们也可以在接口中通过手动添加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<String> 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());
}

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

  • 第一次从数据库服务器查出92.8KB的数据传输到WEB服务器中
  • 将92.8KB的数据从WEB服务器传输到Redis服务器中
  • 后面如果命中缓存将92.8KB数据从Redis服务器传输到WEB服务器
  • 最后将92.8KB数据从WEB服务器返回给用户浏览器

使用Redis当缓存加速接口

使用ZIP优化Redis缓存:


public static final String GZIP_REDIS_KEY = "GZIP_REDIS_KEY";

@GetMapping("/gzipRedis")
public void gzipRedis(HttpServletResponse response) throws IOException {
    RBucket<byte[]> bucket = redissonClient.getBucket(GZIP_REDIS_KEY);
    byte[] data = bucket.get();
    if (data == null) {
        String json=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压缩后的数据传输:

  • 第一次从数据库服务器查出92.8KB的数据传输到WEB服务器中
  • 将11.5KB的GZIP数据从WEB服务器传输到Redis服务器中
  • 后面命中缓存将11.5KB数据从Redis服务器传输到WEB服务器
  • 最后将11.KB数据从WEB服务器返回给用户浏览器

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

其中:

  • -n 100 表示总共请求 100 次。
  • -c 10 表示并发 10 个请求。

未压缩走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万请求在194S完成,缓存时间是100S,服务器端只做了二次查数据库和GZIP压缩然后存数Redis
  • 两次GZIP和之后的数据传输消耗资源可以忽略不计
  • 未压缩10万请求从Redis传输了8.6GB数据到WEB服务器,又从WEB服务器传输8.6GB给用户浏览器,
  • 压缩10万请求从Redis传输了1GB数据到WEB服务器,又从WEB服务器传输1GB给用户浏览器,节省数据传输15.2GB,节省率88%
  • 未压缩数据传输速度达到45M/S,压缩后5.4M/S,节省带宽88%
  • 如果Redis中大JSON都使用GZIP压缩理论上可以节省Redis内存达到88%
  • 因为直接使用gzip返回,所有解压计算在用户浏览器端完成,不消耗服务器CPU资源

请求10万次数据传输流程

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2102361.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB eig 函数简介:计算特征值和特征向量

在数据科学、工程学和数学中&#xff0c;特征值和特征向量是理解和分析矩阵行为的核心概念。MATLAB 的 eig 函数是处理这些概念的强大工具。本文将介绍 eig 函数的基本用法&#xff0c;并通过示例展示如何使用它来计算特征值和特征向量。 什么是特征值和特征向量&#xff1f; …

应用层(Web与HTTP)

目录 常见术语 1.HTTP概况 2.HTTP连接 非持久HTTP流程 响应时间模型 持久HTTP 3.HTTP报文 3.1HTTP请求报文 3.2HTTP响应报文 HTTP响应状态码 4.Cookies&#xff08;用户-服务器状态&#xff09; cookies&#xff1a;维护状态 Cookies的作用 5.Web缓冲&#xff08;…

CDGA|数据治理:构建高效数据管理体系的实践路径

在当今数字化时代&#xff0c;数据已成为企业最宝贵的资产之一&#xff0c;其质量、安全性和有效利用率直接影响着企业的决策能力、运营效率和市场竞争力。因此&#xff0c;数据治理作为确保数据质量、促进数据价值最大化的关键环节&#xff0c;其重要性日益凸显。本文将从几个…

UE4_地形_悬崖拉伸的解决

参考教程 【虚幻5】UE5_UE4_解决悬崖地形贴图拉伸_哔哩哔哩_bilibili 纹理处理 | 虚幻引擎 4.27 文档 | Epic Developer Community (epicgames.com) 主要通过蓝图节点解决&#xff1a;WorldAlignedTexture WorldAlignedTexture&#xff08;全局一致纹理&#xff09;函数用于…

【自用19.1】C++构造函数

构造函数的作用 在创建一个新的对象时&#xff0c;自动调用的函数&#xff0c;用来进行“初始化”工作&#xff1a; 对这个对象内部的数据成员进行初始化。 构造函数的特点 自动调用&#xff08;在创建新对象时&#xff0c;自动调用&#xff09;构造函数的函数名&#xff0c…

乐凡三防|国产化浪潮下的三防平板

在当前的科技环境下&#xff0c;国产化成为了一个热门话题&#xff0c;尤其在三防平板领域&#xff0c;国产化不仅意味着技术的自给自足&#xff0c;更是国家信息安全与产业自主可控的重要体现。三防平板&#xff0c;即具备防水、防尘、防震功能的平板电脑&#xff0c;其全国产…

02-数组

概述 数组是一个由固定长度的特定类型元素组成的序列&#xff0c;一个数组可以由零个或多个元素组成&#xff0c;一旦声明了&#xff0c;数组的长度就固定了&#xff0c;不能动态变化。 len() 和 cap() 返回结果始终一样。 声明数组 package mainimport ("fmt" )f…

【算法专场】模拟(上)

目录 ​前言 模拟算法 1576. 替换所有的问号 495. 提莫攻击 1688. 比赛中的配对次数 6. Z 字形变换 前言 我们在有时候会看到刷题网站上面看到一些已经把题意讲的很明确的题目&#xff0c;并且一般这种不怎么需要利用那些复杂的算法&#xff0c;只需要我们按照着题目的意…

宝藏!《联盟现代控制特训班题库》(麒麟篇) 习题部分:甄选内容

本文内容&#xff0c;全部选自联盟自动化考研联盟企业店( 店)的&#xff1a;初试《现代控制特性班题库》(麒麟篇)&#xff0c;分为讲义和习题两个部分&#xff0c;本文为习题部分的甄选内容&#xff0c;一本书帮你学透现控。 目录 Part1&#xff1a;资料封面&目录 习题部…

Kafka大厂面试14问(附答案)

怎么保证顺序消费&#xff1f; 同一个生产者发送到同一分区的消息&#xff0c;先发送的比后发送的offset要小。同一生产者发送到不同分区的消息&#xff0c;消息顺序无法保证。 怎么解决这个问题&#xff1f; 给一个topic只设置一个分区 相同key会发给一个分区 怎么保证幂…

python常用的列表,元组,字符串,集合,字典的应用方法

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6049c6f7ca2d4a0ca4911562dea7a8cd.png 素材内容来自——黑马程序员

【Altium Designer程序开发】生成XML多级数据库文件 V2.0

此工具用于生成多级多节点的XML数据库文件&#xff0c;主要功能用于测试XML文件的生成速度的&#xff0c;运行环境在Altium Designer中&#xff0c;可用于Altium Designer全系列的版本中。 程序界面如下图所示&#xff0c;每一级节点表示每个父Node的子Node的数量&#xff0c;节…

FRP内网穿透与神卓互联,优势对比

本文介绍分析了当前市面上两款常用的内网穿透工具 frp内网穿透介绍 一、概述 frp&#xff08;Fast Reverse Proxy&#xff09;是一款高性能的反向代理应用&#xff0c;主要用于实现内网穿透功能。通过frp&#xff0c;用户可以将内网中的服务器或服务暴露到公网上&#xff0c;…

跨境电商运营解决方案:反向代购系统物流集运一体化

跨境电商两种模式&#xff0c;一种是国外商品卖到国内&#xff0c;海淘代购。另一种是国内商品卖到国外&#xff0c;也叫反向代购。 什么是反向代购 反向代购是近年兴起的一种购物模式&#xff0c;是帮国外客户购买中国商品。主要是通过外贸代购系统&#xff0c;把淘宝、天猫…

AEC-Q100车规芯片验证

AEC-Q100是汽车电子协会(Automotive Electronics Council,简称AEC)制定的车规级芯片验证标准,它主要针对车载应用的集成电路产品所设计的一套应力测试标准,旨在通过严格的测试流程,确保芯片在复杂多变的汽车环境下具备高可靠性、高安全性和高稳定性。 验证流程 定义规格:…

哪款清理猫咪浮毛效果好?希喂、霍尼韦尔、美的宠物空气净化器PK

最近在宠物领域&#xff0c;宠物空气净化器的讨论热度很高&#xff0c;不少铲屎官们都有购买的意向。身为三猫孩子的家长&#xff0c;养宠以来市面上所有的猫毛清理工具我都用过&#xff0c;这种新兴产品肯定也不会错过。我结合自身情况和预算&#xff0c;对市面上的品牌进行筛…

UI自动化-元素动作WebElement源码类

UI自动化设计元素动作所用到的源码是WebElement源码类 其中用的最多的为前9个&#xff0c;后续是前端开发时常用 webelement源码类 元素动作都是webelement源码类中 1、往输入框里输入内容&#xff0c;元素单击后输入内容&#xff1a;key的值是要查找的值 获取标签的名称 tagn…

【Linux网络编程】协议|OSI模型|TCP/IP模型|局域网通信|跨网络通信|地址管理|流程图

目录 ​编辑 一&#xff0c;协议 协议分层 二&#xff0c;OSI七层模型 三&#xff0c;TCP/IP五层&#xff08;或四层&#xff09;模型 TCP/IP各个层次一些名词解释 为什么要有TCP/IP协议 TCP/IP协议栈与操作系统的宏观关系示意图 四&#xff0c;网络传输基本流程 局…

华为云征文|Flexus云服务X实例使用,宝塔的安装,利用宝塔安装Java、NGINX,Redis,Python,快速搭建开发环境

引出 4核12G-100G-3M规格的Flexus X实例使用测评第4弹&#xff1a;Flexus云服务X实例使用&#xff0c;宝塔的安装&#xff0c;利用宝塔安装Java、NGINX&#xff0c;redis&#xff0c;Python&#xff0c;快速搭建开发环境 什么是Flexus云服务器X实例 官方解释&#xff1a; Fl…

openharmony历程一:安装ubuntu20.04

1.下载ubuntu20.04 官网下载 下拉选择 可使用镜像&#xff1a; 镜像 2.安装 本人使用vmware,其他的如virtualbox也差不多 选择自定义和下一步 我使用的是r5 5600H&#xff0c;只有12核。 由于后面用于鸿蒙安装&#xff0c;推荐内存16GB及以上&#xff0c;硬盘100GB及…