使用适用于 MySQL 的亚马逊 RDS 和适用于 MariaDB 的亚马逊 RDS 中的连接压缩,缩短网络传输时间

我们的客户已经看到 MySQL 客户端和数据库之间的网络带宽成为瓶颈源的许多案例。这会导致查询延迟增加,从而影响性能。这对于网络带宽要求较高的工作负载尤其明显。MySQL 和 MariaDB 通过允许您压缩客户端和数据库服务器之间的流量来解决这个问题。

在这篇文章中,我们将讨论如何使用 适用于 MySQL 的 亚马逊关系数据库服务 (Amazon RDS) 和适用于 MariaDB 的 亚马逊 RDS 的连接压缩 ,并通过测试用例探讨它们的好处。

MySQL 客户端连接压缩选项

在 8.0.18 版本中,MySQL 引入了对 协议_压缩_算法 系统变量的支持,该变量列出了数据库服务器允许用于传入连接的压缩算法。在 Amazon RDS for MySQL 中,此参数设置为 zlib、zstd 、未压缩 ,这意味着默认情况下,我们允许三种类型的连接:zlib 压缩、zstd 压缩和未压缩。

在使用 MySQL 客户端时, --compression -algorhtiment 命令行选项允许客户端在连接到数据库实例时列出所需的压缩算法。该值默认为未压缩。

自 MyS QL 8.0.18 起,早期版本的 MySQL 客户端工具中提供的-- compress 命令行选项已被弃用。对于 8.0.18 之前的 MySQL 客户端版本,除了未压缩的连接外,该客户端仅支持 zlib 压缩算法。您无法使用此选项指定压缩算法或压缩级别,因此我们建议升级到最新的客户端驱动程序以利用压缩。

要建立连接,客户端和数据库服务器必须就双方允许的压缩算法达成一致。由于 Amazon RDS for MySQL 支持所有 3 种压缩选项,因此客户端可以选择任何算法。因此,如果使用 --compression-algortim ation 指定多个选项 ,则会选择数据库服务器支持的第一个压缩算法。例如,如果 --compression-algortims=zlib,zstd ,则选择 zlib 压缩算法 。如果数据库服务器不支持 zlib 压缩算法(适用于 MySQL 的 Amazon RDS 并非如此),则会选择 zstd 压缩算法。

事实证明,与zLib相比,Zstd在压缩速度、解压缩速度和压缩比方面是更有效的算法。您可以评估这两种压缩算法,看看哪一种最适合您的工作负载。

如果您使用 zstd 压缩算法建立连接,则还可以灵活选择压缩级别。MySQL 客户端的 --zstd-compression 级别 命令行选项允许您为连接配置 zstd 压缩级别 。默认为 3。允许的级别为 1—22。

要了解更多内容,请参阅 ZFS 中 zStand ard 的演示文稿, 该演示文稿将 ZSTD 与其他压缩算法进行了比较,还比较了 ZSTD 的压缩级别

尽管 --zstd-compression-level 的值越高,压缩程度越高,但这也会提高压缩和解压缩结果集数据包所需的计算资源的利用率,从而降低查询性能。我们必须仔细选择压缩级别,以便在压缩网络流量和利用计算资源之间取得平衡。

配置您的压缩算法和压缩级别

要充分利用此功能,请务必为工作负载选择正确的压缩算法和压缩级别。实现此目的的一种方法是使用不同的压缩算法(zstd、zlib 和未压缩)对工作负载的性能进行基准测试,对于 zstd,则使用不同的压缩级别,范围可能在 1-22 之间。

在本节中,我们举几个使用 MySQL 客户端建立和监控客户端连接的示例。

使用 MySQL 客户端连接到 RDS 实例,并使用以下命令进行压缩连接:

# Connects to the RDS instance using the MySQL client using the zstd compression algorithm with a compression level of 7.

$ mysql -uuser1 -p -hmysql8031.xxxxxxxxxxxx.us-west-2.rds.amazonaws.com --zstd-compression-level=7 --compression-algorithms=zstd
Enter password:

有几种方法可以检查您与 MySQL 实例的连接是否已压缩。

首先,你可以在 MySQL 命令行上使用 状态 (\ s) 命令。查找 “协议” 字段,该字段显示 “压缩” 的值:

mysql> \s
--------------
mysql  Ver 8.0.30 for Linux on x86_64 (MySQL Community Server - GPL)

Connection id:    819
Current database: 
Current user:   user1@10.1.3.147
SSL:      Cipher in use is ECDHE-RSA-AES128-GCM-SHA256
Current pager:    stdout
Using outfile:    ''
Using delimiter:  ;
Server version:   8.0.31 Source distribution
Protocol version: 10
Connection:   mysql8031.xxxxxxxxxxxx.us-west-2.rds.amazonaws.com via TCP/IP
Server characterset:  utf8mb4
Db     characterset:  utf8mb4
Client characterset:  utf8mb4
Conn.  characterset:  utf8mb4
TCP port:   3306
Protocol: Compressed
Binary data as:   Hexadecimal
Uptime:     2 days 22 hours 29 min 59 sec

Threads: 4  Questions: 1204176  Slow queries: 0  Opens: 215  Flush tables: 3  Open tables: 134  Queries per second avg: 4.744
--------------

注意:协议版本字段提供有关所使用的 TLS 版本的信息,不应与 ZSTD 压缩级别混淆。

您还可以检查 压缩 、压缩 算法和 压缩级别 等状态变量 ,以检查当前连接的压缩状态。

mysql> show status like '%compress%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Compression           | ON    |
| Compression_algorithm | zstd  |
| Compression_level     | 7     |
+-----------------------+-------+
3 rows in set (0.00 sec)

如果启用了性能架构,则还可以使用以下查询检查应用程序中其他连接的压缩功能是否已启用。您可以使用此查询来获取进程列表输出并确定压缩是开启还是关闭。

mysql> select b.PROCESSLIST_ID as Connection_id, VARIABLE_VALUE as 'Compression', PROCESSLIST_USER as user,PROCESSLIST_HOST as 'Host', b.PROCESSLIST_DB as 'Database' , b.PROCESSLIST_COMMAND as 'Command',b.PROCESSLIST_TIME as 'Time' , b.PROCESSLIST_STATE as 'State',   b.PROCESSLIST_INFO as 'Info'  from performance_schema.status_by_thread a join performance_schema.threads b on a.THREAD_ID = b.THREAD_ID where a.VARIABLE_NAME = 'Compression'  and b.PROCESSLIST_ID  <> connection_id();

+---------------+-------------+----------+-------------+----------+---------+------+-----------+-------------------------+
| Connection_id | Compression | user     | Host        | Database | Command | Time | State     | Info                    |
+---------------+-------------+----------+-------------+----------+---------+------+-----------+-------------------------+
|          1109 | OFF         | rdsadmin | localhost   | NULL     | Sleep   |    4 | NULL      | NULL                    |
|          1110 | OFF         | rdsadmin | localhost   | NULL     | Sleep   |    0 | NULL      | NULL                    |
|          1542 | ON          | user1    | 10.1.28.197 | NULL     | Query   |    3 | executing | select * from testdb.t1 |
+---------------+-------------+----------+-------------+----------+---------+------+-----------+-------------------------+
3 rows in set (0.00 sec)

使用适用于 MariaDB 的亚马逊 RDS 进行连接压缩

MariaDB 客户端还支持连接压缩。传递给 MariaDB 客户端的 -- compress 参数强制在服务器/客户端协议中使用压缩。不能使用 --compress 参数指定压缩算法或压缩 级别。

您可以在命令行上使用 st atus (\ s) 命令并查找 “协议” 字段,该字段显示 “压缩” 的值:

MariaDB [(none)]> \s
--------------
mysql  Ver 15.1 Distrib 10.5.10-MariaDB, for Linux (x86_64) using  EditLine wrapper

Connection id:		57079
Current database:	
Current user:		reinvent@172.31.49.222
SSL:			Not in use
Current pager:		stdout
Using outfile:		''
Using delimiter:	;
Server:			MariaDB
Server version:		10.6.10-MariaDB-log managed by https://aws.amazon.com/rds/
Protocol version:	10
Connection:		maria1067.xxxxxxxxxxxx.us-east-1.rds.amazonaws.com via TCP/IP
Server characterset:	latin1
Db     characterset:	latin1
Client characterset:	utf8mb3
Conn.  characterset:	utf8mb3
TCP port:		3306
Protocol:		Compressed
Uptime:			28 days 18 hours 7 min 1 sec

Threads: 4  Questions: 4947224  Slow queries: 0  Opens: 424  Open tables: 13  Queries per second avg: 1.991
--------------

您还可以检查状态变量 压缩 ,以获取当前连接的压缩状态。

MariaDB [(none)]> show status like 'Compression';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Compression   | ON    |
+---------------+-------+
1 row in set (0.002 sec)

性能基准测试

让我们通过一个例子来了解连接压缩的效用。

我们创建了 亚马逊弹性计算云 (亚马逊 EC2)实例并 安装 MySQL 客户端 。我们还使用以下配置创建了适用于 MySQL 的 Amazon RDS 数据库实例。

  • 客户端 — 亚马逊 EC2 t4g.2xlarge 实例、8 个 vCPU、32 GB 内存
  • 数据库服务器 — 适用于 MySQL 的亚马逊 RDS 8.0.31,带有 db.r6g.2xlarge 实例、8 个 vCPU、64 GB 内存

请注意,使用 t2/t3/t4g 等可突发实例类作为客户端,当 CPU 积分用尽时,CPU 可能会耗尽 CPU 资源。

为了便于演示,我们使用带有全表扫描的单选查询。

使用 sysbench 创建测试表。

mysql> create database testdb;
Query OK, 1 row affected (0.00 sec)

现在使用 sysbench 向表中插入 20,000,000 行:

$ sysbench --test=/usr/share/sysbench/tests/include/oltp_legacy/insert.lua --mysql-port=3306 --db-driver=mysql --mysql-table-engine=innodb --oltp-tables-count=1 --oltp-table-size=20000000 --threads=10 --mysql-user=user1 --mysql-db=testdb --mysql-password=<password> --mysql-host=mysql8031.xxxxxxxxxxxx.us-west-2.rds.amazonaws.com prepare
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)

Creating table 'sbtest1'...
Inserting 20000000 records into 'sbtest1'
Creating secondary indexes on 'sbtest1'...

现在我们已经填充了表,我们开始使用全表扫描运行查询,该查询会扫描所有行并将其结果集中的所有行返回给客户端。

使用 MySQL 客户端连接后,您可以在 MySQL 客户端上使用寻呼机命令筛选结果集,使其不显示在终端上:

mysql> pager grep "rows in"
PAGER set to 'grep "rows in"'

我们使用全表扫描对表格进行选择。

mysql> select * from testdb.sbtest1;
20000000 rows in set (3 min 2.50 sec)

我们使用 RDS 上提供的 增强监控 功能来测量网络传输速度。在增强监控操作系统指标中,我们添加网络 RX TX 以获得传输的总数据。您还可以使用 nload 工具来测量安装了 MySQL 客户端的 EC2 实例上的网络带宽。我们的结果如下:

ZSTD Compression Level Max Network bandwidth Utilization(tx+rx) (MBps) Time to Execute Query and Return Result Set(seconds)
0 231 17.25
3 28 72.11
7 16 126.55
10 11 182.45

在本实验中,我们发现使用压缩连接不会提高性能。当压缩级别提高时,网络带宽利用率会降低,但我们也看到运行查询和返回结果集的时间会增加。查询完成时间随着 zstd 压缩级别的提高而增加。执行时间的增加是由于压缩结果集所需的额外开销。现在让我们使用行大小更大的表格:

mysql> create database testdb;
Query OK, 1 row affected (0.07 sec)

mysql> use testdb;
Database changed

我们向表中填充了随机数据,如以下查询所示,而不是使用 sysbench。

mysql> create table t1(col1 int auto_increment primary key, col2 TEXT,col3 TEXT,col4 TEXT, col5 TEXT,col6 TEXT,col7 TEXT,col8 TEXT,col9 TEXT, col10 TEXT);
Query OK, 0 rows affected (0.08 sec)

mysql> insert into testdb.t1 values(null, repeat(md5(rand()*1000),2000), repeat(md5(rand()*1000),2000), repeat(md5(rand()*1000), 2000), repeat(md5(rand()*1000), 2000), repeat(md5(rand()*1000), 2000), repeat(md5(rand()*1000), 2000), repeat(md5(rand()*1000), 2000), repeat(md5(rand()*1000), 2000), repeat(md5(rand()*1000), 2000)); 
Query OK, 1 row affected (0.12 sec)
$ for i in `seq 0 16`;do mysql  -uuser1 -p<password>  -hmysql8031.xxxxxxxxxxxx.us-west-2.rds.amazonaws.com  -e"use testdb;select repeat(md5(rand()),2000) into @tmp; insert into t1 (col2) select @tmp from t1;";done

我们使用全表扫描在桌子上进行选择。

mysql> select * from t1;
32768 rows in set (1 min 16.64 sec)

我们的结果如下:

ZSTD Compression Level Max Network bandwidth Utilization(tx+rx) (MBps) Time to Execute Query and Return Result Set(seconds)
0 594 32.43
3 1.7 11.01
7 0.26 69.92
10 0.23 72.64

在这个实验中,我们使用重复函数将数据加载到表中。由于表数据的冗余性质,压缩算法能够有效地压缩数据。我们看到,通过压缩连接,网络带宽会大大降低。它从 594 Mbps 降低到 1.7 Mbps,zstd 压缩级别为 3。这也缩短了查询完成时间。但是,当压缩级别进一步提高到 7 时,查询需要更多时间才能完成。

结论

在这篇文章中,我们讨论了连接压缩如何帮助处理适用于 Amazon RDS for MySQL 和 Amazon RDS for MariaDB 上某些类型的工作负载,在这些工作负载中,网络带宽受到限制且结果集很大。我们还向您展示了压缩程度如何取决于数据集的性质。

与连接负载的压缩和解压缩操作所需的计算资源成本相比,网络传输时间更长的情况下,您可以看到这种好处。

为了检查连接压缩是否适合您的工作负载,我们建议您进行基准测试。

有关 MySQL 连接压缩的 更多详细信息 ,请参阅 MySQL 参考手册 。添加评论与我们分享连接压缩对您的工作负载有多大用处。


作者简介

默沙德·伊拉尼 是亚马逊网络服务的数据库工程师(DBE)。


*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。