秒启万台主机,腾讯云云硬盘数据调度架构演进

2020-10-19 16:26:45 浏览数 (1)

​导语 | CBS云硬盘为腾讯云客户提供了⾼可靠、⾼可⽤和低成本的统⼀块存储服务。CBS针对数据安全、云服务器⽣产、资源均衡、云盘介质升级等场景下的数据调度能⼒需求,抽象出统⼀数据调度平台。本文是对腾讯云存储专家工程师——杨光超在腾讯云开发者社区online的分享整理,希望与大家一同交流。

点击查看完整直播回放

一、CBS数据调度系统的演进历程 

CBS存储系统,主要为腾讯云的CVM提供高性能、高可靠、低成本的块存储服务。

CBS数据调度系统,是基于存储系统构建的统一的数据调度服务。为什么要构建统一的数据调度呢?

在2015年时它仅仅作为快照系统存在,仅是保存在云上的数据,目的是为了提高整个数据的安全性。用户会对数据进行备份,如果这个时候数据丢失,可以利用快照对其恢复。

上云业务尚未规模化,快照系统的业务量不大,而且快照备份本身是离线业务,所以针对IO时延时延方面并不敏感。

但随着业务上云越来越多,云盘的规模也越来越大。利用回滚的能力,来做镜像生产云服务器,数据调度系统拓展了新的应用场景,同时,系统回滚能力也要求越来越高,时延方面也逐渐敏感。

随着CBS业务不断快速增长和架构不断演进,催生出另一个全新数据调度场景——云盘的在线迁移。

云盘在线迁移是什么意思?某些场景下需要将云盘从一个存储仓库迁移到另外一个存储仓库,而且是在线迁移,对用户的业务是无损的。

它有一个特点是对时延的抖动敏感,用户的业务已经运行了,对整个时延抖动的要求是极低的。

我们把前文所述的数据能力抽象出一个统一数据调度平台,负责我们离线的数据和在线的数据打通。它当前涵盖主要三个场景:数据保护、云服务器批量生产和云盘在线迁移。下文将围绕这三个场景一一展开。

首先介绍整个数据调度系统的三层架构,第一层是业务中控层,中控是高可用服务,负责接受前端的业务请求,不管是打快照还是做回滚,以及云盘迁移,都会到我们的中控层,再转发任务给数据调度层。

数据调度层是集群模式,会把调度任务按照逻辑地址划为大小相同的数据块,并把块信息给到传输层,那么传输层看到的就是一个个的数据块,数据调度层会告诉传输层节点这个数据块源端在哪里,目的在哪里,再由传输层节点完成了数据的搬迁功能。

数据调度系统,为CBS构筑离线存储系统和在线存储系统、在线存储系统之间数据流动能力。

二、典型业务场景以及面临的挑战

下文将为大家介绍CBS的三个典型业务场景,以及面临的挑战有哪些?

1. 数据保护

(1)数据保护

用在我们的日常备份,也就是重要的业务数据要做备份,万一哪天有损坏,我们恢复到前一天或者前一段时间点的数据。这是我们常用的日常备份。目前产品能力有手动快照和定期自动快照两种。

(2)业务恢复

业务恢复指的是,假如你业务受损了,也可以快速的恢复。还有一种场景就是系统重装来恢复环境,假如说你的系统做了测试,想恢复到原来的现场,我们可以通过系统重装来完成。

2. 镜像生产云服务器

(1)镜像制作

通过云盘制作镜像,就是一次快照的创建。

(2)镜像生产云服务器

镜像制作完成之后,我们用镜像去批量部署应用,这样就能够达到快速的部署业务的目的。

(3)镜像异地复制

假如我们的业务需要容灾,或者说同一镜像需要多地域的部署业务,就可以通过把镜像从一个地域复制到另外一个地域完成,就是镜像的跨地域复制能力。

3. 云盘迁移

(1)资源均衡

为了提升用户的体验,需要仓库间资源均衡调度。

(2)架构升级

CBS新架构,无论是产品性能还是用户体验方面,都有很大的提升,需要对云盘做架构升级,需要把云盘从老系统迁到新的系统里。

(3)硬件批次故障

如果出现了批次的硬件故障,需要把仓库里的所有的云盘迁出到正常的仓库里面,这依赖云盘迁移能力。

4. 面临的挑战 

(1)数据保护

  • 无感备份:数据备份要做到无感备份。
  • 数据可靠:备份的数据要可靠存储,不能说备份出去了,当需要恢复的时候发现数据错误。

(2)镜像生产云服务器

  • 秒级开机:在镜像生产云服务器的场景下,为了提升用户体验,需要镜像生产开机之后能够立马启动,而不是要等镜像数据全部下载完成。
  • 高并发能力:我们通过镜像批量发放云服务器的时候,支持用户上万的并发能力。

(3)云盘迁移

  • 业务无感知:不能给用户业务造成可感知的时延抖动。
  • 故障自愈能力:假如迁移的过程中系统出现故障,或者说软件层出现Bug,或者云盘迁移受阻的时候,需要很强的自愈能力,故障对业务无感知。

三、CBS数据调度系统关键技术

1. COW与ROW

对于数据保护技术,传统行业常用的就是快照。提到快照,不得不说常用的两种快照技术:

(1)COW技术

写时复制,就是当创建完快照,再去写这个同一个地址块的时候,需要把原来的地址块中数据先拷贝到新分配的地址块空间中,再更新源地址块中数据。

(2)ROW技术

写访问时,需要重新定向到另外一个地址块空间上去。

对于COW和ROW的实现机制,首先是写时复制。如上图所示,在T1时刻对源卷打下快照,上面蓝色部分是源卷的地址块指针,中间的橙色是磁盘上真正的物理空间——数据块,这个时候源卷和快照的卷,地址块指针都指向相同实际的物理空间。

以访问block4为例,当打完快照想更新block4的数据的时候,写时复制的做法就是先重分配一个新block5,把block4的数据先拷贝到block5里面去,然后再把快照的数据块逻辑地址指针指向第5个数据块,用户io再更新block4数据块。

经过这次写过程之后,我们可以看到源卷的还是指原来的这四个物理block地址,快照这边其实有一个指针映射的过程,从原来的block4转变到block5。

写时复制有一个性能问题,就是把block4的数据读出来,写到block5里面去,然后再同时有一次元数据更改,最后是用户写入到block4上面去,就是一个用户写会放大到“一次读、三次写”的过程。

COW技术存在严重的写放大问题,影响写的性能,它适用的场景是读密集型。ROW跟COW不一样的地方,在于如果用户打完快照再写block4空间,会新分配一个block5,用户数据再写入block5,修改源卷逻辑地址指针映射。ROW除用户写外,只增加一次元数据写操作。这主要是影响读性能,适用于写密集型场景。

ROW和COW它们各有各的应用场景。在分布式存储领域,卷的数据是打散在一个存储集群的很多块硬盘或者ssd上;由于数据打散,读的性能比单物理盘好很多。另外,存储系统多会采用cache技术优化读性能,所以现在分布式存储系统快照多采用ROW模式来实现。

2. 多版本ROW机制

数据调度系统,采用多版本ROW机制实现快照技术。什么是多版本呢?其实就是用版本号去区分快照点数据,创建一次快照,整个卷的版本号会加一。

举个简单例子,一个卷假如有四个数据块,刚开始创卷并写入数据的时候,T0时刻打一次快照,这个时候我们要把备份的数据备份到离线存储器里,很明显我们要把A、B、D三个块搬迁到离线存储系统里去。

假如说这个时候用户再来写A块,因为卷的版本是2,会为A块再重新分配新的数据块A',A'块的版本号记录为2。写C块,因为是第一次写,之前没有分配物理块,那么这次就分配一个物理块C版本号记录为2。到T2时候再打快照能很明确知道,T0时刻到T2时刻新修改的数据块,也就是要把A'和C块搬到离线存储系统里。

3. 快照概述

CBS快照,是快照创建时候的数据的完整备份,采用全量加增量结合的方式备份数据。

全量是T0时刻之前没有打快照的,这个时候的数据全部备份到离线系统。那么在T2时刻创建快照只备份从T0时刻到T2时刻的中间修改的那一部分增量数据,这是全量加增量的备份机制。

创建快照,对用户而言要达到秒级完成。当调度系统收到快照请求,首先到中控层,通知CBS存储系统卷版本号加一,存储系统收到请求后,将更新后的卷版本号同步给CBS客户端。

从CBS客户端新写入的数据携带新版本号写入到存储侧,存储侧就为写请求分配新版本物理block,达到通过block版本区分快照数据还是卷数据。

存储系统响应了之后,就告诉用户创建快照成功了。这个时候快照数据还在我们的CBS存储系统里,快照数据异步搬迁到离线存储系统中。

数据调度层按照卷逻辑地址大小,切分成数据块大小,再告诉数据传输层,一个一个块从存储系统读出来,上传到我们的离线存储系统,这样就完成了数据的备份。之所以要异构存储快照数据,主要是基于快照数据可靠性来考量的

4. 回滚流程

假如创建快照后,用户的云盘数据出现了损坏,用户想回退到某个指定快照点。因为是全量加增量,那怎么知道指定快照点有哪些数据是当前有效的?换句话说,备份完了后怎么知道这个快照点有哪些是新增数据?哪些是需要依赖于旧快照点的数据?

全量加增量的备份方式,通过快照链来标识,快照链会作为元数据持久化;每个快照点具体备份了卷线性地址空间中的哪些数据块通过bitmap来标识,bitmap中为1的bit位表示该逻辑block有数据备份到离线系统中;数据备份完成后,调度系统会把bitmap元数据一起写入离线存储系统中。

当我们选定一个快照点(比如快照点3)进行回滚的时候,看到当前第一个块A3,对应的bitmap的bit位为0,表示没有数据,那就依次向前看依赖的快照点,发现A2是最新的数据,就可以不往前找了,以A2数据为准。

看第二个数据块,本身就有最新数据,那我就以数据块B3为准。第三个数据块没有,再往前,发现到它的依赖节点也没有的话,再依次往前发现也没有,那就是这个数据块就是没有数据的。

第四个数据块,同样的方式查找依赖的快照点,直到找到D1;最终将A2、B3、D1数据块搬迁到云盘里面去,恢复到了你当时打快照点3时场景。

调度系统通过对指定快照点以及依赖的快照点进行数据合并,然后进行数据回放来回到指定快照点创建时刻的场景,这是一个回滚的流程。

5. 镜像生产云服务器

对于镜像,比如在一台云服务器上,预装一些软件,对云盘进行快照并制作成镜像,这个镜像是预装环境一个模板,通过这个模板能够批量复制相同软件环境的云服务器。

在数据调动系统之前,镜像是宿主机从镜像系统下载后写入CBS云盘,整个镜像下载完成后,云服务器才启动起来。

这种方式有诸多不足之处。首先,如果镜像文件很大的话,下载时间很长,影响开机时间;其次,因为宿主机上面还有其他云服务器,下载镜像占用宿主机带宽,其它云服务器会受影响;再次,我们要维护这样一个镜像系统,需要很大的资源开销。

经过场景分析,可以用数据调度系统的回滚能力支撑镜像批量生产云服务器功能。

首先镜像制作用快照创建能力就能够完成,然后把镜像放到我们的离线系统里面。如果需要批量发放云服务器,再通过调度系统从离线的存储系统,将镜像文件导入到云盘上面就可以访问。

对这两种方式做一个对比,从创建时间和资源的占用,速度的资源占用和成本方面,通过回滚创建云服务器具备如下几大优势:

第一,就是秒级创建,不需要全部下载完成,云服务器就可以开机,下文也会介绍其技术细节。

第二,镜像下载是没有经过宿主机的,这样的话对母机的资源没有额外开销,不会影响宿主机上其他云服务器。

第三,数据调度系统是个现成的系统,没有增加额外资源、成本的问题。

综上所述,通过回滚能力生产云服务器,天然就解决了之前镜像生产子机存在的痛点。

6. 秒级回滚

怎样做到开机后立马能够启动呢?其实开机后能不能启动,取决于云服务器是否正常进行io访问。

调度系统提供了一个秒级回滚的能力,通过回滚能让我们的云服务器很短时间开机启动。

云服务器启动要访问CBS云盘上的镜像数据,但镜像从离线存储系统搬迁到云盘上是逐步完成的,要访问的数据不一定已经搬迁到云盘上。

创建云服务器的时候数据调度系统会启动从离线系统到云盘按卷逻辑地址的线性顺序搬迁,将卷的逻辑分成数据块,一块一块地往CBS云盘上数据搬迁。

比如有一块云盘共有7个block,当已经完成了前两个block的搬迁,但用户想访问的是第5个block,此时CBS客户端会判断当前还没有完成第5个block的搬迁,就主动通知数据调度系统,把第5个搬迁到CBS盘上去;调度系统收到这样的请求,会把第5个block优先搬迁到CBS盘上。

搬迁完了之后,通知客户端,block5已经搬迁完成,客户端就可以把访问block5的io下发给存储侧。

也即是,在正常的用户io路径上,增加了一次数据块从离线存储系统到在线存储系统的搬迁过程,只是会增加极短延时,但不会导致启动慢。

7. 热点数据访问策略

通过前文的介绍我们知道,优先搬迁其实是当用户io访问的数据块还没搬迁到CBS云盘场景下,先将io在客户端挂住,同时优先将该数据库从离线系统到在线系统搬迁,然后将用户io下发的过程。

这里有一个io在客户端挂住的动作,而挂住时间长短取决于优先搬迁的整个时延,我们通过优化优先搬迁时延来减少io抖动。

通过镜像生产子机这个典型的应用场景来说,镜像一般会批量发放云服务器,镜像数据本身就是一个典型的热数据访问问题。

为了起到提高用户体验的作用,也即是为了优化用户io在优先中的时延问题,调度系统将镜像数据作为热点数据缓存在传输层,做了一层镜像数据cache,来缩短访问时延。

第一次去传输层加载数据的时候,cache未命中,就从离线存储系统中加载上来,写到我们的CBS系统,同时数据块缓存到我们的cache里面。

第二次加载就能命中,减少访问离线存储系统的时延。无论优先搬迁还是数据搬迁,这层cache对优化用户时延和减轻底层离线系统的负载是有很大作用的。

8. 系统水平扩展能力

为了支持整个云服务器的并发生产能力,调度系统针对系统水平扩展能力做了一些优化。如上图所示,左边是优化前地域部署的一个中心系统,一个数据调度层,另一个数据传输层。

这里会有两个问题:第一,中控层覆盖整个地域,一旦故障,就会影响整个地域的云服务器的生产。

第二,单个大地域里分很多的可用区,其实跨可用区的访问存在时延,而且还挺大的。基于这种考虑,把大的部署模型拆分成小的部署系统,同时增强系统内部可弹性扩展,系统间提升平行复制的能力。

把大地域部署拆分成小可用区部署数据调度系统,一方面缩小故障率,另一方面缩小了跨可用区访问的一个时延的问题,这对调度系统的弹性能力有很大提升,有利于应对CBS业务的快速增长。

系统支持水平扩展能力之后,怎么保证在一个小系统内负载均衡?

这里总结了几个方面分享给大家。我们是通过静态和动态相结合的方式保证整个系统负载均衡。静态通过心跳上报负载信息,我们在创建的时候通过卷式做快照,都是基于云盘而言的,这样我们根据云盘的ID做一次哈希,保证调度层各个节点上卷规模基本一致。

同时,因为每一个云盘的访问的量包括数据量,负载情况都不一样,调度系统根据负载情况再进行动态均衡,如果调度层单节点之间负载差超过了设定的预值,调度系统就会启动动态的再均衡,将高负载节点上的任务调度到低负载节点上,达到各个调度节点之间的负载尽量保持均衡。

再就是传输层,用了哈希的策略,保证各个传输节点均衡。因为传输节点就是看到数据块的搬迁,它只要保证数据块的搬迁是均匀的,那就可以了。

但其实哈希也有少量的不均衡情况,同一个镜像数据块访问会落到同一个传输结点上,批量发放云服务器时,会出现同一时刻访问同一个数据块造成传输层局部热点问题,调度系统通过冗余几个副本来解决局部热点访问问题。

9. 任务平滑切换

假如说调度节点出现了故障,任务在调度层节点间怎么做平滑切换呢?

首先对于节点故障的探测,这里采用的是心跳探测、业务失败率统计以及外围监控探测相结合完成调度层节点的故障探测。

一旦发现调度层节点故障,上报给中控层,中控节点就启动任务从故障节点切换到另一个正常节点。

如果是备份任务,用户对时延不感知,切换速度要求不高;但回滚时,数据访问的优先搬迁需要调度层节点介入,如果不能及时将任务切换到正常的调度节点上,将会导致io卡住,体验很差。

为了解决这个问题,CBS客户端访问故障节点失败后,轮询下一个调度节点,从下一个调度节点获取当前任务服务的调度节点地址信息,并快速切换,达到快速恢复io的目的。

任务的元数据是共享的,调度节点都可以访问到;目的调度节点会根据唯一的任务key再把原数据加载出来。以上是任务平滑切换的基本机制。

10. 镜像跨地域复制技术

除了镜像生产,还有镜像的跨地域复制。首先,需要两套数据调度系统支持,通过两个地域的调度系统中控层,完成镜像元数据的传输。

A地域调度层和传输层负责从A地域把数据块读出来写到B地域来,完成搬迁后,A地域的中控层通知B地域中控层已经完成了数据的搬迁,B地域中控层通知调度层去完成源和目的数据一致性校验,保证数据可靠传出。

那为什么A地域的系统不能既负责传输又负责校验呢?这相当于一个人既是裁判又是运动员,容易出问题发现不了。基于数据安全考虑,传输和校验分开进行。

11. 云盘无感迁移

云盘迁移,是将云盘从一个存储仓库迁移到另一个存储仓库,业务无感知。迁移最核心的两个点:数据可靠性和业务无感知。

数据可靠性将在下文展开论述,这里重点介绍如何做到业务无感知迁移。

要做到业务无感知,关键在于迁移过程中用户io时延不会有明显增加,为了达到这个目的,数据调度系统引入一个IO接入层,把用户的IO和调度系统底层的顺序搬迁IO隔离开,做到用户IO与顺序搬迁IO隔离,减少IO抖动。

云盘迁移过程中,用户IO如何访问云盘数据呢?

接入层做按搬迁数据块大小将卷划分成block列表,同时维护每一个block状态。block有三个核心状态,状态之间会流转。如果是读请求,就统一读源仓库;如果是写请求,则根据访问block当前状态,按下面规则来处理。

  • 第一个是未搬迁状态,用户IO访问的话,IO写到源仓库。
  • 第二个状态是正在搬迁中,接入层会暂时把IO挂住,等调度层把数据搬迁完,挂住的IO再放下去,写到原仓库和目的仓库。IO挂住的概率极低,运营统计不到十万分之一。
  • 第三个状态是已搬迁,同时写源端和目的端。

为什么访问已搬迁状态的block,IO要同时写源端和目的端呢?这里是为了提升系统可用性,假如说底层出现了任何故障,CBS客户端只需要将IO链路上断开,基于iscsi断链重连会自动切回原仓库中去,因为源仓库数据是完整的,IO的自愈能力就比较高了。

迁移完了之后,把客户端的IO路径切到目的仓库。这个时候的IO路径,也是基于iscsi的I端到T端的断链重连的过程。通过引入接入层,整个IO路径,时延上只是增加了一段网络开销,时延抖动非常低,目前云盘在线迁移,业务感知不到。

云盘迁移里的功能点非常丰富,还有一套辅助的系统——云盘迁移决策系统,它能根据当前仓库的负载情况,各个盘的历史访问情况,做一系列的预测,然后来发掘仓库是否有容量、流量风险,提前决策,选择一批合适的云盘,选择最优的目的仓库,发起迁移,提前解除资源风险,这也是为CBS业务增长在运营上做的一些建设。

12. 数据可靠性

以上三个场景,面临一个共同的挑战就是数据可靠性。

在快照制作镜像场景,从在线存储里面把数据读出来,写入到我们离线存储里面,调度系统的数据块会增加MD5校验头部一起写入离线存储系统中;回滚的时候,调度系统从离线系统读出来再计算一次MD5,检查数据是否有损坏。

元数据除了MD5校验外,还会跨地域备份,增强数据可靠性,同时加强跨地域巡检。 

我们在IO路径上常遇到悬空IO的一些问题,比如说链路切换的时候有一些IO还没落盘,卡到路上,残留的IO会把新写的数据覆盖的问题。

这种问题在云盘迁移过程中表现尤为明显,因为云盘迁移涉及两次io链路切换:从原仓库切到接入层、从接入层切到目的仓库,其实这些链路切换过程都会有IO的残留问题。那么调度系统如何解决这个问题呢?

关键是引入版本号机制,低版本数据不能覆盖高版本数据。每一条链路上版本号不一样,我们在底层存储上做了一些保证,设定了高版本数据可以覆盖低版本数据,但低版本数据不能覆盖高版本数据。

调度系统为每一条链路指定一个新版本,版本号随切换顺序递增,这样低版本数据即使有残留,也不会覆盖新链路上的数据,因为新链路上的数据版本号高。

四、未来演进方向

当前主要是服务于块存储的场景,接下来会在支持块、文件、DB三个场景下数据调度的一些需求上发力,让调度系统能适配更多业务场景。

第二是性能上面,需要支持超低时延云盘的在线迁移。

第三是数据安全,数据安全是我们的核心能力,我们的快照能力现在支持的RPO窗口是比较大的,后续我们还要支持秒级RPO能力,满足客户更细粒度的数据保护需求。

最后就是运营方面的一些建设,也就是前文提到的智能调度,整个云盘的迁移需要智能化,通过AI训练动态实时发现潜在资源风险,这样就能够做到整个存储层池化资源的均衡。

六、Q&A

Q:首次全量打快照时,空块也要搬迁么?

A:空块在打快照的时候是不需要搬迁的。

Q:现在还是按地域部署?

A:我们的部署模型,这块是不断优化演进的过程,之前是按大地域来部署,运营出现过一些问题,现在按小地域部署。后续会更加强化小地域和一个逻辑管理单元,一个逻辑调度的能力的复制。当超过最大能力时候,我们再去扩展调度能力。

Q:迁移的速度是如何保证的?

A:速度这块是个动态控制的过程,最早是静态,现在慢慢演变成动态,因为存储仓库负载是一个动态的过程,动态探测当前的空余带宽,去充分利用仓库空余带宽,提升数据搬迁的速度。

Q:大数据写入的时候云盘的在线迁移有限制吗?

A:这块是有限制的。当前有带宽瓶颈,因为接入层双写源和目的;但我们现在正在开发一个新能力,就把云盘上的带宽打散到接入集群上去,突破单点的瓶颈,支持更高带宽云盘迁移。

Q:云硬盘如何选型?

A:我们提供了多种的云硬盘的选型,这块可以参照我们的在线产品介绍,根据不同的产品能力规格,来选择你的云盘。

Q:系统可不可以跟ZK交互?

A:ZK系统就是提供中控层选主服务,并不参与到调动的过程。

Q:如果写入太快,打快照速度可能追不上写入速度吗?

A:这块是两个概念,一旦创建完快照,快照数据是静态的数据,用户先写的数据,是新的数据块,二者没什么关系,调度系统完成快照数据顺序搬迁,不影响用户写入。

Q:快照删除后,老的版本数据如何回收?

A:备份完数据后,有一个数据的回收过程。因为已经完成备份的数据保留在在线系统里面,在线存储系统的block使用率,随着打快照会慢慢的增长,存在资源风险。这些旧版本的也就是快照版本的数据会回收掉。如果高版本的数据对低版本数据有依赖,比如说新版本的数据块只写了前4KB,低版本的数据写了尾巴4KB,这个时候旧版本的数据回收的时候,是要把旧版本尾巴上的这4K合并到新版本里去,才能把旧的版本数据块回收掉,这是回收的基本原理。

Q:数据块 划分大小 是多大?

A:此处讲到数据块的大小,只是说了设计的原理,没有具体说数据块大小,这个数据块大小可能根据我们是按1MB来切分的,关于数据块大小划分各个厂商可能不一样。

Q:如果快照取消了会有残留数据么在COS里?

A:如果你正在打快照过程中,然后你取消了,我们会把前面的在离线系统里删除掉,所以它不会残留的。

Q:跨区域的镜像搬迁,对网络有额外要求么?

A:网络其实我们目前是没有什么要求,在访问网络带宽的时候会做留空,会做资源限制,因为我们的数据启动系统和离线,都是在公司内网。

Q:我们现在整个数据调度系统是不是没有主备的概念?

A:我们在中控节点是有主备的概念。然后我们的调度集群和传输集群都是无状态的,也就是没有主备的概念。

0 人点赞