一、背景
面对着业务的发展,不管是在线,近线还是离线系统,其所需要的存储规模以及存储成本,成倍上涨。如果还是采取传统的分散式存储管理方式,除了高昂的管理分散式存储的成本,还会增加存储成本。
因此,我们极需一种既高效又省成本的数据存储以及存储管理方式。自然地,我们把目光聚焦到了分布式存储系统上。
从目前行业发展趋势来看,各大互联网公司都设计或者维护了自己的分布式存储系统。如Google的GFS(Colossus 为GFS第二代分布式存储系统),Facebook和LinkedIn的HDFS等。由此可见,分布式存储也是大势所趋。
同样在阿里,我们今年对数据库进行计算存储分离,面临的难度也非常大。因此,我们也对各种分布式存储进行了许多研究,开源的如Ceph,还有阿里云的盘古等。
我们紧跟业界以及开源社区,并不断吸收其优秀成果;同时也做了大量的研究,测试和验证。根据集团业务的特性,我们进行了许多软件层面,甚至软硬件结合的优化,为集团业务的发展赋能。
分布式存储系统所具备的优点就是为了克服传统存储方式的缺点。那么,它将会给我们带来哪些收益呢?
二、分布式存储的收益
分布式存储系统所带来的收益主要体现在以下几个方面。总体上来讲,主要是降低存储成本,同时也提高了资源的分配效率,助力计算资源的弹性调度。
2.1 解除机型配比
一般性的,我们将服务器分为两部分,计算资源和存储资源。计算资源如CPU和内存,计算资源的特点就是无状态,资源分配比较灵活。存储资源有状态,需要保证数据的一致性和持久性,资源分配比较固定,会涉及到数据的迁移。如果数据量太大,就会遇到迁移性能的问题。
传统的存储方式,是单台服务器类型的,将计算资源与存储资源(HHD和SSD等存储设备)绑定在一起。因此一台机器CPU,内存与存储设备比值都是固定的。这带来的一个问题,就是我们会比较频繁的改变我们的机型,因每年我们的计算资源与存储资源的配比都在变化,业务数据的增长非常快。这也在某种程度上提高了每年采购机器的成本。
引入分布式存储系统后,解除了这两者紧密耦合的现状,使得降低存储成本成为了可能。计算资源和存储资源解耦后,各自可以按不同的策略进行过保,在一定程度上降低了成本。
2.2 解决存储碎片
传统分散式的存储模型,必然会有存储碎片问题的存在。因为每台服务器都会为线上业务预留一定的存储空间,以满足将来业务数据增长的需要。但是采用预留空间的方式会有一个问题,就是我们无法准确地评估真实的实际空间需求,往往预留的会比较多,业务实际需求与预留空间这两者的差距就是存储空间浪费量。
这些服务器残留了独立的10G,20G的空间碎片,在一定程度上也并不能满足业务实例申请的规格,但将这些碎片合并在一起就能满足业务所需。
引入分布式存储系统后,大大减少这种碎片,业务实际的数据存储空间按需进行动态分配。我们引入数据增长趋势分析,每天或者每周进行存储在线动态扩容,以提高管理效率,降低存储成本。
2.3 计算资源弹性
传统资源配置下,我们的计算资源调度水平受限于单台机器的存储容量。在制定Docker容器化规格时,连同存储容量一起考虑,其调度和资源分配算法异常复杂。当CPU,内存以及存储容量这三者在某种程度上发生冲突时,往往会牺牲一定的存储资本,来达成Docker实例规格的妥协。
将计算资源与存储资源分离后,计算资源得到解脱。我们在安排机器的过保时,采用不同的策略,降低机器采购成本。
另外,计算资源是无状态的,独立之后,进行容器化,就可以方便的进行调度,提高效率。更重要的是,让离在线混布成为一种可能或者让其更高效。
2.4 解决差异化需求
某些新兴业务,往往会呈现爆发式增长。自然而然,其数据量也会呈跳跃式的爆炸。此时对存储的规格的需求就会比较大,因为业务短时间内往往来不及做架构优化,或者做数据分片来降低单机的数据存储容量。这会给传统的存储模型带来很大的挑战,因为传统的分散式的单台服务器的存储容量已经不能满足需求。
分布式存储系统破除了这种大存储容量实例规格的天花板限制,业务不再关心底层存储的实现,我们根据业务数据的增长趋势分析,动态扩展存储空间。
三、面临的问题
尽管分布式存储有上述的诸多优点,然而如何设计其高可用性,如何减少数据丢失的概率,是摆在我们面前必须要去克服的问题。那么我们又是如何来架构和设计的呢?
3.1 数据丢失
在分布式存储系统中,为了防止单机故障而造成数据丢失,往往会引入多个数据副本,我们称之为replica set。此replica set中数据的副本个数用R来表示。一般的,R等于3,就表示是这份数据的存储份数是“3”,也就是我们通常所说的 3-way replication。
在随机的模式下,有可能replica set的3份数据位于同一个rack中,那么当此rack掉电就会导致数据丢失,对线上业务造成影响。随着集群规模的变大,如果有超过1%的数据节点遭遇断电,并且断电之后又有一部分机器重起失败,或者进程异常导致数据文件损坏;那么其影响都将随着集群规模的增长而变得异常严重,成为分布式存储系统致命的问题。
当然,我们可能通过增加数据的副本数即“replica set size”,来降低数据丢失的概率。又或者提高底层IDC以及网络的高可用性,减少断网或者网络故障发生的概率。但是这些方法都是绕开问题的本质来优化的,另外带来的存储成本的增长也是不能接受的。
早期,Facebook和LinkedIn在使用HDFS时,也同样面临这样的问题,也做了这方面不少的验证和测试。最终较为一个合理的方案就是通过合理安排replica set中数据存储的位置来降低数据丢失的可能性。
3.2 数据散射度
为了能够更好的理解数据副本存储位置(data locality),我们引入数据散射度(scatter width)的概念。怎么来理解数据散射度?
假设一个集群,有N个节点,数据副本replica set size为R,那么数据散射度最差的情况就是从N个节点中任意取R个的组合数,也就是C(N,R)。我们假定N为“9”,R为“3”。
举个例子:我们定义三个copy set(存放的都是不同的数据):{1,2,3},{4,5,6},{7,8,9}。任意一组copy set中存放的数据没有重复,也就是说一份数据的三个副本分别放置在:{1,4,7}或者{2,5,8}或者{3,6,9}。那么这个时候,我们称之为其数据散射度S为“3”,远小于随机组合的C(9,3)。
随机组合时,任意3台机器Down机都会存在数据丢失。而采用Copy Set方案后,只有当{1,4,7}或者{2,5,8}或者{3,6,9}其中的任意一个组合不可用时,才会影响高可用性,才会有数据丢失。
综上可知,我们引入copy set的目标就是尽量的降低数据散射度“S”。
但是现实远非这么简单,当我们降低数据散射度后,其数据恢复速度变小,也就是说恢复时间变长。因此,我们必须在数据散射度“S”和恢复速度中找到一个平衡。
四、高可用性设计
一般地,业务统一用N个“9”来表示一个分布式系统的高可用性。一般业界做得好的,都已经能达到9个“9”。那么,我们的分布存储系统又如何来设计,又能达到多个“9”呢?
4.1 OSD Domain
默认的OSD节点bucket是基于Host的,也就是说取决于一台机器上存储设备的数量。如下图所示,一台Host上面有4个OSD(device,如HDD或SSD等)。所以在集群存储数据时,会寻找数据存放位置。
首先会将Primary放入到Host0的四个节点中,即{0,1,2,3}。同一组中的OSD会根据权重进行平衡。另外两个副本按同样的权重计算方法放到Host1和Host2中。从总上来看,就是三份数据分别放到Host0,Host1和Host2上面,在每一个Host中数据均匀的分布在4个OSD节点上。
当Host0中的OSD 0节点(存储设备)挂掉,会做两个事情:
- 会从Host0中剩余的OSD节点中,找可替代节点,将新增数据写到剩余的节点中
- 当OSD 0恢复时,会将Host0其它OSD节点中刚才新增的数据copy回OSD 0,这个叫recovery的backfill过程
我们的目的,就是减少recovery时backfill的时间。所以如果一个Host下面的OSD节点越多,就会有越多的节点参加backfill,恢复速度就会越快。一般单台机器的存储设备挂载都是有限制的,我们很快就会遇到瓶颈。另外,目前的SSD 128K的写入速度也在400-500M/s之间,跟我们的目标相比,并不算太高。
基于此,我们计了OSD domain,它摆脱了单台机器的设备挂载量限制。如下所示,其中黄色虚线框中的OSD都在同一个OSD domain中。一个OSD domain中包含4台机器,每台机器有4个OSD节点(存储设备)。此时,当一个OSD挂掉后,会有15个OSD参加新增数据的平衡和recovery的backfill,大大缩短了恢复时间。
在这些OSD Domain中,故障是隔离的,所以一般也称OSD Domain为故障隔离域。
4.2 Replica Domain
在第三个章节中,我们提到了数据散射度问题,数据散射度越大,可用性越差,丢失数据的可能性越高。因此,我们怎么来解决这个问题呢?
这需要结合copy set的原理来做合理架构与设计,再基于上面OSD domain的设计,我们再新增replica domain,将三个不同rack中的OSD domain组成三个copy set,用于存放replica set的三个数据副本。
具体架构图如下,这样部署后,copy set做到了一个非常低的水平。
另外,为了节省IDC机架位资源,我们在一个集群下分为两个replica domain,每个replica domain下面又有3个OSD domain:
4.3 泊松分布
到这里,我们的副本存放拓扑结构设计差不多完成了,那么接下来,我们来计算下这种部署能做到多个“9”呢?
在分布式存储集群中,X个磁盘发生故障的事件是独立的,其概率是符合泊松分布的。
拿磁盘来讲,其MTTF为1million,因此AFR为“1-(24*365/1million)= 0.98832”,约为“0.99”。泊松分布中,两个重要的变量因还素X和Mean我们都确定了。
对于分布式存储池来讲,X就是replica set size “R”,Mean就是“0.99”。
我们存储集群的高可用性可以简单的按以下函数来量化:P = f(N, R, S, AFR),其中:
- P: 丢失所有副本的概率
- R: 副本数,也就是replica set size
- S: 单组OSD Domain中OSD的个数
- N: 整个集群中OSD的总数
- AFR: 磁盘的年平均故障率
进行演化后,我们得到可用性公式:P = Pr * M / C(N,R),其中:
Pr:为R个数据副本同时失效的概率,相当于是Primary在做recovery恢复时,其它R-1个副本也Fault掉了。
M:为可能的Copy set数目
R:为replicat set size,即副本数
N:为集群OSD总数
C(N,R):为N个OSD节点中,取R个副本的组合数
从上面的高可用性公式可以看出,一般在给定集群OSD节点数和副本数“R”后,C(N,R)也就确定了。那么,为了提高可用性,我们必须想办法降低Pr和M的值。
存储节点的拓扑结构,基于以上分析,做的最终架构优化:
- 为了降低Pr,我们引入了OSD domain,默认基于Host单机,无法发挥网络“多打一”的优势,我们引入OSD domain,提高单个OSD恢复的速度。将原来三个OSD节点扩大到16个,恢复速度提高了5倍以上。
- 为了降低M,也就是copy set的size,我们引入了replica domain。同一个PG中所有的OSD必须在同一个replica domain中,降低了数据丢失的概率了,提高了高可用性。
以下经我们架构设计后,再根据泊松分布计算出来的高可用性:
根据这个架构设计,在同一个IDC内,我们基本上能做到接近于10个“9”的高可用性。比之于默认的算法,高可用性整整提高了将近100倍。
4.4 网络拓扑结构
根据上面的分布式拓扑结构设计,再结合现有的网络拓扑结构,我们的架构设计最终方案为:
一个存储集群24台机器,两个replica domain,每个replica domain中有三个OSD domain,每个OSD domain中4台机器,因此计算公式如下:
2(一般为两个,由网络交换机下挂的机器数决定)* 3(replica set,replica domain) * 4(scatter width,OSD domain)= 24
原则性的,replica domain的机器位于三个不同的rack时,这三个rack不能在同一个port中。一个交换设备下挂16台机器,两个OSD domain,这两个OSD domain属于不同的replica domain。
在实际生产中,为了高可用性,我们建议至少部署4个rack集群。另外,在集群扩容时,建议按一组replica domain的规模来扩容。
每一组OSD domain中,存储机器数目也可以是4台或者8台不等,可以按单台的机器容量来进行动态规划,但是计算公式可大致参考以上的部署策略。
五、总结与展望
目前,软硬件结合的分布式存储IO stack也在不断的优化(SPDK,NVMe 等)中,网络基础架构RDMA的网络设计也在验证和POC中。这些新的思路与整个业界的生态体系发展趋势一致。
在可预见的将来,存储技术上将会有不断的融合与补益,这也有利于存储技术的更新换代,也更好的支撑业务的快速发展;最终具备,技术扩展业务边界以及业务向技术拿红利的能力。
计算存储分离更多细节,将在以后的篇章中讲述。