最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

数据传输

互联网 admin 4浏览 0评论

数据传输

作者:刘安

爱可生测试团队成员,主要负责 DTLE 开源项目相关测试任务,擅长 Python 自动化测试开发。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


背景:

在 3.21.07.0 之前 DTLE 也支持并行回放,但是需要事务在源端 MySQL 执行时就要多线程并行执行,并且还要处于同一个组提交中。如此苛刻的条件导致虽然在传输任务中配置了目标端的并发数,但是很难真正的触发DTLE并行回放。

当然如果源端 MySQL 配置了 binlog_transaction_dependency_tracking=WRITESET 也可以实现高并行度的回放,但是这个配置的默认值为 COMMIT_ORDER 。

有什么办法在不改变 MySQL 配置的情况下实现DTLE的高并行度回放?

DTLE 在 3.21.07.0 版本开始支持基于 writeset 的增量并行回放(以下简称 MTS ),在 3.21.08.0 版本中又对这个功能进行了进一步的改善。那么就来看一下 DTLE 的这个行功能对传输速度以及系统资源占用的影响有多大吧。

一、环境准备

1. 源端部署 MySQL 实例

配置binlog_transaction_dependency_tracking=COMMIT_ORDER

shell> dbdeployer deploy single 5.7.31 --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON -c binlog_transaction_dependency_tracking=COMMIT_ORDER --gtid --port 3306

2. 目标端部署 MySQL 实例

shell> dbdeployer deploy single 5.7.31 --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON --gtid --port 3306

3. 部署由两个 DTLE 3.21.08.0 组成的集群

4. 部署DTLE监控系统

请参考我的上一篇文章《如何搭建 DTLE 的监控系统》

二、测试步骤

1. 数据准备

i. 源端 MySQL 插入100万行基础数据
shell> sysbench /usr/share/sysbench/oltp_common.lua --mysql-host=10.186.16.109 --mysql-port=3306 --mysql-user=test --mysql-password=test --mysql-db=test --create_secondary=off --table-size=1000000 --tables=1 prepare
ii. 记录源端MySQL Executed_Gtid_Set的值
mysql> show master status\G;
*************************** 1. row ***************************File: mysql-bin.000002Position: 189905893Binlog_Do_DB:Binlog_Ignore_DB:
Executed_Gtid_Set: 00003306-0000-0000-0000-000000003306:1-16,
288f4ef1-1b70-11ec-8add-b083fecd2cf3:1-378
1 row in set (0.00 sec)
iii. 将源端的基础数据复制到目标端 MySQL
iv. 源端 MySQL 插入测试数据,共100000个事务、600000个query
shell> sysbench /usr/share/sysbench/oltp_write_only.lua --mysql-host=10.186.16.109 --mysql-port=3306 --mysql-user=test --mysql-password=test --mysql-db=test --report-interval=10 --table-size=1000000 --tables=1 --time=0 --threads=1 --events=100000 run

# 这是一个事务中包含的query示例
shell> cat general.log
2021-09-24T05:50:49.441174Z	   12 Query	BEGIN
2021-09-24T05:50:49.441240Z	   12 Execute	UPDATE sbtest1 SET k=k+1 WHERE id=4997
2021-09-24T05:50:49.441361Z	   12 Execute	UPDATE sbtest1 SET c='03163446517-15844049190-31912517155-76808269330-04050893973-74319634217-49805144545-10801190640-86257363147-68318210832' WHERE id=5002
2021-09-24T05:50:49.441493Z	   12 Execute	DELETE FROM sbtest1 WHERE id=5029
2021-09-24T05:50:49.441606Z	   12 Execute	INSERT INTO sbtest1 (id, k, c, pad) VALUES (5029, 5046, '69556849701-65231705332-27842829357-27348055172-35878376643-27881096491-17377489810-14516858565-38927590402-67912505189', '78037141434-67280017469-22218032946-70184714598-49746437373')
2021-09-24T05:50:49.441724Z	   12 Execute	COMMIT

2. 运行计算QPS的脚本

# coding=utf-8import time
from datetime import datetime, timedeltaimport pymysqlquery_1 = "SHOW MASTER STATUS;"
# 已知要传输600000个query
queries = 600000run_time = datetime.now()
print(f"RUN TIME: {run_time}")with pymysql.connect(host='10.186.16.117', port=3306, user='test', passwd='test', autocommit=True) as db:with db.cursor(pymysql.cursors.DictCursor) as cursor:cursor.execute(query_1)data = cursor.fetchone()init = data['Executed_Gtid_Set']while True:cursor.execute(query_1)data = cursor.fetchone()if data['Executed_Gtid_Set'] != init:start_time = datetime.now()print(f"START TIME: {start_time}")breaktime.sleep(1)equal_times = 0last_gtid = ''# 5秒钟MySQL的gitd不再变动,视为传输结束while equal_times <= 5:cursor.execute(query_1)data = cursor.fetchone()current_gtid = data['Executed_Gtid_Set']print(f"CURRENT GTID: {current_gtid}")if current_gtid == last_gtid:equal_times += 1else:equal_times = 0last_gtid = current_gtidtime.sleep(1)end_time = datetime.now() - timedelta(seconds=5)print(f"END TIME: {end_time}")diff = (end_time - start_time).secondsprint(f'耗时: {diff}')print(f'QPS: {queries / diff}')

3. 创建不开 MTS 特性的增量任务

  • 配置Gtid="记录的源端MySQL Executed_Gtid_Set的值"

  • 配置UseMySQLDependency=true

job "no-mts" {datacenters = ["dc1"]group "Src" {affinity {attribute = "${node.unique.name}"value = "dtle-src-1"}task "src" {driver = "dtle"config {Gtid = "00003306-0000-0000-0000-000000003306:1-16, 288f4ef1-1b70-11ec-8add-b083fecd2cf3:1-378"ReplicateDoDb = [{TableSchema = "test"}]ConnectionConfig = {Host = "10.186.16.109"Port = 3306User = "test"Password = "test"}}}}group "Dest" {affinity {attribute = "${node.unique.name}"value = "dtle-dest-1"}task "dest" {driver = "dtle"config {ParallelWorkers = 32UseMySQLDependency = trueConnectionConfig = {Host = "10.186.16.117"Port = 3306User = "test"Password = "test"}}}}
}

三、其他的使用场景测试

1. MySQL 不启用 MTS,DTLE 启用 MTS 场景

  • 需要将前述测试步骤中创建的DTLE任务中的配置改为UseMySQLDependency=false

2. MySQL 启用 MTS,DTLE 不启用 MTS 场景

需要重新部署源端 MySQL 实例并添加如下配置:

  • binlog_transaction_dependency_tracking=WRITESET
  • transaction_write_set_extraction=XXHASH64
shell> dbdeployer deploy single 5.7.31 --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON -c binlog_transaction_dependency_tracking=WRITESET -c transaction_write_set_extraction=XXHASH64 --gtid --port 3306

3. MySQL 和 DTLE 都启用 MTS 场景

4. 以上场景都可以增加目标端 DTLE 到目标端 MySQL 的网络延迟来进一步对比测试

四、测试结果

MySQL配置DTLE配置网络延迟QPScpu-源端cpu-目标端内存-源端内存-目标端带宽
MySQL:offMTS:off0ms257558%35%138MiB162MiB2.21Mib/s
MySQL:offMTS:off20ms412%2%137MiB165MiB36.5Kib/s
MySQL:offMTS:on0ms6666138%70%139MiB158MiB5.94Mib/s
MySQL:offMTS:on20ms114023%14%138MiB170MiB1Mib/s
MySQL:onMTS:off0ms6593135%73%138MiB167MiB5.79Mib/s
MySQL:onMTS:off20ms115823%15%139MiB169MiB1Mib/s
MySQL:onMTS:on0ms6976134%73%139MiB171MiB6.26Mib/s
MySQL:onMTS:on20ms114521%14%139MiB167MiB1Mib/s

备注:

  • MySQL:off表示MySQL配置binlog_transaction_dependency_tracking=COMMIT_ORDER
  • MySQL:on表示MySQL配置binlog_transaction_dependency_tracking=WRITESETtransaction_write_set_extraction=XXHASH64
  • MTS:off表示DTLE任务配置UseMySQLDependency = true
  • MTS:on表示DTLE任务配置UseMySQLDependency = flase
  • 网络延迟指的是目标端DTLE到目标端MySQL的网络延迟

五、结论

  • MySQL 和 DTLE 中只需有一侧开启 MTS 功能,就可以大幅提升 DTLE 传输速度
  • 开启 MTS 功能并且变更的数据不相互依赖时,在无网络延迟时可以比不开 MTS 提高2.6倍的传输速度,在网络延迟为20ms时可以不开 MTS 提高28倍的传输速度
  • 开启 MTS 功能,DTLE 对内存的使用并无明显变化,DTLE 对 CPU 的使用有升高了1倍多
  • 目标端 DTLE 和目标端的 MySQL 之间的网络延迟要尽可能的小,这样可以明显提升传输速度

数据传输

作者:刘安

爱可生测试团队成员,主要负责 DTLE 开源项目相关测试任务,擅长 Python 自动化测试开发。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


背景:

在 3.21.07.0 之前 DTLE 也支持并行回放,但是需要事务在源端 MySQL 执行时就要多线程并行执行,并且还要处于同一个组提交中。如此苛刻的条件导致虽然在传输任务中配置了目标端的并发数,但是很难真正的触发DTLE并行回放。

当然如果源端 MySQL 配置了 binlog_transaction_dependency_tracking=WRITESET 也可以实现高并行度的回放,但是这个配置的默认值为 COMMIT_ORDER 。

有什么办法在不改变 MySQL 配置的情况下实现DTLE的高并行度回放?

DTLE 在 3.21.07.0 版本开始支持基于 writeset 的增量并行回放(以下简称 MTS ),在 3.21.08.0 版本中又对这个功能进行了进一步的改善。那么就来看一下 DTLE 的这个行功能对传输速度以及系统资源占用的影响有多大吧。

一、环境准备

1. 源端部署 MySQL 实例

配置binlog_transaction_dependency_tracking=COMMIT_ORDER

shell> dbdeployer deploy single 5.7.31 --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON -c binlog_transaction_dependency_tracking=COMMIT_ORDER --gtid --port 3306

2. 目标端部署 MySQL 实例

shell> dbdeployer deploy single 5.7.31 --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON --gtid --port 3306

3. 部署由两个 DTLE 3.21.08.0 组成的集群

4. 部署DTLE监控系统

请参考我的上一篇文章《如何搭建 DTLE 的监控系统》

二、测试步骤

1. 数据准备

i. 源端 MySQL 插入100万行基础数据
shell> sysbench /usr/share/sysbench/oltp_common.lua --mysql-host=10.186.16.109 --mysql-port=3306 --mysql-user=test --mysql-password=test --mysql-db=test --create_secondary=off --table-size=1000000 --tables=1 prepare
ii. 记录源端MySQL Executed_Gtid_Set的值
mysql> show master status\G;
*************************** 1. row ***************************File: mysql-bin.000002Position: 189905893Binlog_Do_DB:Binlog_Ignore_DB:
Executed_Gtid_Set: 00003306-0000-0000-0000-000000003306:1-16,
288f4ef1-1b70-11ec-8add-b083fecd2cf3:1-378
1 row in set (0.00 sec)
iii. 将源端的基础数据复制到目标端 MySQL
iv. 源端 MySQL 插入测试数据,共100000个事务、600000个query
shell> sysbench /usr/share/sysbench/oltp_write_only.lua --mysql-host=10.186.16.109 --mysql-port=3306 --mysql-user=test --mysql-password=test --mysql-db=test --report-interval=10 --table-size=1000000 --tables=1 --time=0 --threads=1 --events=100000 run

# 这是一个事务中包含的query示例
shell> cat general.log
2021-09-24T05:50:49.441174Z	   12 Query	BEGIN
2021-09-24T05:50:49.441240Z	   12 Execute	UPDATE sbtest1 SET k=k+1 WHERE id=4997
2021-09-24T05:50:49.441361Z	   12 Execute	UPDATE sbtest1 SET c='03163446517-15844049190-31912517155-76808269330-04050893973-74319634217-49805144545-10801190640-86257363147-68318210832' WHERE id=5002
2021-09-24T05:50:49.441493Z	   12 Execute	DELETE FROM sbtest1 WHERE id=5029
2021-09-24T05:50:49.441606Z	   12 Execute	INSERT INTO sbtest1 (id, k, c, pad) VALUES (5029, 5046, '69556849701-65231705332-27842829357-27348055172-35878376643-27881096491-17377489810-14516858565-38927590402-67912505189', '78037141434-67280017469-22218032946-70184714598-49746437373')
2021-09-24T05:50:49.441724Z	   12 Execute	COMMIT

2. 运行计算QPS的脚本

# coding=utf-8import time
from datetime import datetime, timedeltaimport pymysqlquery_1 = "SHOW MASTER STATUS;"
# 已知要传输600000个query
queries = 600000run_time = datetime.now()
print(f"RUN TIME: {run_time}")with pymysql.connect(host='10.186.16.117', port=3306, user='test', passwd='test', autocommit=True) as db:with db.cursor(pymysql.cursors.DictCursor) as cursor:cursor.execute(query_1)data = cursor.fetchone()init = data['Executed_Gtid_Set']while True:cursor.execute(query_1)data = cursor.fetchone()if data['Executed_Gtid_Set'] != init:start_time = datetime.now()print(f"START TIME: {start_time}")breaktime.sleep(1)equal_times = 0last_gtid = ''# 5秒钟MySQL的gitd不再变动,视为传输结束while equal_times <= 5:cursor.execute(query_1)data = cursor.fetchone()current_gtid = data['Executed_Gtid_Set']print(f"CURRENT GTID: {current_gtid}")if current_gtid == last_gtid:equal_times += 1else:equal_times = 0last_gtid = current_gtidtime.sleep(1)end_time = datetime.now() - timedelta(seconds=5)print(f"END TIME: {end_time}")diff = (end_time - start_time).secondsprint(f'耗时: {diff}')print(f'QPS: {queries / diff}')

3. 创建不开 MTS 特性的增量任务

  • 配置Gtid="记录的源端MySQL Executed_Gtid_Set的值"

  • 配置UseMySQLDependency=true

job "no-mts" {datacenters = ["dc1"]group "Src" {affinity {attribute = "${node.unique.name}"value = "dtle-src-1"}task "src" {driver = "dtle"config {Gtid = "00003306-0000-0000-0000-000000003306:1-16, 288f4ef1-1b70-11ec-8add-b083fecd2cf3:1-378"ReplicateDoDb = [{TableSchema = "test"}]ConnectionConfig = {Host = "10.186.16.109"Port = 3306User = "test"Password = "test"}}}}group "Dest" {affinity {attribute = "${node.unique.name}"value = "dtle-dest-1"}task "dest" {driver = "dtle"config {ParallelWorkers = 32UseMySQLDependency = trueConnectionConfig = {Host = "10.186.16.117"Port = 3306User = "test"Password = "test"}}}}
}

三、其他的使用场景测试

1. MySQL 不启用 MTS,DTLE 启用 MTS 场景

  • 需要将前述测试步骤中创建的DTLE任务中的配置改为UseMySQLDependency=false

2. MySQL 启用 MTS,DTLE 不启用 MTS 场景

需要重新部署源端 MySQL 实例并添加如下配置:

  • binlog_transaction_dependency_tracking=WRITESET
  • transaction_write_set_extraction=XXHASH64
shell> dbdeployer deploy single 5.7.31 --remote-access % --bind-address 0.0.0.0 -c skip-name-resolve -c binlog_format=ROW -c binlog_row_image=FULL -c log_slave_updates=ON -c binlog_transaction_dependency_tracking=WRITESET -c transaction_write_set_extraction=XXHASH64 --gtid --port 3306

3. MySQL 和 DTLE 都启用 MTS 场景

4. 以上场景都可以增加目标端 DTLE 到目标端 MySQL 的网络延迟来进一步对比测试

四、测试结果

MySQL配置DTLE配置网络延迟QPScpu-源端cpu-目标端内存-源端内存-目标端带宽
MySQL:offMTS:off0ms257558%35%138MiB162MiB2.21Mib/s
MySQL:offMTS:off20ms412%2%137MiB165MiB36.5Kib/s
MySQL:offMTS:on0ms6666138%70%139MiB158MiB5.94Mib/s
MySQL:offMTS:on20ms114023%14%138MiB170MiB1Mib/s
MySQL:onMTS:off0ms6593135%73%138MiB167MiB5.79Mib/s
MySQL:onMTS:off20ms115823%15%139MiB169MiB1Mib/s
MySQL:onMTS:on0ms6976134%73%139MiB171MiB6.26Mib/s
MySQL:onMTS:on20ms114521%14%139MiB167MiB1Mib/s

备注:

  • MySQL:off表示MySQL配置binlog_transaction_dependency_tracking=COMMIT_ORDER
  • MySQL:on表示MySQL配置binlog_transaction_dependency_tracking=WRITESETtransaction_write_set_extraction=XXHASH64
  • MTS:off表示DTLE任务配置UseMySQLDependency = true
  • MTS:on表示DTLE任务配置UseMySQLDependency = flase
  • 网络延迟指的是目标端DTLE到目标端MySQL的网络延迟

五、结论

  • MySQL 和 DTLE 中只需有一侧开启 MTS 功能,就可以大幅提升 DTLE 传输速度
  • 开启 MTS 功能并且变更的数据不相互依赖时,在无网络延迟时可以比不开 MTS 提高2.6倍的传输速度,在网络延迟为20ms时可以不开 MTS 提高28倍的传输速度
  • 开启 MTS 功能,DTLE 对内存的使用并无明显变化,DTLE 对 CPU 的使用有升高了1倍多
  • 目标端 DTLE 和目标端的 MySQL 之间的网络延迟要尽可能的小,这样可以明显提升传输速度
发布评论

评论列表 (0)

  1. 暂无评论