利用JuiceFS使MySQL 备份验证性能提升 10 倍


Posted in MySQL onMarch 17, 2022

前言:

JuiceFS 非常适合用来做 MySQL 物理备份,具体使用参考官方文档。在测试时,备份验证的数据准备(xtrabackup --prepare)过程非常慢。我们借助 JuiceFS 提供的性能分析工具做了分析,快速发现性能瓶颈,通过不断调整 XtraBackup 的参数和 JuiceFS 的挂载参数,在一个小时内将时间缩短到原先的 1/10。本文将我们性能分析和优化的过程记录分享下来,给大家分析和优化 IO 性能提供参考。

数据准备

我们通过 SysBench 工具生成一个大小 11GiB 左右的单表数据库,数据库表的 partition 设置成 10。为了模拟一个正常的数据库读写场景,通过 SysBench 以秒 50 个请求的压力访问数据库,在该压力下数据库对数据盘造成的写数据在 8~10MiB/s 范围内。通过下列命令将数据库备份到 JuiceFS 上。

# xtrabackup --backup --target-dir=/jfs/base/

为了保证每次数据准备操作的数据完全一样,使用 JuiceFS 的快照(snapshot)功能基于 /jfs/base 目录生成快照 /jfs/base_snapshot/。每一次操作前都会将前一次数据准备操作过的数据删掉重新生成一个新的快照。

使用默认参数

# ./juicefs mount volume-demoz /jfs

#  time xtrabackup --prepare --apply-log-only --target-dir=/jfs/base_snapshot

执行总耗时62秒。

JuiceFS支持导出操作日志 oplog,并能对 oplog 进行可视化展示。在执行 xtrabackup --prepare操作之前我们新开一个终端连接到该服务器,在命令行输入

# cat /jfs/.oplog > oplog.txt

开始搜集 oplog 日志,然后执行 xtrabackup --prepare 操作,操作结束后将 oplog.txt 下载到本地,上传到 JuiceFS 提供的 oplog 分析页面:https://juicefs.com/oplog/

我们将 oplog 进行可视化展示

利用JuiceFS使MySQL 备份验证性能提升 10 倍

这里先大致介绍下这个图中各种元素含义。我们的一条 oplog 中包含了时间戳,线程 ID,文件系统操作函数(read, write, fsync, flush 等),操作持续的时间等。左侧数字表示线程 ID,横轴表示时间,不同类型操作用不同颜色标记。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

我们把局部图像放大,不同颜色代表不同类型的操作就一目了然。

排除掉与本次操作无关的几个线程。在数据准备过程中有 4 个线程负责读,5 个线程负责写数据,读写在时间上都是重叠的。

增大 XtraBackup 的内存缓冲区

参考 XtraBackup 官方文档,数据准备是使用内嵌的 InnoDB 在备份数据集上执行故障修复(crash recovery)的过程。

使用 --use-memory 选项增大内嵌 InnoDB 的内存缓冲区大小,默认 100MB,我们增大到 4GB。

# time xtrabackup --prepare --use-memory=4G --apply-log-only --target-dir=/jfs/base_snapshot

执行时间降到了33秒。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

可以看到读写不重叠了 ,将数据读到内存处理完成后写入文件系统。

增大 XtraBackup 读线程数

通过增大缓冲区将时间缩短了一半,整个读的过程耗时依然比较明显。我们看到每个读线程基本都是跑满的状态,我们尝试增加更多的读线程。

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=16 --innodb-read-io-threads=16 --apply-log-only --target-dir=/jfs/base_snapshot

行时间降到了23秒。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

读线程已经增加到了 16 个(默认 4 个),读操作降到 7 秒左右。

JuiceFS 启用异步写

上一步我们极大的优化了读操作时间,现在写过程消耗的时间就比较明显了。通过分析 oplog,发现写操作中 fsync 是不能并行的,因此增大写线程数并不能提升写的效率,在实际操作过程中我们也通过增大写线程数验证了这一点,这里就不赘述了。分析 oplog 对同一个文件(相同文件描述符)的写操作的参数(偏移,写数据大小),发现有大量的随机写操作,我们可以在挂载 JuiceFS 时启用 --writeback 选项,写数据时先写本地盘,再异步写到对象存储。

# ./juicefs mount --writeback volume-demoz /jfs
# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=16 --innodb-read-io-threads=16 --apply-log-only --target-dir=/jfs/base_snapshot

时间降到了 11.8 秒。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

写过程已经降到 1.5 秒左右。

我们看到读线程读操作依然比较密集,我们尝试持续增加读线程数,InnoDB 读线程数最大为 64,我们直接调成 64。

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=64 --innodb-read-io-threads=64 --apply-log-only --target-dir=/jfs/base_snapshot

执行时间 11.2 秒,相比之前基本没变化。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

我们看到,读线程读操作已经比较稀疏了,应该是线程读的数据之间有依赖关系,导致不能完全并行化,已经不能通过提升线程数压缩读过程的时间了。

增大 JuiceFS 的磁盘缓存

在上一步中,我们通过提升读线程数来提升读过程的效率已经到顶了,只能通过降低读数据的延迟来减少读过程时间。

JuiceFS 在读操作处理上提供了预读和缓存加速能力,我们接下来尝试通过增大 JuiceFS 的本地缓存来降低读操作的延迟。

将 JuiceFS 的本地缓存由高效云盘换成 SSD 云盘,并将缓存大小由 1G 改成 10G。

# ./juicefs mount --writeback volume-demoz --cache-size=10000 --cache-dir=/data/jfsCache /jfs

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=64 --innodb-read-io-threads=64 --apply-log-only --target-dir=/jfs/base_snapshot

执行时间降到了 6.9 秒。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

通过提升缓存性能和增大缓存空间进一步减少了读操作耗时。

到此我们总结一下,我们通过分析 oplog,不断寻找可以优化的点,将整个数据准备过程一步步从 62 秒降到 6.9 秒,效果通过下图更直观的展示。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

增大数据库数据量

以上的操作都是针对 11G 这样一个比较小的数据集不断调整参数进行优化得到一个很好的结果。作为对比,我们以同样的方式生成一个 115G 左右的 partition 为10的单表数据库。在 SysBench 持续每秒 50 个请求情况下,执行备份操作。

# time xtrabackup --prepare --use-memory=4G --innodb-file-io-threads=64 --innodb-read-io-threads=64 --apply-log-only --target-dir=/jfs/base_snapshot

这个过程耗时 74 秒。

利用JuiceFS使MySQL 备份验证性能提升 10 倍

我们看到,读和写还是分开的。

在数据量增大10倍左右,相应的准备时间也增大到10倍。这是因为备份(xtrabackup --backup)过程所需的时间扩大到 10 倍,在 SysBench 对数据库压力不变的情况下,备份过程中产生的 xtrabackup_logfile 也是原先的 10 倍。数据准备是要把 xtrabackup_logfile 中的所有数据更新合并到数据文件中,可见即使数据规模增大了 10 倍,但更新单条日志的时间基本不变。从上图也可以验证这一点,数据规模增大后,准备过程仍然是分成了读数据和写数据这两个明显的过程,说明设定的 4GB 的缓冲区大小仍然是够用的,整个过程仍然可以在内存中完成然后更新到文件系统。

总结

我们使用 SysBench 这个相对简单的工具构造初始数据,持续给数据库一定数据更新的压力模拟数据备份时数据库运行场景。使用 JuiceFS 的 oplog 来观察 XtraBackup 在数据准备过程中访问备份数据的读写特点,调整 XtraBackup 和 JuiceFS 的参数来不断优化数据准备过程的效率。

在实际生产场景中,情况比我们 SysBench 模拟要复杂得多,我们上面的线性关系不一定严格成立,但是我们通过分析 oplog 快速发现可以优化的点,进而不断调整 XtraBackup 和 JuiceFS 的缓存和并发的思路是通用的。

整个调参过程耗时 1 小时左右,oplog 分析工具在这个过程中发挥了很大的作用,帮助我们快速定位系统性能瓶颈,从而针对性地调整参数做优化,也希望这个 oplog 分析功能也能帮助大家快速定位和分析遇到的性能问题。

到此这篇关于利用JuiceFS使MySQL 备份验证性能提升 10 倍的文章就介绍到这了,更多相关 MySQL 性能提升 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
mysql批量新增和存储的方法实例
Apr 07 MySQL
MySQL kill不掉线程的原因
May 07 MySQL
MySQL删除和插入数据很慢的问题解决
Jun 03 MySQL
安装配置mysql及Navicat prenium的详细流程
Jun 10 MySQL
MySQL 亿级数据导入导出及迁移笔记
Jun 18 MySQL
Mysql中where与on的区别及何时使用详析
Aug 04 MySQL
MySQL空间数据存储及函数
Sep 25 MySQL
面试中老生常谈的MySQL问答集锦夯实基础
Mar 13 MySQL
MySQL数据库优化之通过索引解决SQL性能问题
Apr 10 MySQL
mysql性能优化以及配置连接参数设置
May 06 MySQL
MySQL数据库配置信息查看与修改方法详解
Jun 25 MySQL
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
May 08 MySQL
MySQL 分区表中分区键为什么必须是主键的一部分
MySQL优化及索引解析
一条 SQL 语句执行过程
Mysql事务索引知识汇总
Mar 17 #MySQL
MySQL慢查询优化解决问题
Mar 17 #MySQL
MySQL日期时间函数知识汇总
MySQL优化常用的19种有效方法(推荐!)
You might like
超级简单的php+mysql留言本源码
2009/11/11 PHP
Smarty实现页面静态化(生成HTML)的方法
2016/05/23 PHP
PHP实现基于面向对象的mysqli扩展库增删改查操作工具类
2017/07/18 PHP
kmock javascript 单元测试代码
2011/02/06 Javascript
JS保存和删除cookie操作 判断cookie是否存在
2013/11/13 Javascript
eclipse导入jquery包后报错的解决方法
2014/02/17 Javascript
深入学习JavaScript中的Rest参数和参数默认值
2015/07/28 Javascript
基于jQuery实现美观且实用的倒计时实例代码
2015/12/30 Javascript
JavaScript操作表单实例讲解(上)
2016/06/20 Javascript
js移动焦点到最后位置的简单方法
2016/11/25 Javascript
js微信扫描二维码登录网站技术原理
2016/12/01 Javascript
微信小程序返回多级页面的实现方法
2017/10/27 Javascript
Angular实现搜索框及价格上下限功能
2018/01/19 Javascript
浅谈vue单一组件下动态修改数据时的全部重渲染
2018/03/01 Javascript
vue项目中应用ueditor自定义上传按钮功能
2018/04/27 Javascript
Vue不能检测到Object/Array更新的情况的解决
2018/06/26 Javascript
微信小程序用户位置权限的获取方法(拒绝后提醒)
2018/11/15 Javascript
Webpack中SplitChunksPlugin 配置参数详解
2020/03/24 Javascript
详解微信小程序入门从这里出发(登录注册、开发工具、文件及结构介绍)
2020/07/21 Javascript
easy_install python包安装管理工具介绍
2013/02/10 Python
Python之eval()函数危险性浅析
2014/07/03 Python
Python生成pdf文件的方法
2014/08/04 Python
零基础写python爬虫之使用Scrapy框架编写爬虫
2014/11/07 Python
Python去除列表中重复元素的方法
2015/03/20 Python
python利用datetime模块计算时间差
2015/08/04 Python
Python 基础教程之包和类的用法
2017/02/23 Python
Python重新加载模块的实现方法
2018/10/16 Python
python使用PIL模块获取图片像素点的方法
2019/01/08 Python
Python flask框架post接口调用示例
2019/07/03 Python
浅析python中while循环和for循环
2019/11/19 Python
Html5 localStorage入门教程
2018/04/26 HTML / CSS
瑞士网球商店:Tennis-Point
2020/03/12 全球购物
开放系统互连参考模型
2016/06/29 面试题
超市实习总结自我鉴定
2013/09/19 职场文书
php随机生成验证码,php随机生成数字,php随机生成数字加字母!
2021/04/01 PHP
浅谈MySql整型索引和字符串索引失效或隐式转换问题
2021/11/20 MySQL