侵权投诉
订阅
纠错
加入自媒体

2015存储峰会:IO协议栈前沿技术研究解读

2015-12-28 15:07
kumsing
关注

  近日,PMC公司资深数据中心架构师张冬在中国存储峰会上做了关于IO协议栈前沿技术和动态的技术分享,以下是演讲的精华内容。

  IO协议栈的概念

  IO协议栈是操作系统里的一系列软件模块,让你的应用要读盘的时候,比如读一个U盘,U盘插上以后,点一个复制粘贴,复制粘贴是一个程序,并不是某个菜单,你点的这个菜单,激发了这么一个进程,后面起了一个进程,比如Linux下的做运维的都知道有一个dd的程序,这个程序会调用系统提供的一些代码。当然先得打开,然后做一个准备工作,然后才读写。这些代码都是OS提供的,你只需要调用就可以了。这些代码会被映射到用户空间里面。你把IO下发给这些代码以后,你把这些参数传给他,要读写哪个文件,哪个路径,哪个设备,怎么度,怎么写?把所有的参数告诉它。

  它下一步实现一个操作叫陷入内核,中断到内核里面,这一步操作开始非常大,因为牵涉到权限的转换,开销是很大的。进入内核以后,先到一个VFS的层,这是一大块的代码,这个层就是目录层,比如C:/,Linux下/某个字母,再写一些字母。谁来维护目录和底层的存储的实体的映射关系呢?由VFS层维护,你访问的是一个网络盘的路径,还是一个本地盘的路径,是一个文件,串口,终端,其实都是符号,由VFS把IO下发给底下对应的承载者,底下画了四个承载者。还有跨设备的各种设备,还有网络的系统,还有内存里面的数据结构,比如/PROC,有一些运维的时候用的一些命令,把它从零改成一,触发了某一个逻辑,这都是内存里面的数据结构,也在这个符合下限。

  这层再往下,如果访问块设备,直接下到块层,块层是最终对存储设备的集中访问点,在这个层里面,有一些附加功能,比如多路径,加密这种分层,缓存,很多的开源的这些产品,其实都是基本上在块层这个功能上面做二次开发做出来的。块层下面就是一个IO的队列,在这儿做一下IO的优化,合并,存盘这些事情。在这儿会有一个瓶颈,就是IO这个里头的队列是一个瓶颈,上层把IO往这个队列里面放,下层不断把IO拿走。俗话说的SCSI协议栈,包括三层,一个是上层的协议驱动,指磁盘驱动,磁带驱动,如果有其他的设备,比如打印机之类的,SCSI打印机和扫描仪也有,很早的时候,这块就是驱动设备了。SCSIMiddle层就是管SCSI指令,下发下来都是在内存里的数据结构,每个OS都不一样,但是如果发到磁盘,发到外面的交换机,必须把它弄成标准化的,因为外面有很多厂商做硬件,你不标准,就没法做了这个硬件,你不能说为每个OS都做一个硬件。这层除了翻译成SCSI指令,这边有SCSI语义,还有管真正的SCSI的处理,比如超时了怎么办这些事情,这是中间层。

  底下这层是HBA层,首先要有驱动,在HBA上有设备发现的这么一层库,因为传统的SCSI几十年前,那时候只有SCSI这么一种物理硬件,大家可能有人见过,很粗很笨的线缆,后来出现了FC,SAS这些,更快速的、高效的物理链路类型。SCSI协议,如果想跑在这些物理链路上,就需要有这么一块代码,这个网络里面,把你对端的SCSI设备发现上来,如果后端改成SAS,这块代码就会往SAS网络上发出一些广播的消息,将设备探测到,然后才生成设备符号。

  再往下就是硬件,出了协议就是硬件,硬件得连到HBA上,SCSI卡、SAS卡、以太网卡、各种卡,通过这个卡,再通过网络,或者连交换机,或者直连,连到最终的设备上。所以,这儿画的一些箭头指的是什么呢?每一种硬件,每一个角色都有各自的驱动。最底层的设备,它的驱动在最上面,再往上一层,HBA驱动在这个地方,然后HBA上还有一个PCIE控制器,它是从里向外扩散的一个东西。但是,IO要先发给最上面的驱动,先冲着最底下的设备来,驱动是从上往下这么发出去。这是传统的协议栈。

  红色的这块,就是所谓NVMe的协议栈。NVMe跟PCIe有什么区别呢?NVMe它是一个协议栈,是一个协议。跟说话一样,中文就像是SCSI,非常博大精深,有语法,还有成语,非常厚重。NVMe相当于英文,简单直接26个字母。但是,我们都是用嗓子来说话,都是用空气来传播,振动来传播,就是这个道理。SCSI也可以跑在PCIe上,就像SCSI跑在FC上一样,同理NVMe也可以跑到以太网上,也可以跑到FC上,怎么over都行,over在串口上都行,只要不嫌慢。NVMe的协议栈非常轻量级,像英文一样,表达简单,所以它的速度比较快。

  传统IO协议栈的问题

  我们看看这个传统协议栈到底出了什么问题?为什么这么多人在尝试修改它?主要问题就在于闪存。它没出现之前,没有任何问题,它一出现,全是问题。我们看到底有哪些问题?

  第一个问题是太长。大家可以看到,前面讲的所有这一堆东西,其实整个就是IO协议栈。当然,SCSI协议栈是泛式的,一般指下面这块,但是上面这块也应该算。它经历了多少个块?非常多的模块,你每经历一个模块,你这个代码就要在CPU内存之间交换、执行一会儿,还牵涉到来回切换。当然,你拿人的标准来判断,CPU执行的这一条IO可能费不了多长时间,比如微秒、毫秒级。但是,对于SSD,SSD响应非常快,如果上面太慢,性能就发挥不出来。我们常说NVMeSSD性能很高,你是把它放到机箱里面性能很高,但是假设把一块NVMeSSD放到海南去,从北京发一个IO协议到海南,然后它返回,它肯定不会快了。也就是这个IO发出来,到磁盘被收到之间,经历的路径越长,这个时延就越大,经历的模块越多,每个模块处理的事情越多,时延越大。那就是说NVMe离远了,它就不快了。就因为这个时延太高。

  第二个问题是太重。所谓太重,每一层都有自己的处理逻辑,比如下到VFS,要搜一下这个目录到底对应的谁?搜fstab表,要是访问文件系统,还得到文件系统把元数据读出来,也就是读元数据的时候,文件系统就会往磁盘上发IO,读上元数据,找到处理你这个IO必要的信息,然后IO才能下到盘,相当于一个IO触发了N个IO,有可能很慢,很重。Block层有很多协议要处理,SCSI协议栈更厚了,因为SCSI传统的东西,发展到现在几十年了,里面什么东西都往里加,各种库,各种不定都往里塞,塞的整个协议栈很重。再往下就是黑盒,到外面的设备怎么实现,你也不知道,有可能就是一块盘,也可能是被别人虚拟出来的盘,也有可能是分布式的,像刚才讲的那种,也有可能是集中式的,你也不知道。但是,你可以猜到什么?下面的存储设备,其实它内部也是个OS,你的IO到他那儿,他也要经历这层,最后才下到真正的物理盘,可能经历N轮,IO才能下去,所以传统协议栈又长又重。

  第三个问题是太窄。所谓太窄,就是Block层的队列只有一个。这个队列就是IO不断的往里堆,你有多个应用访问底下的设备,多个应用都是多盒CPU,每个CPU运行一个线程,每运行一个线程都往下发IO,如果正好四个线程都往里发IO,相当于一个单车道,两辆车同时往里塞,就会出现撞车,IO也是一样道理。谁要往这里面发IO,要更新写指针,线程需要将原来的值读入,更改,再写回去,如果线程1读入,线程2也读入,那么这两个线程最后就会有一个IO被丢掉以及错乱。另外。如果这个变量是双字节,或者四字节,你写一个字节,我写一个字节,最后写乱了,就崩溃了,乱套了。所以,如果要往里插入IO,必须把这个队列锁住,又把这个变量锁住,先加锁,加锁别人就不能访问了,然后你再往里写。这样顶上看似是并行的,到这儿就变串行了,又需要加锁,所以开销就非常大了,最后导致性能比较差。当然,对于机械硬盘,都不是问题,因为机械硬盘太慢了,这点开销对它来讲,根本就不算开销。

  第四个问题是太浅。这个队列不但就一个队列,还窄,而且还浅,里面容纳不了多少IO,SATA最大32,SAS盘最大256,上去还有HBA卡的队列,驱动里面的队列,Block里的队列,这些队列都是照着这个盘设计的,比如256个盘,256×32,最大照着那个来,但是实际比这个还要少。浅会造成什么问题?如果底下很慢,浅没有问题,因为一时半会儿消耗不完这也IO。但是,如果很快,会发现一会儿这个队列就空了,一会儿IO还没有下来,又空了,整个这个跟开车一样,油给不上,就是这个道理,太浅了。

1  2  3  下一页>  
声明: 本文由入驻维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。

发表评论

0条评论,0人参与

请输入评论内容...

请输入评论/评论长度6~500个字

您提交的评论过于频繁,请输入验证码继续

暂无评论

暂无评论

文章纠错
x
*文字标题:
*纠错内容:
联系邮箱:
*验 证 码:

粤公网安备 44030502002758号