剑客
关注科技互联网

给Ceph插上一双翅膀

Ceph与SPDK、DPDK

引子

Ceph是一个优秀的开源分布式存储系统,一个系统同时做到对象存储、文件存储、块设备存储,号称统一存储。伴随着云计算社区Openstack一起快速发展。NBS从年初开始在线上部署使用了Ceph,磁盘全部使用SSD,来提供块存储服务。在Ceph的使用过程中,我们已经充分感受到Ceph在高可用、高可靠、易部署、易维护方面的优点,Ceph本身的设计也算得上优秀,NBS小组之前也针对Ceph的设计做了一系列的分享。但是作为一个存储系统除了高可用、高可靠外,我们还希望能获得高性能,而Ceph在这方面就有点差强人意,至少在其块存储服务性能上,还有很大的提升空间。我们在Ceph的使用和测试过程中发现Ceph本身对CPU资源消耗比较严重,计算资源竟然成为了系统的瓶颈,以致无法发挥出SSD磁盘应有的性能。我们在测试和分析中发现,其原因一方面是Ceph实现中在网络连接、多线程、锁粒度等方面还需要做进一步的优化,另一方面是伴随着现在网络、存储设备性能的提升,在高IO负载的情况下,系统软件、存储软件本身在IO消耗中占的比例越来越高。 抛开Ceph我们来看一些性能方面的数据对比:

在如今已经普遍使用的万兆网卡下,每秒最多可以收发14.88millions (Packets Per Second) 的数据包,那么一个数据包的处理时间,只需要大概67ns,在2.0GHz的CPU下,只要130个时钟周期。而做一次上下文切换则大概需要上千ns (How long does it take to make a context switch?) 。现在PCI-Express x16的速度已经达到5GBytes/s,而CPU访问内存的带宽也就6-8GBytes/s (Memory_bandwidth) 。可见硬件的性能有了很大的提高,而软件成了制约性能的瓶颈,这就好比我的出行,从出发地到目的地,交通工具的速度从普通火车到高铁、到飞机了,但是候车(机)、安检却还是花费很多时间,我们的旅行时间还是无法降低下来。

DPDK

概述

DPDK(Data Plane Development Kit)就是以Intel为首的厂商为解决上述网络问题而提出的解决方案,在引入到存储领域之前,在软件定义网络(SDN)方面已经有了很多重要的应用,它实际上是为解决x86体系下网络传输效率的一系列技术手段的集合。

多个技术

其中最重要的一项就是采用轮询方式(poll-mode drivers)来实现数据包的处理。

PMDs

操作系统处理IO可以有两种方式:一种是利用中断(interrupt),即I/O设备有IO事件时,产生一个CPU中断,来通知CPU;另外也可以通过轮询,即CPU不断的检测I/O设备,查看是否有IO事件。当I/O设备较慢或者说IO较少时,无疑中断是一种高效的方式,没有IO时,CPU可以进行其他的工作,而轮询的方式,CPU需要浪费很多时钟周期用来检测,IO响应可能还没有中断更及时。但是当I/O设备很快、IO很多时,情况就不一样了,我们知道中断也是有代价的,CPU响应中断时,需要保存现场(content),处理完中断后需要返回并恢复现场,也就是我们通常说的context switch。试想当IO密集、中断很多的情况下,CPU就把很多时钟周期(clock cycles)浪费在了context switch上。随着现在I/O设备性能越来越高,这个问题在现实中也是变的越来越严重。这时反而利用轮询的方式,反而可以提高数据处理的效率。实际上DPDK和SPDK正是在这样的背景下产生的。

在X86结构中,处理数据包的处理方式就是通过CPU中断方式,既网卡驱动接收到数据包后通过中断通知CPU处理,然后由CPU拷贝数据并交给协议栈(TCP/IP Stack),协议栈在内核态完成协议处理后,再交给用户态的应用程序进行数据的处理。在数据量大时,这种方式会产生大量CPU中断,导致CPU无法运行其他程序。而DPDK则采用轮询方式(PMD)实现数据包处理过程:DPDK重载了网卡驱动,该驱动在收到数据包后不中断通知CPU,而是将数据包通过零拷贝技术存入内存,这时应用层程序就可以通过DPDK提供的接口,直接从内存读取数据包。这种处理方式节省了CPU中断时间、内存拷贝时间,并向应用层提供了简单易行且高效的数据包处理方式,使得网络应用的开发更加方便。

通过kernel驱动的包处理流程:

给Ceph插上一双翅膀

DPDK模式下包处理流程:

给Ceph插上一双翅膀

UIO

上面DPDK的数据包处理整个过程都是工作在用户态,不需要CPU介入,不仅节省了CPU中断,还节省了进程内核态和用户态的切换,所以会“节省”很多CPU资源。这样从理论上说起来其实也是好理解的,但是可能还是会觉得有违我们传统上的认识。《Linux Devic Driver》中有这样一句话,相比看过的都会影响深刻,“The most important devices can’t be handled in user space, including, but not limited to, network interfaces and block devices.” 。实际上就像我们前面说到的,这些都是在I/O设备性能迅猛提高的背景下,以及分布式系统的广泛应用、我们期望能在普通的x86体系下,达到媲美甚至超过传统存储系统的性能,而产生的技术变化。UIO模式下的IO栈变化:

kernel驱动的IO栈:

给Ceph插上一双翅膀

UIO:

给Ceph插上一双翅膀

除了采用PMD和UIO,DPDK还采用了下面一些技术。

hugepage

我们知道linux在进行内存管理时,分为物理内存和虚拟内存,由内存管理单元(MMU)完成虚拟内存到物理内存的地址映射,虚拟内存按照页(pages)来管理,大小为4k,MMU进行地址转换需要的信息保存在称为页表(page table)的数据结构中,这样系统在访问一次内存时,需要访问两次内存:首先访问pagetable,获得物理地址,然后再次访问获取数据,实际上pagetable在实现上还往往分为多级(比如page directory + page table)。为了优化这个过程,我们知道CPU会有一个称为TLB的缓存器,来缓存虚拟地址和物理地址的映射信息,减少一次多余的内存访问。但是既然是cache,就肯定会有缓存不命中(miss)的情况,miss时就多出至少一次内存访问。无疑pagetable信息越多或者说page越多的情况下,就会需要越多的TLB空间,空间一定的情况下,miss的概率就会响应变大。TLB类似L1、L2,访问是非常快的,一般只需要0.5到1个时钟周期(clock cycles),而一次内存操作则可能需要几十个操场,可以看出相对来说页表查找是一种很耗时的操作。为了优化上述问题,引入了hugepage,简单来说就是增大page到小,这样可以减少pagetable信息,一个 TLB 表项可以指向更大的内存区域,这样可以 大幅减少 TLB miss 的发生。DPDK 则利用大页技术,所有的内存都是从 HugePage 里分配,实现对内存池(mempool)的管理,并预先分配好同样大小的mbuf,供每一个数据包使用。

CPU affinity

现代操作系统都是基于分时调用方式来实现任务调度,多个进程或线程在多核处理器的某一个核上不断地交替执行。每次切换过程,都需要将处理器的状态寄存器保存在堆栈中, 并恢复当前进程的状态信息,这对系统其实是一种处理开销。将一个线程固定一个核上运行,可以消除切换带来的额外开销。另外将进程或者线程迁移到多核处理器的其它核上进行运行时,处理器缓存中的数据也需要进行清除,导致处理器缓存的利用效果降低。 CPU 亲和技术,就是将某个进程或者线程绑定到特定的一个或者多个核上执行,而不被 迁移到其它核上运行,这样就保证了专用程序的性能。DPDK 使用了 Linux pthread 库,在系统中把相应的线程和CPU进行亲和性绑定,然后相应的线程尽可能使用独立的资源进行相关的数据处理。

除了上述技术,DPDK中还包括很多方面的优化,比如优秀的内存、缓存管理,环形无锁队列等等,使得通过DPDK可以达到非常高效的网络包处理。值的说一下的是,DPDK需要网卡的硬件支持,不过DPDK是一个开源的项目,不仅仅是intel的网卡才支持。

SPDK

概述

SPDK(Storage Performance Development Kit )也是由intel主导的一个项目,目前也已经开源。SPDK是伴随着存储设备的性能提升而发展出来的技术。如今闪存设备已经开始广泛应用,我们在部署使用Ceph时已经是用的全SSD(SATA SSD)。SATA SSD相比于机械硬盘,性能已经有几十倍的提升,后续再采用PCIe/NVMe SSD性能将再有几十倍的提升。以前磁盘IO是最慢的一环,所以其他环境的性能消耗相对都是少数,如今磁盘性能提升很大,相比于存储设备的提升,我们的存储软件架构则没有大的变化,软件的消耗在IO整体时间上占的比重越来越大。SPDK就是来解决这个问题的一个方案,也是多项技术的集合,和DPDK的思路一样,最重要的两点就是PMD和UIO。PMDs对于存储设备来说就是改变之前存储设备的驱动模式,UIO将磁盘IO用户态话避免内核上下文切换和中断处理,减少CPU消耗,这些跟上面DPDK的思路是一样的,这里就不展开了。

CEPH与DPDK、SPDK

目前在CEPH系统CPU瓶颈没办法得到很好的解决的情况下,社区开始引入DPDK和SPDK,国内的一家创业存储企业xsky已经向社区提交了Ceph对DPDK的支持方案,方式是重写了async messenger,然后DPDK(DPDKStack)和kernal tcp/ip(PosixStack)一样作为async messenger的插件。加上后续对SPDK的支持,将形成IO路径全用户态、全异步的模式,将性能发挥到极致。真的像是跟CEPH插上两根翅膀一样,如虎添翼,在统一存储,软件自定义存储(SDS)领域将得到更好的发展。

与DPDK、SPDK结合后Ceph的IO路径:

给Ceph插上一双翅膀

参考资料

http://dpdk.org/

http://www.slideshare.net/garyachy/dpdk-44585840

https://software.intel.com/en-us/articles/introduction-to-the-storage-performance-development-kit-spdk

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址