美团云混合存储系统:成本及性能优化路径

前言

在过去60年间,机械硬盘的容量呈指数级增长的同时体积也越来越小。1956年IBM一块 5兆的巨型硬盘需要数人推上车去运输,到2016年一块3.5寸的机械硬盘就有10TB的大小,60年增长了9个数量级。但与容量和体积的变化相比,机械硬盘的性能增长非常缓慢,吞吐率基本保持在200兆每秒上下。IOPS增长更慢,一块7200转的硬盘在不同的iodepth下的IOPS次数大概在100-200范围内。这是容量与性能上的失衡。

而另一方面,目前市场上固态硬盘和机械硬盘报价,单GB的成本可以相差10倍,巨大的差价就是巨大的优化空间。

容量与性能、成本的失衡促使美团云存储研发团队开始推进混合存储系统的研究。

设计混合存储系统的意义

通常,根据成本和性能这两个维度,我们可以将云硬盘分成3档:

  1. 容量型云硬盘:成本比较低,性能也比较低的产品
  2. 效率型云硬盘:成本及性能适中的产品
  3. 性能型云硬盘:性能比较高,价格也比较高

因为性价比适中,所以我们在云平台上给用户创建最多就是效率型的云硬盘。

我们不妨计算一下,如果要求云平台为100个云硬盘同时提供4000并发IOPS能力的话,我需要准备一个什么样的系统。有两种实施方案:

第一种,如果用传统的机械硬盘去搭建这个系统,大致需要6千块硬盘,产生48千瓦的功耗,3年TCO就会达到千万元。

第二种,用单盘性能3万(保守估计)IOPS的固态硬盘,则只需40块,功耗是0.1千瓦,3年TCO只有20万。

两种方案同样达到目标的情况下呈现出50倍的成本差距,固态硬盘性价比优势更明显。

因此,当我们设计存储系统的时候,性能和容量主要为满足需求,当这需求确定了之后,就会有一个最优成本方案。这也是我们设计混合存储系统的一个主要思路。下面具体讲一下如何通过对混合存储系统进行成本优化和性能优化来实现这一想法。

混合存储-成本优化路径

缓存优化

在如何平衡需求与成本获得最优解的思考中,我们很自然地想到将机械硬盘的很多flash组合起来形成混合存储,并让每一块flash都发挥出比较显著的优势。那么如何优化呢?

优化的方式有以下两种:

一种是RAID卡缓存,把闪存当作机械硬盘的混存。如果要是这样混存的话,其实最简单的就是在RAID卡上面有加一个小的闪存给做缓存;

另一种是内核缓存,为内核增加了一些模块,如用flash给机械硬盘做缓存。

缓存的优化方案有很高的性价比,加上去之后效果是立竿见影。但是有一些缺陷,优化效果受限于缓存的命中率,对随机读测试无效,无法实现产品承诺。所以我们没有放弃了这一方案。

纠删码

降低成本还有一种方式就是纠删码,传统的分布式存储一般是3块数据,每一块数据分3个副本,一共要存12块。换了纠删码的话,3块数据通过数据运算产生两个校验块,则是存6块,达到空间下降一半的效果。

但是纠删码分布式存储条件下,尤其是热的分布式可读可写的情况下,实现纠删码是一个非常复杂的过程。而且它在写作的时候对性能是有影响,因为写的时候有编码,而编码会对IO流程产生一些影响,会对性能产生负面效果。

所以我们尝试了一些其他的方案。首先我们进行了一个性能测试,用不同的测试方式对SSD随机写的性能IOPS和机械硬盘顺序写的IOPS分别进行了测试。

测试结果显示,机械硬盘随机IO非常差,但是顺序IO结果不错,大致可以达到跟一块SSD的水平。这一结果启发了我们,可以在机械硬盘上用顺序写的方式重新写。

当客户端要读数据的时候,数据就直接从闪存里面去读;当写的时候,写到闪存里,同时顺序的写到两块机械硬盘上面。这样的话,读是从固态硬盘读,可以保证良好性能;写的时候固态硬盘随机写性能也好,换了这方式以后整个系统的性能就实现了均衡。

前文提到在机械硬盘上是顺序写,顺序写有一个问题,因为顺序写相当于排列队列,读的时候就需要知道到队列的位置去读。所以这种方式对读很不利,我们还是要把专用的顺序写到专用数据,回写到所谓数据块里面。所以,这需要系统允许在比较闲置的时机,将数据回写到Journal,保证这顺序有高有低的。实测,线上workload存在明显的波峰波谷现象,所以也证明了通过纠删码实现混合存储这一方案实现成本优化的可行性。

上述混合存储的思路是基于美团云的块存储系统得以实现的,整个系统是美团云存储团队完全自主研发。关于该存储系统的详解,可点击《分布式块存储系统Ursa的设计与实现》了解详情。后续我们还将分享纠删码的相关内容,请持续关注更新。

混合存储-性能优化路径

固态硬盘的性能非常好,如果想要把固态硬盘性能发挥出来的话,需要在软件上做很多的优化。第一个方面是优化代码效率,第二是发觉利用并行性。

代码效率

在代码效率方面的优化,有几个方面:

  • 避免使用Iostream
  • Stack vs new/delete
  • Resource poling&caching
  • Logging
  • SSE/AVX(CRC、EC)
  • 避免使用Sendfile()
  • 保持可维护性

上述几种方式中,Sendfile有一个非常大的问题,它不支持异步文件读取,这样的话会影响服务端的并发处理,反而会降低性能,所以我们不建议用sendfile。还有iostream,我们注意到有些开源存储系统在使用,虽然在IO提升方面可能是比较方便的方式,但是效率比较低,因此我们也不建议使用。

并行

在并行的方面,有四个优化方向:

1、无关任务独立并行执行

在服务端把无关的每一个Disk都有一个或多个进程进行服务,客户端每virtual disk 一个进程;

2、盘内并行

使用异步API;

3、任务流出:流水化处理

磁盘和网络并行运行。

从这图上可以看出来网络的流水化对IOPS提升非常明显。

4、任务完成:乱序完成

慢请求不阻塞其他请求。

SubChunk

IOPS方面,机械硬盘吞吐率表现较差一些。所以我们会把机械硬盘上面做SubChunk来提高吞吐率。

确定优化方案后,我们对该方案进行了一些性能评估。测试环境中我们用了三台服务器,其中一台服务器配了12块SSD,另外配了12块HDD。

在吞吐率方面我们的混合存储方案性能可以跟SSD性能相差不大;

在IOPS方面可以说两种方式基本上是没有什么显著区别的;

在延迟上,我们首先用了ping-4KB做测试,大概是一百多us的延迟,然后按照SSD+ping-4KB、SSD-Hybrid、SSD3R分别去读写数据测延迟,SSD-Hybrid与SSD3R的延迟基本持平。这个延迟对于TCP网络加以太网还是不错的。

因此这一混合存储方案从性能和成本是上能够满足产品需求的。性能上面还有一些潜力可挖,比如说用RDMA等,对此,我们今后还将持续优化。

发布于 2017-07-05