性能测试和调优

测试

块设备性能测试

安装fio
sudo apt-get install fio

FIO的测试参数

参数名 描述
ioengine 负载引擎;我们一般使用libaio,发起异步IO请求。
bs IO大小
direct 直接写; 绕过操作系统Cache。因为我们测试的是硬盘,而不是操作系统的Cache,所以设置为1。
rw 读写模式;顺序写write、顺序读read、随机写randwrite、随机读randread。
size 寻址空间,IO会落在 [0, size)这个区间的硬盘空间上。这是一个可以影响IOPS的参数。一般设置为硬盘的大小。
filename 测试对象
iodepth 队列深度,只有使用libaio时才有意义。这是一个可以影响IOPS的参数。
runtime 测试时长
测试随机写

4K随机读测试,测试参数和测试结果如下所示:

fio -ioengine=libaio -bs=4k -direct=1 -thread -rw=randwrite -size=100G -filename=/dev/vdb \
-name="4KB randwrite test" -iodepth=32 -runtime=60
测试顺序写

测试512KB顺序写,看看云硬盘的最大MBPS(吞吐率)是多少,测试参数和测试结果如下所示:

fio -ioengine=libaio -bs=512k -direct=1 -thread -rw=write -size=100G -filename=/dev/vdb \
-name="512KB seqwrite test" -iodepth=64 -runtime=60

条带化参数调优

使用rbd命令创建block时默认是不启用条带化的。

开启条带化参数的优势:

  1. 对象数目更少,占用的文件句柄少,性能更好
  2. 块设备的地址空间到对象的寻址过程,需要执行更少的CRUSH 算法,有利于随机读写性能
  3. 数据按更小的粒度(stripe_unit)随机分布,可以带来更好的顺序读写性能

以上3点就是ceph 添加条带化特性,而不是直接把object_size调小来实现对象的并行访问

开启条带化参数的不足:

  1. block设置条带化参数后,不能被以内核模块的方式挂载为宿主机的磁盘,只能被kvm-kemu 以qemu-driver挂载为VM的磁盘。

  2. 磁盘物理地址到对象的映射计算更复杂,不易理解掌握

测试条带化参数对性能的影响:

创建Block object_size=32M --stripe-unit 2M --stripe-count 32 (object_size=32M ,32M是对象允许的最大值,可以减小对象个数减少存储对象名称的开销。 --stripe-count 32 因为有21个OSD机器,可以达到均匀分布),一般可以尝试创建多组参数组合的磁盘来确定综合性能最优的参数组合,这个测试过程比较耗时和繁琐重复,可以写脚本工具来实现自动化测试。

rbd创建块设备命令

rbd create image/myimage2 --size 102400 --object-size 32M --stripe-unit 2M --stripe-count 32 --image-feature layering --image-feature striping

调优

OS调优

优化操作系统的参数可以充分利用硬件的性能。

组件 配置
CPU 关闭CPU节能模式
CPU 使用Cgroup绑定Ceph OSD进程到固定的CPU
RAM 关闭NUMA
RAM 关闭虚拟内存
网卡 设置为大帧模式
SSD 分区4k对齐
SSD 调度算法为noop
SATA/SAS 调度算法为deadline
文件系统 使用XFS
文件系统 挂载参数为noatime

RBDCache调优

RBDCache 是Ceph的块存储接口实现库 Librbd 的用来在客户端侧缓存数据的目的,它主要提供了读数据缓存,写数据汇聚写回的目的,用来提高顺序读写的性能。Ceph 既支持以内核模块的方式来实现对 Linux 动态增加块设备,也支持以 QEMU Block Driver 的形式给使用 QEMU 虚拟机增加虚拟块设备,而且两者使用不同的库,前者是内核模块的形式,后者是普通的用户态库。 RBDCache 针对后者,前者使用内核的 Page Cache 达到目的。

RBDCache 参数

目前 RBDCache 只支持以内存的形式存在,因此需要提供一些策略来不断回写到 Ceph 集群来实现持久化。在 Lirbd 中有若干选项来控制 RBDCache 的大小和回写策略:

rbd参数 默认值 说明
rbd_cache_size 32MB 能使用的最大缓存大小
rbd_cache_max_dirty 24MB 缓存中允许脏数据的最大值,到达此值后会阻塞VM的写操作
rbd_cache_target_dirty 16MB 开始执行回写过程的脏数据大小
rbd_cache_max_dirty_age 1s 缓存中单个脏数据最大的存在时间,超过这个时间会触发回写
rbd_cache_writethrough_until_flush true 在收到第1个flush操作后,从writethrough模式切换后writeback模式

除了当满足缓存回写要求大小或者时间才会回写数据外,Librbd 提供的 Flush 接口同样能将缓存中的脏数据全部回写。

RBDCache 由于只是以内存的形式存在,因此大部分人可能会关心是否由于意外的 Kernel Crash 或者 Host 端掉电而导致潜在的数据丢失情况,那么下面就主要讨论这种情况。

内核中的Cache

内核的存储体系中主要有两种缓存,一是 Page Cache,二是 Buffer Cache。Page Cache 是在 Linux IO 栈中为文件系统服务的缓存,而 Buffer Cache 是处于更下层的 Block Device 层,由于应用大部分的使用存储数据是基于文件系统,因此 Buffer Cache 实际上只是引用了 Page Cache 的数据,而只有在直接使用块设备跳过文件系统时,Buffer Cache 才真正掌握缓存。

这些 Cache 都由内核中专门的数据回写线程负责来刷新到块设备中,应用可以使用如 fsync, fdatasync 之类的系统调用来完成强制执行对某个文件数据的回写。像数据一致性要求高的应用如 MySQL 这类数据库服务通常有自己的日志用来保证事务的原子性,日志的数据被要求每次事务完成前通过 fsync 这类系统调用强制写到块设备上,否则可能在系统崩溃后造成数据的不一致。

而 fsync 的实现取决于文件系统,文件系统会将要求数据从缓存中强制写到持久设备中。但是这里还有另外一个问题,通常成为 Block Device Cache(块设备缓存),这类缓存并不存在归 Kernel 管理,例如:传统磁盘上的控制器缓存,RAID 控制器缓存、RBDCache,它主要是被块设备自己管理。

块设备缓存

传统硬件块设备提供缓存的目的与 RBDCache 的意义是一致的,它们同样面临在机器掉电情况下,存在于磁盘控制器上的缓存丢失的情况。但是现代磁盘控制器或者 RAID 卡都会配置一个小型电容用来实现在机器掉电后对缓存数据的回写,但是 Linux Kernel 无法知晓到底是否存在这类“急救”装置来实现持久性,因此,大多数文件系统在实现 fsync 这类接口时,同时会使用 Kernel Block 模块提供的 “blkdev_issue_flush” API 去给块设备发送一个 Flush Request,块设备收到 Flush Request 后就会回写自身的缓存。但是如果机器上存在电容,那么实际上 Flush Request 会大大降低文件系统的读写性能,因此,文件系统会提供如 barrier 选项来让用户选择是否需要发送 Flush Request,比如 XFS 在 mount 时就支持 “barrier=0” 来选择不发送 Flush Request (Write barrier support.)。

QEMU 中的缓存

回到 RBDCache 的使用情况里,用户往往是使用 QEMU 实现的 VM 来使用 RBD 块设备,那么 Linux Kernel 中的块设备驱动是 virtio_blk。它会对块设备各种请求封装成一个消息通过 virtio 框架提供的队列发送到 QEMU 的 IO 线程,QEMU 收到请求后会转给相应的 QEMU Block Driver 来完成请求。

而当 QEMU Block Driver 是 RBD 时,缓存就会交给 Librbd 自身去维护,也就是一直所说的 RBDCache。用户在使用了开启 RBDCache 的 RBD 块设备 VM 时需要给 QEMU 传入 “cache=writeback” 确保 QEMU 知晓有缓存的存在,不然 QEMU 会认为后端并没有缓存而选择将 Flush Request 忽略。

QEMU 作为最终使用 Librbd 中 RBDCache 的用户,它在 VM 关闭、QEMU 支持的热迁移操作或者 RBD 块设备卸载时都会调用 QEMU Block Driver 的 Flush 接口。

RBDCache 可能造成的数据破坏

开启 RBDCache 的 RBD 块设备实际上就是一个不带电容的磁盘,我们需要让文件系统开启 barrier 模式,幸运的是,这也是文件系统的默认情况。除此之外,因为文件系统实际上可能管理的是通过 LVM 这种逻辑卷管理工具得到的分区,因此必须确保文件系统下面的 Linux Device Mapping 层也能够支持 Flush Request,LVM 在较早版本的 Kernel 中就已经支持 Flush Request,而其他 DM-* 模块可能就会忽略该请求,这就需要用户非常明确的了解。

rbd 会默认开启一个叫”rbd_cache_writethrough_until_flush”的一个选项,它的作用就是为了避免一些不支持 “flush” 的 VM 来使用 RBDCache,它的主要方式是在用户开启 RBDCache 的情况下,在收到来自 VM 的第一个 Flush 请求前,它是不会在逻辑上启用 Cache 的。这样就避免了旧内核不支持 Flush 的问题。

results matching ""

    No results matching ""