上周,腾讯云SSD云盘在官网开放内测,一周以来接收了2800+用户内测申请(点击“SSD云盘”可查看原文免费申请内测),SSD如此火爆,不禁让人想一探SSD云盘背后的强大技术支撑。
今日,InfoQ主办的QCon(2016全球软件开发大会)在北京举行,腾讯云资深存储架构师吉永光分享了腾讯云弹性块存储系统的实践,首次披露了SSD云盘的设计理念与技术架构。
云小哥第一时间为大家送上现场分享
吉永光
腾讯云资深存储架构师
在腾讯云负责分布式存储系统的开发与运营工作。从事多年集中存储产品研发,并推出多个中端存储产品以及相关存储管理软件。
大家好!今天要分享的内容主要有:
Overview
弹性块存储架构
关键实现技术
典型应用
云存储服务的最底层,通常是若干个抽象的存储池,这些存储池可能基于分布式存储系统构建,也可能是基于传统的SAN存储服务器,或者是两者的混合,其介质可能是sata,sas,ssd,也可能tiered storage pool。
存储池通过虚拟存储网关对外提供统一抽象的存储服务,其服务对象可能是 object存储服务和block存储服务。
今天我们的分享主题focus在弹性块存储服务,那我们重点看下block存储的软件协议栈。
通过虚拟存储网关的抽象,我们将存储池的资源以volume(虚拟磁盘)的形式提供给虚拟卷控制器驱动,虚拟卷控制器负责将远程存储资源虚拟为本地磁盘提供给hypervisor,hypervisor再将磁盘提供给上层的虚拟机用户使用。
用户可以像使用本地盘一样,使用block存储服务,比如:分区,创建文件系统,并基于文件系统构建web,mysql或者hadoop等服务等。对于使用文件系统的这类应用来说,从自建迁移到使用弹性块存储的公有云,几乎是零成本的。
目前主流的公有云提供商,比如AWS,腾讯云,阿里云等,都需要用户通过购买虚拟机和云盘的方式来获取弹性块存储服务。今天跟大家分享一下腾讯云弹性块存储服务也就是云盘后台分布式存储系统的设计和实现。
我们对于底层存储系统的设计理念就是简单,越简单越可控。
从架构图可以看到,我们的系统主要分为三个模块:Client模块、Master模块,Chunk server模块。Client通常部署在hypervisor上,也就是概述图里面提到的Volume storage controller。
它主要有两个功能:
一是负责磁盘虚拟化。将存储池抽象的volume空间映射为本地盘,存储池的volume是由分布在不同Chunk server上的Block组成,client负责将它们映射为统一的逻辑地址;
二是存储协议转换。将用户的IO请求按照固定的块大小进行拆分,并将请求路由到不同的Chunk server。
Chunk Server是存储节点,负责管理分配Block,保存用户数据。对存储系统来说,最重要的是数据安全,所以我们采用每份数据冗余三份的方式保存。每个Block块会分布在不同的三台Chunk server上。
在公有云中,用户的数据都存在同一个存储池中,用户数据隔离非常重要,所以Chunk server还会进行用户的访问鉴权,只有合法的Client才能访问Chunk server数据,鉴权控制粒度是盘和用户粒度。
Master模块主要负责管理Client到Chunk server的路由,以及Chunk server的故障剔除和恢复。
Master将路由信息推送到Client,Client根据路由信息对用户IO请求实施转发。同时,Maste负责监控Chunk server的状态,当集群出现坏盘或者死机时候,及时对其进行剔除,并启动数据迁移和恢复。
我们将Chunk server上的存储空间划分为若干固定大小的block,它是空间分配回收的基本单位;用户看到的统一逻辑地址空间,就是由分布在不同chunk server上的block构成;chunk server负责block的分配管理。
如果整个系统的路由都已block为粒度进行管理,势必对Master和Client内存造成巨大压力(PB级别的系统,其路由条目可到GB级别),为了优化路由,大多数分布式存储系统都会在block基础上增加一个逻辑管理层,我们称为partition。
partion是路由,故障恢复的基本单位,每个partion包含若干的block;通过引入partition,路由条目可缩小到MB级别。
在分布式系统中,节点故障是常态,如果降低节点故障对用户访问的影响,以及减少故障恢所需要搬迁的数据量,是分布式系统设计首要需要考虑的问题。一致性hash算法能有效解决这两个问题,所以一致性hash在分布式系统的设计中,有着广泛的应用。
为了让用户访问均衡,我们将hash ring划分为多个hash node,hash node对应一组partition group(包含3个partition),不同的hash node可能对应相同的partition group。
首先,每块云盘都有独一无二的diskid,diskid与用户请求的blockid(逻辑地址空间上的id)号,可以构成一个独一无二的key,用来标识某个block;
然后,使用该key可以从一致性hash环上定位到具体的hash node,从而找到该block所属的partition group,该partition group包含了三份数据所属chunk server的ip,磁盘信息;
最后,client根据该信息将请求forward到指定的chunk server上。
由于我们采用了三份本存储,任何一份数据异常,另外两份数据必须是可以用的,这就要求三份数据是严格一致。
分布式系统写多份通常有两种方法:
从client直接写多份到存储副本;
client先写到主副本,再由主副本流水同步到从副本。
第一种方式,写延时最小,但是由于client写三份数据,给他带来的网络流量压力较大;第二种方式,client流量压力最小,但是写延时相对较高。
我们采用了折衷的方案,client先写主副本,同时写两份从副本,当从副本更新成功后,向用户返回写成功。原则是写三份成功再返回用户成功。对于读请求,直接向主副本请求数据。
分布式系统中,副本故障是常态,在故障期间,分布式系统对外提供的是降级服务,如何快速完成数据恢复,是衡量存储系统好坏的重要标准。
导致副本故障的原因很多,有存储设备自身硬件问题,也有网络问题,或者驱动,自身程序的bug等。
若对于所有故障采用相同恢复方式的话,恢复代价较高,比如:对于4T的sata盘,受限磁盘带宽,按照50MB/s的恢复时间,大概需要花费23小时,如果是整机故障,则恢复代价更高。
是否任何情况下我们都需要对数据进行全量的恢复呢?
实际除了硬件故障外,软件或者网络故障其实都可以在短时间内恢复,而在这个时间内发生的数量修改并不多。
我们采用增量恢复技术来加快用户数据恢复,所谓增量恢复,即故障节点恢复后,只向主同步节点故障期间的数据修改即可,这个数据量是远远小于全量恢复的。
如何做到增量恢复呢?
迁移恢复的最小逻辑单位是partition,最小物理单位是block,每个block维护自身的seq号,每次更新,seq号会自增,用户新的写请求依然会同时写到三个副本(包括故障恢复副本),但是故障副本的新写入数据只能写在内存cache,不能刷新到磁盘,后台进程负责比较故障副本上block与主副本block的seq,相同的则跳过恢复,不同的则恢复到故障副本磁盘。
当然,并不是每次故障都那么幸运,能快速恢复,比如不可逆的硬件故障,更换物理设备的时间会比较长,这个时候可能我们需要发全量的数据迁移。即将故障partition的所有数据迁移到另外三份正常的partition。
Mater负责分配三份目的Partition,用户新请求写到主节点后,同时写到另一份从副本和目的主副本,然后目的主副本负责同步到两份目的从副本。后台进程负责将存量数据从源主副本同步到目的副本。
这里需要考虑后台进程与用户写请求的互斥,具体实现原理与快速恢复相同。
如果说可靠性是存储系统安身立命之本,那性能则是其攻城略地的利器。
对块存储系统来说,其性能衡量标准主要有四个方面:
顺序读性能
顺序写性能
随机读性能
随机写性能
对云盘而言,由于底层采用了分布式架构,其发性能,随机性能是大幅优于本地盘的,但由于网络延时的原因,其顺序读写性能与本地盘相比,有着较大差距。
对于写性能,由于文件系统cache的存在,将用户写请求转为了异步请求,其延时对用户并没有大的影响;但是顺序读,文件系统只有简单的预读算法,所以读请求的延时,对用户体验有重大影响。
解决顺序读性能问题,预读是最有效的方法,可以扬长避短。决定预读效果的主要有两个方面,一个是预读算法,一个预读窗口。要实现一个预读算法很容,只需要简单记录用户请求,并判断新请求的起始是否上个请求的结尾即可。
但实际应用中,是否有这么理想的模型呢?
比如同时拷贝几个文件,或者云盘上同时运行了几个应用进程,这都可能导致同时存在多个请求流。如果采用简单的预读算法,其预读效果可能不理想。
为了解决这个问题,我们采用了多路预读方式,即同时探测多个读请求流,若发现为预读,则启动多路预读,保证每个顺序读请求流的命中率。
预读窗口显然是越大越好,可以充分发挥分布式存储系统的并发优势,但是一味的扩大预读窗口,会对后端存储造成压力,影响其他业务IO,最理想的窗口应该是可以保证前端请求可以持续不多的在预读cache命中。
我们会根据前后端的访问延时,动态的调整预读窗口大小,保证命中率的前提下,尽可能降低对后端存储的压力。
从快照的定义可以看出,快照的主要用途在于容灾,对生产系统的milestone进行备份。
投资界有句名言-“不要把鸡蛋放在一个篮子里”,所以我们设计快照系统的时候,将快照数据存在了与生产系统隔离的,不同存储引擎的存储系统里面,除了在硬件上容灾外,还可以在软件和运营层面容灾(案例)。
当用户创建快照后,我们立即启动后台进程,已block为单位,将用户数据从生产系统拷贝到快照系统,为了保证用户数据的时间点一致,我们快照设计采用了多版本和Cow技术。
用户创建一次快照,用户的写入数据版本就会自增,并分配新的block进行保存,避免对原来数据的修改,从而保证数据的时间点一致。
由于快照分配也是以block为粒度,而用户写不一定覆盖整个block块,所以需要在用户第一次写时,将旧block数据拷贝的新block后,在实施修改。后台进程会负责将所有的旧block拷贝到快照系统。
所以,在我们设计中,创建快照是一个瞬间过程,但整个快照数据的备份,是需要耗费一定的时间,其长短又备份带宽决定。
前面我们也提到,快照的主要目的是容灾,当我们使用快照实施回滚时,通常是发生了数据丢失或者损坏。而快照数据是保存在与生产环境隔离的存储系统中。
如何快速的实施回滚呢?
首先,快照的回滚确实与创建一样,存在数据搬迁过程,需要一定的时间窗口,那为了让用户能够实时回滚数据,我们设计了读写的trigger机制。
用户一旦使用快照实施回滚以后,我们立即启动回滚进程实施数据的搬迁,而且这个时候,用户即可使用该快照数据了。
我们后台通过bitmap记录了完成搬迁的block块,当用户请求时,先检查对应的block是否已经完成回滚动作,若未完成,则先阻塞用户请求,优先触发对该block的回滚,完成后在执行用户请求,从而保证用户能实施使用回滚数据。
数据是企业最核心最有价值的东西,快照虽然能有效快速的将数据恢复到某个时间点,但毕竟存在一定的RPO窗口,其窗口内丢失的部分数据,可能就是一家企业的生命线。
目前公有云的用户运营水平参差不齐,对部分有运营经验和实力的公司,为了保证自身的核心数据的万无一失,除了选择使用云盘外,可能还会在自身业务侧设计容灾架构。
但大部分公有云用户可能不具备这类意识和能力,一旦发生黑客攻击或者误操作导致数据损坏时,虽然通过快照能够进行一定程度的补救,但丢失的部分数据依然可能是致命的。
为了彻底消除RPO窗口,我们加入了CDP机制。其实现原理非常简单,即所有的用户修改请求,除了应用到生产系统,我们会将其旁路到CDP系统,当用户线上系统出现数据损坏时,可以通过重放请求,帮助用户恢复到任意时刻的数据。
然如果CDP系统保留用户全量的修改数据,其成本过于高昂,难以产品化以帮助到广大用户。
为了降低成本,我们结合快照,仅保留7天的修改数据,从而保证用户能恢复到7天内任意时刻数据,从而彻底解决用户数据丢失的后顾之忧。
高性能、高数据可靠性:高效支持虚拟机热迁移,提前避免物理故障带来的业务中断 ,适用于高负载、核心关键业务系统。提供三份数据冗余,具备完善的数据备份、快照、数据秒级恢复能力 。
弹性扩展:云盘可在区域内自由挂载、卸载,无需关闭/重启服务器;云盘的容量可弹性配置,按需升级容量;单台虚拟机最多可挂载10块云盘,容量达40TB 。
云盘多线程访问能力优秀,高效支持Hadoop-Mapreduce、HDFS。高效应对TB/PB级数据的离线处理,广泛应用于数据分析、挖掘、商业智能等领域。
我们做了一个测试,择取12Core 40GB RAM 服务器5台,各挂载1TB SSD云盘、1TB 普通云盘,进行Spark/zookeeper/HDFS部署,模拟离线数据分析。
测试结果显示,1.5TB数据,5块普通云盘提供500MB/s的读取速度, 50分钟读取到内存。使用SSD云盘,可在25分钟完成!
腾讯云SSD云盘,基于全SSD存储介质、CBS分布式架构,实现了超强性能与超高可靠性的集合。
SSD云盘适合对I/O性能要求高、同时对数据可靠性要求也高的场景。
尤其适合如PostgreSQL、MySQL、Oracle、SQL Server等中大型关系数据库应用、对数据可靠性要求高的I/O密集型等核心业务系统以及对数据可靠性要求高的中大型开发测试环境。
在联机事务处理上,我们进行了mysql压力测试,在4台Core 8GB RAM虚拟机上挂载800G的SSD云盘,进行Mysql version 5.5.42部署。
测试结果显示:用sysbench模拟OLTP性能测试,测试集为1千万条记录,TPS可达1616、QPS达29000,单盘足以支撑每秒上万人的在线同时交易!
腾讯云团队在QCon
火爆的咨询现场
QCon是由InfoQ主办的全球顶级技术盛会,自2007年3月份首次举办以来,已经有超万名高级技术人员参加过QCon大会,面向5年以上的技术团队负责人、架构师、工程总监、高级开发人员分享技术创新和最佳实践。
联系客服