Ceph性能测试、优化及硬件选型详解|万字长文
一般基准测试原则
基准测试的主要测试案例是:
- 线性读写(大块,长队列),单位MB/s
- IOPS(每秒输入/输出操作数)中的小块(4-8kb,iodepth=32-128)的高度并行随机读写
- IOPS中的单线程事务性随机写入(4-8kb,iodepth = 1)和读取(尽管单线程读取更为罕见
测试您的磁盘
在部署Ceph之前在驱动器上运行fio:
WARNING!对于那些不明白问题的人——写测试是破坏性的。不要在包含重要数据的磁盘上运行它,例如OSD日志分区。
- 在测试之前尝试禁用驱动器缓存:hdparm -W 0 /dev/sdX(SATA驱动器),sdparm --set WCE=0 /dev/sdX(SAS驱动器)。通常,这是服务器固态硬盘(例如Micron 5100或Seagate Nytro)绝对需要的(请参阅#Drive缓存正在使您变慢),因为它使随机写入iops 增加了两个数量级以上(从288 iops到18000 iops!)。在某些情况下,它可能没有任何改善,因此请同时尝试使用-W0和-W1选项。
- 线性读取:fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4M -iodepth=32 -rw=read -runtime=60 -filename=/dev/sdX
- 线性写入:fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4M -iodepth=32 -rw=write -runtime=60 -filename=/dev/sdX
- 峰值并行随机读取:fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=128 -rw=randread -runtime=60 -filename=/dev/sdX
- 单线程读取延迟:fio -ioengine=libaio -sync=1 -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=1 -rw=randread -runtime=60 -filename=/dev/sdX
- 峰值并行随机写入:fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=128 -rw=randwrite -runtime=60 -filename=/dev/sdX
- 日志写入延迟:fio -ioengine=libaio -sync=1 -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=1 -rw=write -runtime=60 -filename=/dev/sdX。还可以使用-fsync=1而不是-sync=1进行尝试,并记下最差的结果,因为有时sync或fsync会被杂乱的硬件忽略。
- 单线程随机写入延迟fio -ioengine=libaio -sync=1 -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=1 -rw=randwrite -runtime=60 -filename=/dev/sdX
您想问为什么这么慢?见下文。
一个有用的习惯是在您部署Ceph OSD的每个SSD上留一个空的分区,以便以后进行基准测试,因为某些SSD用满后会变慢。
测试您的Ceph集群
推荐的基准测试工具:
- fio -ioengine=rbd。运行以下命令:
- fio -ioengine=rbd -direct=1 -name=test -bs=4M -iodepth=16 -rw=write -pool=rpool_hdd -runtime=60 -rbdname=testimg
- fio -ioengine=rbd -direct=1 -name=test -bs=4k -iodepth=1 -rw=randwrite -pool=rpool_hdd -runtime=60 -rbdname=testimg
- fio -ioengine=rbd -direct=1 -name=test -bs=4k -iodepth=128 -rw=randwrite -pool=rpool_hdd -runtime=60 -rbdname=testimg
然后重复执行rw=read/randread。
这是为了进行如下测试:
- 可能的最佳延迟
- 线性带宽
- 随机访问iops
从空的RBD镜像读取非常快,因此在测试之前预先填满rbd镜像磁盘。
从您的实际RBD用户所在的节点运行测试。当您从单独的物理服务器运行测试时,结果通常会稍好一些。
- 从VM内部或通过内核RBD驱动程序(krbd)是相同的:
- fio -ioengine=libaio -direct=1 -name=test -bs=4M -iodepth=16 -rw=write -runtime=60 -filename=/dev/rbdX
- fio -ioengine=libaio -direct=1 -sync=1 -name=test -bs=4k -iodepth=1 -rw=randwrite -runtime=60 -filename=/dev/rbdX
- fio -ioengine=libaio -direct=1 -name=test -bs=4k -iodepth=128 -rw=randwrite -runtime=60 -filename=/dev/rbdX不要错过添加的-sync=1选项。它是有意添加的,以匹配ioengine=rbd测试。ioengine=rbd没有同步的概念,所有内容始终与其保持“同步”。总体而言,这种写模式(事务性单线程写)对应于DBMS。请注意,不管将数据移入和移出内核的假定开销如何,内核客户端实际上都应该更快。
- ceph-gobench或者使用工具https://github.com/vitalif/ceph-bench。最初的想法来自俄语Ceph Chat中的“ Mark's bench”(https://github.com/socketpair/ceph-bench)。两者都使用non-replicated的Ceph池(size=1),在每个单独的OSD中创建几个4MB对象(默认为16个),并对一个OSD中随机选择的对象执行随机单线程4kb写操作。这模仿了对RBD的随机写入,并允许通过分别对它们进行基准测试来确定有问题的OSD。要创建non-replicated的基准池,请使用ceph osd pool create bench 128 replicated; ceph osd pool set bench size 1; ceph osd pool set bench min_size 1。只需注意128(PG数量)就足以让所有OSD至少获得一个PG。
Notes:
- 切勿使用dd测试磁盘性能。
- 不要使用rados bench。它创建少量对象(每个线程1-2个),因此所有对象始终驻留在缓存中,并且改善了结果,超出了应有的范围。
- 您可以使用rbd bench,但是fio更好。
为什么这么慢
首先:
- 对于线性读写,Ceph并不慢。
- Ceph在HDD上并不慢:理论上,Bluestore的单线程随机写入性能是驱动器IOPS的66%(2/3)(当前实际为33%,但是如果您在此后版本将此自动或者手动修复的话:https://github.com/ceph/ceph/pull/26909,性能将恢复到66%),而多线程read/write性能几乎是原始驱动器速度的100%。
但是,大家总认为当使用用SSD替换HDD并使用高速网络时,Ceph的速度应该几乎一样快。每个人都习惯了I/O速度慢而软件速度快的想法。对于Ceph,通常情况并非如此。
Ceph是一个软件定义的存储系统,其“软件”是巨大的开销。当前的一般规则是:无论使用什么驱动器或网络,使用Ceph都很难实现0.5ms以下的随机读取延迟和1ms以下的随机写入延迟。使用一个线程,这仅代表2000个随机读取iops和1000个随机写入iops,即使您设法实现此结果,也已经处于良好状态。使用最好的硬件并进行一些调整,您也许可以进一步改进它,但只能进行两次左右。
但是延迟重要吗?是的,当涉及到单线程(synchronous)随机read/write时,它确实可以。基本上,所有希望数据持久的软件都执行fsync调用,以序列化写入。例如,所有DBMS都可以。因此,要了解这些应用程序的性能极限,您应该使用iodepth=1对群集进行基准测试。
延迟不随服务器或每个SSD的OSD或RAID0中的两个RBD的数量而定。当您使用iodepth=1对集群进行基准测试时,您一次只能对一个放置组进行基准测试(PG是一个三元组或一对OSD)。结果仅受单个OSD处理单个请求的速度影响。实际上,iodepth=1时,IOPS=1/latency。尼克·菲斯克(Nick Fisk)的演讲题目为 «Low-latency Ceph»。«Low-latency Ceph»指出0.7毫秒,仅约1500 iops。
Micron设置案例
这是Micron的案例。他们使用了2倍replication,非常昂贵的CPU(每台服务器2x28核Xeon Platinum),高速的网络(2x100G,实际上是2x2x100G ——两张带有2个端口的卡)和10倍于四个节点的最佳NVMe:https:/ /www.micron.com/resource-details/30c00464-e089-479c-8469-5ecb02cfe06f
在100%CPU负载下,它们仅获得了350000的具有高并行度的峰值写入iops。它看起来似乎很多,但是如果将其除以NVMe的数量(350000/40 NVMe),则每个NVMe仅8750 iops。如果我们考虑2个副本和WAL,则每个驱动器得到8750 * 2 * 2 = 35000 iops。因此,Ceph仅从可以单独提供260000 iops的NVMe 中压缩了35000 iops 。这就是Ceph的开销。
在该文章中也没有单线程延迟测试。这样的测试可能非常有趣。
更新资料
https://www.micron.com/-/media/client/global/documents/products/other-documents/micron_9300_and_red_hat_ceph_reference_architecture.pdf
新的NVMe是Micron 9300,最大可能容量为12.8 TB。与9200相比,每一个都提供更多的写入iops:310k而不是260k。其他所有内容保持不变。
100个RBD客户端的新写入性能结果为477029 iops(比以前的测试高36%)。请记住,尽管如此,每个客户端仍然只有4770 iops。对于10个RBD客户端,结果更好:294000 iops,即每个客户端29400 iops。
是什么对性能有帮助?我猜是配置。与之前的测试相比,他们更改了以下内容:
- 禁用Messenger校验和(ms_crc_data = false)和bluestore校验和(bluestore_csum_type = none)
- 调整rocksdb:bluestore_rocksdb_options = compression=kNoCompression,max_write_buffer_number=64,min_write_buffer_number_to_merge=32,recycle_log_file_num=64,compaction_style=kCompactionStyleLevel, write_buffer_size=4MB,target_file_size_base=4MB,max_background_compactions=64,level0_file_num_compaction_trigger=64,level0_slowdown_writes_trigger=128, level0_stop_writes_trigger=256,max_bytes_for_level_base=6GB,compaction_threads=32,flusher_threads=8,compaction_readahead_size=2MB 分为:
- 主要部分可能是64x32x4 MB的内存表设置(number x merge x size),而不是默认的4x1x256 MB。对于我来说,这种变化的影响还不是很明显。这可能会略微减少CPU负载,因为排序大内存表比排序小内存表慢。但是,32x4压缩可能不会比1x256快得多。
- max_bytes_for_level_base发生了巨大的变化,从256MB增加到6GB!
- 添加了压缩线程
- 每个OSD分配14 GB RAM
- osd_max_pg_log_entries=osd_min_pg_log_entries=osd_pg_log_dups_tracked=osd_pg_log_trim_min = 10。但是我不确定这一点,它在我的测试中没有任何影响。
其他说明:
- 在先前版本的测试中,cephx已被禁用。这次他们也禁用了signatures。不过,这似乎毫无意义,禁用的cephx不会进行任何signatures。
- 他们已经配置了debug objecter= 0/0,其余的调试级别设置为零。
- 似乎他们还没有尝试更改preferred_deferred_size和min_alloc_size。
- 新的NVMes绝对没有任何改变。无论如何,Ceph的最大参数为260000 iops。
- 在新的文档中,存在QD=1的70/30 R/W测试。这是针对100个RBD客户端完成的,但对于它们的群集,这是“低负载”条件(主机上的CPU负载为19.38%)。他们报告了0.37ms/0.72ms的随机读写延迟。实际上,他们将其报告为反转,但让我们假设0.37ms实际上是用于读取的,因为在Ceph中读取总是更快。再次仅对应于2700/1388单线程R/W iops。
CAPACITORS!
需要注意的重要一件事是,Ceph中的所有写入都是事务性的,即使没有特别要求也是如此。这意味着写入操作只有在将它们写入所有OSD日志并将fsync写入磁盘后才能完成。这是为了防止类似[#RAID WRITE HOLE]的情况。
为了更清楚地说明,这意味着Ceph 不使用任何驱动器写缓冲区。相反,它在每次写入后清除所有缓冲区。这并不意味着根本就没有写缓冲,而是在客户端(虚拟机内部的RBD缓存,Linux页面缓存)上有一些缓存。但是不使用内部磁盘写缓冲区。
就写入IOPS而言,这使得典型的台式机SSD对于Ceph日记绝对具有非常出色的性能。您可以期望的数字在100到1000(或500-2000)iops之间,而您可能希望至少看到10000(即使是非有名的SSD也可以在没有fsync的情况下完成10000 iops)。
因此,您的磁盘也应使用-iodepth=1 -fsync=1(或-sync=1,请参见[#O_SYNC vs fsync vs hdparm -W 0]进行基准测试。
真正可以帮助我们构建闪电般快的Ceph集群的东西是是带有(超级)电容器的SSD,在M.2 SSD上肉眼可见:
超级电容的工作方式类似于SSD的内置UPS,并允许其在断电时将DRAM缓存刷新到持久性(闪存)内存中。因此,缓存变为“非易失性”,因此SSD可以安全地忽略fsync(FLUSH CACHE)请求,因为它确信缓存内容将始终进入持久性存储。
这增加了事务性写IOPS,使其等于非事务性。
超级电容通常在数据表中称为«enhanced/advanced power loss protection» 。这项功能几乎仅在«server-grade» SSD(甚至不是全部)中提供。例如,英特尔DC S4600有超级电容,而英特尔DC S3100没有超级电容。
这是服务器和台式机固态硬盘之间的主要区别。一般用户不需要事务,但是服务器运行DBMS,而DBMS希望它们确实非常糟糕。
而且Ceph也这样做,您只应为Ceph群集购买具有超级电容的SSD。即使您考虑使用NVMe,不带电容器的NVMe也比带电容器的SATA更差。台式机NVMe可以执行150000+次写入iops而不进行同步,但是它们只能进行600-1000 iops。
另一个选择是Intel Optane。Intel Optane还是SSD,但基于不同的物理原理,相变内存而不是闪存。规格说,这些驱动器能够擦除550000 iops,而无需擦除块,因此不需要写缓存和超级电容器。但是,即使Optane的延迟为0.005ms(即),Ceph的延迟仍为0.5ms,因此将它们与Ceph一起使用毫无意义,与普通的服务器SSD/NVM相比,您可以获得相同的性能,却要花很多钱。
Bluestore与Filestore
TODO:本节缺少随机读取性能比较。
Bluestore是Ceph的“新”存储层。所有案例和文档都说在所有方面都更好,实际上对于“新”事物来说似乎是合理的。
对于线性写入工作负载,Bluestore实际上比Filestore快2倍,因为它没有两次写入——大块仅被写入一次,而不是Filestore中的两次。Filestore记录所有内容,因此所有写操作都首先进入日志journal,然后复制到主设备。
Bluestore的功能也更加丰富:它具有checksums,compression,erasure-coded和virtual clones。其中checksums可以使2x-replicated的池更好地自我修复,erasure-coded覆盖使EC可用于RBD和CephFS,而virtual clones使VM在进行快照后运行得更快。
在仅使用HDD(或仅使用不良SSD)的设置中,对于随机写入,Bluestore的速度也比Filestore快2倍。这再次是因为它每次写入至少可以提交1次,至少在应用此修补程序的情况下:https : //github.com/ceph/ceph/pull/26909并打开bluefs_preextend_wal_files。实际上,可以说Bluestore的延迟写入实现对于慢速驱动器的事务性写入确实是最佳的。
但是,如果您切换到更快的驱动器,Bluestore的随机写入似乎不会比Filestore的随机写入好得多。这在HDD + SSD和全闪存设置中的显示方式有所不同,这两种设置都非常受欢迎。
数据盘HDD + journal日志盘SSD
Filestore将所有内容写入journal,并且仅在journal占容量的一定百分比时才开始将其刷新到数据后端。这非常方便,因为它使journal充当临时写入突发的“临时缓冲区”。
即使将WAL+DB放在SSD上,Bluestore也无法做到这一点。它也有一个”journal“,称为“deferred write queue”,但是它很小(只有64个请求),并且缺少任何类型的后台刷新线程。因此,您实际上可以增加最大的延迟请求数,但是在队列填满之后,性能将下降,直到OSD重新启动为止。
因此,Bluestore的性能非常稳定,但比相同硬件的Filestore的峰值性能差。换句话说,Bluestore OSD拒绝执行随机写入的速度比HDD平均可以执行的速度更快。
使用Filestore,当日志未满时,您很容易获得1000-2000 iops。使用Bluestore,无论SSD日志如何,您只能获得100-300 iops,但是随着时间的推移它们绝对稳定并且永不下降。
SSD-only(全闪存)
在全闪存集群中,Bluestore自身的延迟通常比Filestore的延迟大30-50%。但是,这仅指Bluestore本身的延迟,因此这30%至50%的绝对数字约为0.1ms,这在Ceph的总延迟之前很难注意到。即使延迟时间更长,并行吞吐量的峰值通常也稍好一些(+ 5~10%),而峰值CPU使用率则稍低一些(-5~10%)。
但是,相对于那样的架构工作量,仅增加5-10%仍然是一个遗憾。
RAM usage
还要注意的另一件事是,Bluestore使用了更多的RAM。这是因为它将RocksDB用于所有元数据,另外还单独缓存了其中的一些元数据,并且还尝试缓存了一些数据块,以弥补页缓存使用率的不足。一般的经验法则是每1TB存储1GB RAM,但每个OSD不少于2GB。
关于block.db大小调整
和往常一样,有些问题。
官方文件说,您应该为block.db(Bluestore的元数据分区)分配4%的慢速设备空间。这很多,Bluestore很少需要那么多空间。
但是主要的问题是,Bluestore使用RocksDB,而RocksDB仅在认为整个层都适合该设备时才将文件放在快速设备上(RocksDB是由文件提供的)。因此,Ceph中的默认RocksDB设置为:
- 1 GB WAL = 4x256 Mb
- max_bytes_for_level_base和max_bytes_for_level_multiplier是默认设置,因此分别为256 Mb和10
- 所以L1 = 256 Mb
- L2 = 2560 Mb
- L3 = 25600 Mb
…所以…
仅当RocksDB的大小至少为2560 + 256 + 1024 Mb(将近4 GB)时,RocksDB才会将其放置在block.db中。而且只有在L3至少为25600 + 2560 + 256 + 1024 Mb(将近30 GB)时,它才会放置在那里。和L4——仅当其至少为256000 + 25600 + 2560 + 256 + 1024 Mb(大约286 GB)时。
换句话说,除了4、30、286 GB之外,所有block.db大小都是没有意义的,Bluestore将不会使用任何超出先前“舍入”大小的东西。至少如果您不更改RocksDB设置。这4个值太小,286个太大。
因此,只需为所有Bluestore OSD保留30 GB。
RAID Controllers
- SATA可以,您根本不需要SAS。SATA简单且绝对比旧的RAID控制器快。
- 除非绝对确定需要,否则请不要使用RAID。所有驱动器均应使用直通(HBA)模式进行连接。
- 如果您的RAID控制器无法执行直通模式,请对其进行刷新。如果无法刷新它,则将其丢弃并购买HBA(“RAID without RAID”),例如LSI 9300-8i。
- 如果您仍然无法丢弃它,请禁用所有缓存并祈祷。问题是RAID控制器有时会忽略fsync请求,因此Ceph可能会因突然断电而损坏。甚至某些HBA都可以这样做(即某些Adaptec)。
- 从理论上讲,您可以尝试在RAID0模式下利用电池(或超级电容)支持的控制器缓存来提高写入延迟。但是,这很容易使自己陷入困境。如果这样做,至少要进行一些电源拔出测试。
- 关于RAID0的邮件列表中的一个好帖子:http://lists.ceph.com/pipermail/ceph-users-ceph.com/2019-July/036237.html (TLDR:永远不要使用它!)
- RAID和HBA/SATA之间的IOPS差异可能非常明显。损坏或旧的RAID控制器很容易成为瓶颈。
- HBA也有IOPS限制。例如,对于LSI 9211-8i,所有磁盘约为280000 iops。
- 始终为SAS和NVMe驱动器打开blk-mq——或仅使用最新的内核版本,从4.18左右开始,默认情况下blk-mq处于打开状态。对于SATA,则不需要。
CPUs
- CPU是在优质SSD上运行的Ceph的主要瓶颈。
- 正如尼克·菲斯克(Nick Fisk)在他的演讲中所说的那样——Ceph是一种软件定义的存储,每一个Ceph软件都将以每GHz的CPU时钟速度运行得更快。
- 服务器CPU通常具有NUMA(非统一内存访问)。这意味着某些CPU内核无法直接访问RAM或硬件部分。他们必须将请求转发到其他内核才能访问此硬件。
- 您应该尝试使用时钟速度更高且没有NUMA的CPU来最大化性能。也就是说,具有更多核心的较慢CPU可能比具有较少核心数的较快CPU更糟糕。
- 但在一定程度上是合理的,因为一个Bluestore OSD在满负载下最多可以吃掉约6个内核。
- “时钟速度”表示名义上的速度,而不是Turbo Boost速度,因为Turbo Boost仅对单线程工作负载有益。
- CPU pinning建议(taskset)几乎已经过时,因为Ceph OSD是多线程的。写入期间至少有4个线程处于活动状态,因此,如果为每个OSD分配少于4-6个内核,则只会降低OSD的速度。
- OSD工作线程计数有两个参数——osd_op_num_shards和osd_op_num_threads_per_shard…
- 但是尝试对其进行调整是没有意义的,默认配置(对于HDD为1x5,对于SSD为2x8)是最佳的。问题在于所有工作线程仍将写操作序列化到单个kv_sync_thread中,并且整个方案最多只能扩展到约6个工作线程。
- 有一件事情可以一次减少2-3倍的延迟。它禁用了CPU的所有节能功能:
- cpupower idle-set -D 1—— 这将禁用C状态(或者您可以将processor.max_cstate = 1 intel_idle.max_cstate = 0传递给内核命令行)
- for i in $(seq 0 $((nproc-1))); do cpufreq-set -c $i -g performance; done ——这将禁用频率缩放。
- 禁用节能功能后,CPU会作为GTX发热,但iops会增加2-3倍。
- 对CPU的高要求是在“超融合设置”中不使用Ceph的原因之一,“超融合设置”是存储和计算节点组合在一起的设置。
- 您还可以禁用所有硬件漏洞缓解措施:noibrs noibpb nopti nospectre_v2 nospectre_v1 l1tf=off nospec_store_bypass_disable no_stf_barrier(或者对于新内核,仅mitigations=off)
虚拟机设置和文件系统选项
- RBD的默认qemu选项不是很好。
- 典型的问题表示:
- 它使用慢速仿真的LSI控制器
- 它使用具有缓存读取但没有缓存写入的模式。
- qemu中的驱动器缓存由“ cache”选项控制。它可以是missing, writethrough, writeback, none, unsafe, directsync。使用RBD时,此选项还会影响rbd缓存,这是Ceph客户端库(librbd)端的缓存。
- 但是cache=unsafe不适用于RBD,它仍在等待写入确认。而writethrough,missing和directsync基本上是等效的。
- RBD缓存对HDD很有帮助,但是在全闪存群集上,它会减慢一切。有些东西是用锁实现的,有些东西是单线程的,有人试图对其进行优化,但是工作还没有完成。
- 有以下驱动器模拟选项:lsi (slowest), virtio-scsi (fast), virtio (fastest,但在QEMU 4.0之前不能执行TRIM)。virtio-scsi可以使用多个队列,因此使用快速底层存储(使用本地NVMe?)应该是最快的——但Ceph似乎无关紧要。
- 文件系统也会减慢速度!具体来说,如果您没有启用延迟时间,它将在每次数据small write时更新inode mtime。mtime是元数据的一部分,因此记录了此更改,这使得在FS中的文件上运行fio -sync=1 -iodepth=1 -direct=1测试结果时,结果差3-4倍。
- 如果您很不幸在Ceph VM中运行Oracle,那么至关重要的是设置FILESYSTEMIO_OPTIONS=SETALL。如果不设置,则I / O将非常慢。
所以…
- 对于HDD/SSD + HDD群集,建议使用qemu cache=writeback。此模式是安全的,因为guest fsync使qemu刷新RBD缓存。也就是说,guest不会丢失日记数据。
- 对于仅SSD的群集,最好完全禁用缓存(cache=none)。它通常将最大并行iops增加2倍左右。
- 最好的仿真驱动程序是virtio。现在,找到在VM GUI(Proxmox,Opennebula)中进行设置的方法。以Opennebula为例,它改变仿真驱动程序的方式很不方便。
- 尝试都使用lazytime。它需要一个相当不错的内核:ext4至少为4.0,XFS至少为4.17。对于XFS,似乎还需要最新版本的util-linux。
Network,DPDK和SPDK
- 快速网络对于线性read/write和rebalancing最为重要。是的,您需要10G或更高的速度,但是对于Ceph而言,通常的0.05ms-0.1ms以太网延迟就足够了。进一步改进它们不会提高您的随机read/write性能。巨型帧(mtu=9000)也仅适用于线性read/write。
- DPDK=Data Plane Developer Kit,快速的Intel库,用于与用户空间中的网络和RDMA(Infiniband)设备一起使用,而无需内核上下文切换
- SPDK=Storage Performance Developer Kit,用于在用户空间中与NVMe SSD配合使用的附加Intel库,也非常快。还有libnvme-SPDK的一个分支,其中删除了DPDK依赖性。
- Ceph中有DPDK和SPDK支持:
- 通过ms_type=async + dpdk启用了DPDK
- 通过将spdk:PCI_serial_number作为设备名称传递并使用手动部署文档来部署OSD,从而为NVMe启用了SPDK。
- DPDK支持已报错——构建脚本已报错,即使您像我这样手动修复它们,也存在一些错误,这些错误会使OSD在处理约50个数据包后崩溃。
- SPDK构建脚本是可以的,并且默认情况下甚至使用它构建了Ceph。甚至有一些报告说它可以工作,但是,当我尝试使用SPDK启动OSD时,我的OSD刚刚hung起。
- 两者都没有用,因为Ceph本身并没有那么快。网络延迟是0.05毫秒还是0.005毫秒都没关系——Ceph软件耗时0.5到1毫秒。有一个在邮件列表中的实验测试——从所有Ceph的代码中独立AsyncMessenger,然后单独对它进行基准测试( https://www.spinics.net/lists/ceph-devel/msg43555.html )——他只得到了大约80000 iops。
- 从长远来看,甚至对于NVMe都不需要SPDK,因为Linux 5.1终于有了一个适当的异步I/O实现,称为io_uring:https: //lore.kernel.org/linux-block/20190116175003.17880-1-axboe@kernel.dk/——它为您提供了与SPDK几乎相同的延迟,并且复杂度大大降低。最后,它还可以与缓冲的I/O一起使用。
驱动器缓存降低速度
O_SYNC vs fsync vs hdparm -W 0
SATA和SCSI驱动器有两种刷新缓存的方式:FLUSH CACHE命令和用于写入的FUA(Force Unit Access)标志。第一个是显式刷新,第二个是将数据直接写入media的指令。更准确地说,SCSI/SAS中有FUA标志,但SATA的情况尚不清楚:它在NCQ规范中,但实际上大多数驱动器都不支持它。
似乎fsync发送了FLUSH CACHE命令,并使用O_SYNC打开文件设置FUA bit。
有什么区别吗?通常没有。但有时,取决于确切的控制器是否配置可能有所不同。在这种情况下,fio -sync=1和fio -fsync=1开始给出不同的结果。在某些情况下,其中之一测试方式驱动器会忽略。
除此之外,SATA/SAS驱动器还具有缓存禁用命令。当禁用缓存时,Linux完全停止发送刷新。似乎这也应该导致与fsync/O_SYNC相同的性能,但事实并非如此!超级电容与固态硬盘给很多有问题缓存更好的性能。例如,Seagate Nytro 1351给您288 iops(带缓存)和18000 iops(不带缓存)!
为什么?似乎是因为驱动器将FLUSH CACHE解释为“请刷新所有缓存,包括非易失性缓存”命令,而“ disable cache”被解释为“请禁用易失性缓存,但是您可以保留非易失性,如果需要,请一对一“。这使得在每次写入后进行刷新操作的写入要比禁用高速缓存的写入慢。
NVMe呢?NVMe的可变性略低——NVMe规范中根本没有“ disable cache”命令,但是就像SATA规范中一样,有FLUSH CACHE命令和FUA bit。但是,再次,根据个人经验,我可以说,Linux或驱动器本身经常会在NVMe中忽略FUA,因此fio -sync=1的结果与fio -direct=1相同,而没有任何同步标志。-fsync=1正确执行,并将性能降低到它必须属于的位置(台式机NVMe为1000-2000 iops)。
PS:Bluestore使用fsync。Filestore使用O_SYNC。
服务器固态硬盘
禁用缓存不是一个玩笑!
fio -ioengine=libaio -name=test -filename=/dev/sdb -(sync|fsync)=1 -direct=1 -bs=(4k|4M) -iodepth=(1|32|128) -rw=(write|randwrite)
Write
Micron 5100 Eco 960GB
sync or fsyncbsiodepthrwhdparm -W 1hdparm -W 0sync4k1write612 iops22200 iopssync4k1randwrite612 iops22200 iopssync4k32randwrite6430 iops59100 iopssync4k128randwrite6503 iops59100 iopssync4M32write469 MB/s485 MB/sfsync4k1write659 iops25100 iopsfsync4k1randwrite671 iops25100 iopsfsync4k32randwrite695 iops59100 iopsfsync4k128randwrite701 iops59100 iopsfsync4M32write384 MB/s486 MB/s
Read
bsiodepthrwresult4k1randread6000 iops4k4randread15900 iops4k8randread18500 iops4k16randread24800 iops4k32randread37400 iops4M1read460 MB/s4M16read514 MB/s
hdparm -W 0和1的读取没有区别。
Seagate Nytro 1351 XA3840LE10063
在测试之前,磁盘已填充90-100%。
Write
sync or fsyncbsiodepthrwhdparm -W 1hdparm -W 0sync4k1randwrite18700 iops18700 iopssync4k4randwrite49400 iops54700 iopssync4k32randwrite51800 iops65700 iopssync4M32write516 MB/s516 MB/sfsync=14k1randwrite288 iops18100 iopsfsync=14k4randwrite288 iops52800 iopsfsync=44k4randwrite1124 iops53500 iopsfsync=14k32randwrite288 iops65700 iopsfsync=324k32randwrite7802 iops65700 iopsfsync=14M32write336 MB/s516 MB/s
Read
bsiodepthrwresult4k1randread8600 iops4k4randread21900 iops4k8randread30500 iops4k16randread39200 iops4k32randread50000 iops4M1read508 MB/s4M16read536 MB/s
如果要超过288 iops,请禁用缓存。
RAID WRITE HOLE
即使我们谈论的是RAID(比Ceph等分布式软件定义的存储要简单得多),我们仍然在谈论分布式存储系统——具有多个物理驱动器的系统都是分布式的,因为每个驱动器的行为和提交(或不提交)数据是独立的。
当驱动器不同步时,Write Hole是RAID阵列中几种情况的名称。假设您有一个包含两个磁盘的简单RAID1阵列。您写一个扇区。您将写命令发送到两个驱动器。然后在命令完成之前发生电源故障。现在,在系统再次引导之后,您将不知道副本是否包含相同的数据,因为您不知道哪个驱动器成功写入了数据,而哪个驱动器没有写入成功。
我将从两个驱动器中读取数据,如果遇到不同的数据,我将选择其中一个副本,然后获取旧数据或新数据。
但是,请想象一下您拥有RAID5。现在,您拥有三个驱动器:两个用于数据,另一个用于奇偶校验。现在,假设您再次覆盖了一个扇区。在写入之前,您的磁盘包含:(A1),(B1)和(A1 XOR B1)。您想用(B2)覆盖(B1)。为此,您将(B2)写入第二个磁盘,并将(A1 XOR B2)写入第三个磁盘。再次发生电源故障,同时,磁盘1(未写入任何内容的磁盘)发生故障。您可能会认为您仍然可以重建数据,因为您拥有RAID 5,并且3个磁盘中的2个仍然有效。
但是,假设磁盘2成功写入了新数据,而磁盘3却失败了(反之亦然)。现在您有了:(丢失的磁盘),(B2)和(A1 XOR B1)。如果您尝试从这些副本中重建A,您将得到(A1 XOR B1 XOR B2),这显然不等于A1。因此,RAID5损坏了断电时甚至尚未写入的数据。
由于这个问题,异常关闭后将有不完整数据的磁盘,Linuxmdadm拒绝启动不完整的阵列。除了有每个磁盘驱动器级别的完整数据日志记录外,没有其他解决此问题的方法。而这正是Ceph所做的!因此,Ceph实际上比RAID更安全。可能较慢,但更安全。
快速了解SSD和闪存
尽管闪存允许在小块(通常为512到4096字节)中进行快速随机写入,但其显着特征是必须在擦除每个块之前将其擦除。但是,与读写相比,擦除速度较慢,因此制造商设计存储芯片时总是要一次擦除一大组块,因为这几乎与擦除一个块所需的时间相同。这组称为“擦除单元”的块通常为2-4兆字节。另一个独特的功能是物理上限制了擦除/编程周期的总数——在数千个周期(MLC存储器的通常数目)之后,该块出现了故障,并停止接受新的写入,甚至丢失了先前写入其中的数据。密度较小且价格便宜的(MLC / TLC / QLC,每单元2/3/4bits)存储芯片具有较小的擦除限制,而稀疏和昂贵的(SLC,每个单元1bits)具有更大的限制(最多可重写100000)。但是,所有限制仍然是有限的,因此愚蠢地覆盖同一块将非常缓慢,并且会非常迅速地破坏SSD。
但是现代SSD并非如此——即使便宜的型号也非常快且通常耐用。但为什么?值得称赞的是SSD控制器:SSD包含非常智能且功能强大的控制器,通常具有至少4个内核和1-2 GHz时钟频率,这意味着它们与手机处理器一样强大。为了使FTL固件平稳运行,需要所有这些功能。FTL代表“闪存转换层”,它是负责将小块的地址转换为闪存芯片上物理地址的固件。每个写请求总是放在预先释放的空间中,而FTL仅记住数据的新物理位置。这使得写入非常快。FTL还对可用空间进行碎片整理,并在所有存储单元之间移动内存块,以实现均匀的磨损。此功能称为磨损平衡。SSD通常还保留一些额外的物理空间,以增加耐用性并简化磨损平衡。这称为预留空间。价格较高的服务器SSD的空间过多,例如,Micron 5100 Max保留了37.5%的物理内存(额外的60%添加到了用户可见的容量中)。
这也是使功率损耗保护成为问题的FTL。映射表是元数据,当您刷新缓存时也必须将其映射到非易失性存储器中,这就是使台式机固态硬盘通过fsync变慢的原因。事实上,正如我所写的那样,我认为它们可以使用RocksDB或基于类似的LSM-tree系统来存储映射表,即使没有电容器也可以使fsync快速。这将导致日志空间的浪费和额外的写入放大(因为每个日志块仅包含1次写入),但仍然可以使写入速度更快。所以,他们要么不了解LSM树,要么FTL元数据不是fsync的唯一问题。
当我尝试在邮件列表中向他人讲授“所有SSD正确执行fsync”时,我得到了以下答复:https://www.usenix.org/system/files/conference/fast13/fast13-final80.pdf 。长话短说,它说在2013年,一种常见的情况是SSD根本不同步fsync调用上的元数据,这导致掉电时发生各种有趣的事情,甚至导致某些SSD完全失效。
还存在一些非常老的固态硬盘,没有电容器(OCZ Vector/Vertex),能够实现非常大的sync iops数量。它们如何工作?没有人知道,但是我怀疑他们只是不做安全的写。近年来,闪存覆盖的核心原理没有改变。5年前,SSD也是基于FTL的。
因此,似乎有两种“断电保护”:简单的PLP表示“发生断电时我们进行fsync,并且不会停止或丢失数据”,而高级PLP表示fsync的写入速度一样快且为非同步。在当前的几年中(2018年至2019年),简单的PLP似乎已经成为标准,并且大多数SSD不会因电源故障而丢失数据。
USB闪存驱动器
为什么USB闪存驱动器那么慢?就较小的随机写入而言,它们通常每秒仅执行2-3次操作,同时由类似的闪存芯片供电——也许便宜些和更差一些,但显然不会差1000倍。
答案还在于FTL。USB闪存驱动器也具有FTL,甚至具有一定的损耗平衡,但是与SSD FTL相比,它非常小巧。它的CPU速度很慢,只有很少的内存。因此,它没有地方存储完整的小块映射表,而是转换大块(1-2兆字节甚至更大)的位置。缓冲写操作,然后一次刷新一个块;一次可以缓冲的块数有一个很小的限制。该限制通常仅在3到6个块之间。
此限制始终足以将大文件复制到以任何常见文件系统格式化的闪存驱动器。一个打开的块接收元数据,另一个接收数据,然后继续前进。但是,如果您开始进行随机写操作,您将停止点击打开的块,这就是滞后的原因。
推荐SSD型号
- Micron 5100/5200和soon 5300
- Seagate Nytro 1351/1551
- HGST SN260
- Intel P4500
https://docs.google.com/spreadsheets/d/1E9-eXjzsKboiCCX-0u0r5fAjjufLKayaut_FOPxYZjc
结论
针对随机reads/writes优化Ceph的快速指南:
- 仅将SSD和NVMe与超级电容配合使用。提示:99%的台式机SSD/NVMe没有超级电容。
- 使用hdparm -W 0禁用其缓存。
- 禁用节能功能:governor=performance,cpupower cpupower idle-set -D 0
- 禁用签名:cephx_require_signatures = false cephx_cluster_require_signatures = false cephx_sign_messages = false(并将-o nocephx_require_signatures,nocephx_sign_messages用于rbd映射和cephfs内核安装)
- 为获得良好的SSD和NVMe,请执行以下操作:设置min_alloc_size=4096,preferred_deferred_size_ssd=0(在部署OSD之前)
- 在Nautilus之前版本一定要设置:[global] debug objecter=0/0(客户端运行速度变慢)
- 尝试在用户空间驱动程序中禁用rbd缓存(QEMU选项cache=none)
- 对于仅适用于HDD或性能不佳的SSD驱动器,可以使用补丁https://github.com/ceph/ceph/pull/26909
本文翻译自:https://yourcmc.ru/wiki/Ceph_performance (感谢大神)