javazx 发表于 2017-3-4 13:56:45

《大规模分布式存储系统》第6章 分布式表格系统【6.3】

6.3 Windows Azure Storage
Windows Azure Storage(WAS)是微软开发的云存储系统,包括三种数据存储服
务:Windows Azure Blob、Windows Azure Table、Windows Azure Queue。三种数据存
储服务共享一套底层架构,在微软内部广泛用于社会化网络、视频、游戏、Bing搜
索等业务。另外,在微软外部也有成千上万个云存储客户。
6.3.1 整体架构
WAS部署在不同地域的多个数据中心,依赖底层的Windows Azure结构控制器
(Fabric Controller)管理硬件资源。结构控制器的功能包括节点管理,网络配置,
健康检查,服务启动,关闭,部署和升级。另外,WAS还通过请求结构控制器获取
网络拓扑信息,集群物理部署以及存储节点硬件配置信息。
如图6-10所示,WAS主要分为两个部分:定位服务(Location Service,LS)和存
储区(Storage Stamp)。
图 6-10 Azure storage整体架构
●定位服务的功能包括:管理所有的存储区,管理用户到存储区之间的映射关
系,收集存储区的负载信息,分配新用户到负载较轻的存储区。LS服务自身也分布
在两个不同的地域以实现高可用。LS需要通过DNS服务来使得每个账户的请求定位
到所属存储区。
●每个存储区是一个集群,一般由10~20个机架组成,每个机架有18个存储节
点,提供大约2PB存储容量。下一步的计划是扩大存储区规模,使得每个存储区能够
容纳30PB原始数据。存储区分为三层:文件流层(Stream Layer)、分区层
(Partition Layer)以及前端层(Front-End Layer)。
●文件流层:与Google GFS类似,提供分布式文件存储。WAS中文件称为流
(streams),文件中的Chunk称为范围(extent)。文件流层一般不直接对外服务,需
要通过服务分区层访问。
●分区层:与Google Bigtable类似,将对象划分到不同的分区以被不同的分区服
务器(Partition Server)服务,分区服务器将对象持久化到文件流层。
●前端层:前端层包括一系列无状态的Web服务器,这些Web服务器完成权限验
证等功能并根据请求的分区名(Partition Name)将请求转发到不同的分区服务器。
分区映射表(Partition Map)用来决定应该将请求转化到哪个分区服务器,前端服务
器一般缓存了此表从而减少一次网络请求。
另外,WAS包含两种复制方式:
●存储区内复制(Intra-Stamp Replication):文件流层实现,同一个extent的多个
副本之间的复制模式为强同步,每个成功的写操作必须保证所有副本都同步成功,
用来实现强一致性。
●跨存储区复制(Inter-Stamp Replication):服务分区层实现,通过后台线程异
步复制到不同的存储区,用来实现异地容灾。
6.3.2 文件流层
文件流层提供内部接口供服务分区层使用。它提供类似文件系统的命名空间和
API,但所有的写操作只能是追加,支持的接口包括:打开&关闭文件、改名、读取
以及追加到文件。文件流层中的文件称为流,每个流包含一系列的extent。每个extent
由一连串的block组成。
如图6-11所示,文件流"//foo"包含四个extent(E1、E2、E3、E4)。每个extent包
含一连串追加到它的block。其中,E1、E2和E3是已经加封的(sealed),这就意味
着不允许再对它们追加数据;E4是未加封的(unsealed),允许对它执行追加操作。
图 6-11 某文件流示例
block是数据读写的最小单位,每个block最大不超过4MB。文件流层对每个block
计算检验和(checksum)。读取操作总是给定某个block的边界,然后一次性连续读
取一个或者多个完整的block数据;写入操作凑成一个或者多个block写入到系统。
WAS中的block与GFS中的记录(record)概念是一致的。
extent是文件流层数据复制,负载均衡的基本单位,每个存储区默认对每个extent
保留三个副本,每个extent的默认大小为1GB。如果存储小对象,多个小对象可能共
享同一个extent;如果存储大对象,比如几GB甚至TB,对象被切分为多个extent。
WAS中的extent与GFS中的chunk概念是一致的。
stream用于文件流层对外接口,每个stream在层级命名空间中有一个名字。WAS
中的stream与GFS中的file概念是一致的。
1.架构
如图6-12所示,文件流层由三个部分组成:
图 6-12 Azure文件流层的架构
●流管理器(Stream Manager,SM)
流管理器维护了文件流层的元数据,包括文件流的命名空间,文件流到extent之
间的映射关系,extent所在的存储节点信息。另外,它还需要监控extent存储节点,负
责整个系统的全局控制,如extent复制,负载均衡,垃圾回收无用的extent,等等。流
管理器会定期通过心跳的方式轮询extent存储节点。流管理器自身通过Paxos协议实现
高可用性。
●extent存储节点(Extent Node,EN)
extent存储节点实际存储每个extent的副本数据。每个extent单独存储成一个磁盘
文件,这个文件中包含extent中所有block的数据及checksum,以及针对每个block的索
引信息。extent存储节点之间互相通信拷贝客户端追加的数据,另外,extent存储节点
还需要接受流管理器的命令,如创建extent副本,垃圾回收指定extent,等等。
●客户端库(Partition Layer Client)
客户端库是文件流层提供给上层应用(即分区层)的访问接口,它是一组专用
接口,不遵守POSIX规范,以库文件的形式提供。分区层访问文件流层时,首先访问
流管理器节点,获取与之进行交互的extent存储节点信息,然后直接访问这些存储节
点,完成数据存取工作。
2.复制及一致性
WAS中的流文件只允许追加,不允许更改。追加操作是原子的,数据追加以数
据块(block)为单位,多个数据块可以由客户端凑成一个缓冲区一次性提交到文件
流层的服务端,保证原子性。与GFS一样,客户端追加数据块可能失败需要重试,从
而产生重复记录,分区层需要处理这种情况。
分区层通过两种方式处理重复记录:对于元数据(metadata)和操作日志流
(commit log streams),所有的数据都有一个唯一的事务编号(transaction
sequence),顺序读取时忽略编号相同的事务;对于每个表格中的行数据流(row
data streams),只有最后一个追加成功的数据块才会被索引,因此先前追加失败的
数据块不会被分区层读取到,将来也会被系统的垃圾回收机制删除。
如图6-12,WAS追加流程如下:
1)如果分区层客户端没有缓存当前extent信息,例如追加到新的流文件或者上一
个extent已经缝合(sealed),客户端请求SM创建一个新的extent;
2)SM根据一定的策略,如存储节点负载,机架位置等,分配一定数量(默认
值为3)的extent副本到EN。其中一个extent副本为主副本,允许客户端写操作,其他
副本为备副本,只允许接收主副本同步的数据。Extent写入过程中主副本维持不变,
因此,WAS不需要类似GFS中的租约机制,大大简化了追加流程;
3)客户端写请求发送到主副本。主副本将执行如下操作:a)决定追加的数据
块在extent中的位置;b)定序:如果有多个客户端往同一个extent并发追加,主副本
需要确定这些追加操作的顺序;c)将数据块写入主副本自身;
4)主副本把待追加数据发给某个备副本,备副本接着转发给其他备副本。每一
个备副本会根据主副本确定的顺序执行写操作;
5)备副本副本写成功后应答主副本;
6)如果所有的副本都应答成功,主副本应答客户端追加操作成功;
追加过程中如果某个副本出现故障,客户端追加请求返回失败,接着客户端将
联系SM。SM首先会缝合失败的extent,接着创建一个新的extent用来提供追加操作。
SM处理副本故障的平均时间在20ms左右,新的extent创建完成后客户端追加操作可以
继续,整体影响不大。
每个extent副本都维护了已经成功提交的数据长度(commit length),如果出现异
常,各个副本当前的长度可能不一致。SM缝合extent时首先请求所有的副本获取当前
长度,如果副本之间不一致,SM将选择最小的长度值作为缝合后的长度。如果缝合
操作的过程中某个副本所在的节点出现故障,缝合操作仍然能够成功执行,等到节
点重启后,SM将强制该节点从extent的其他副本同步数据。
文件流层保证如下两点:
●只要记录被追加并成功响应客户端,从任何一个副本都能够读到相同的数据;
●即使追加过程出现故障,一旦extent被缝合,从任何一个被缝合的副本都能够
读到相同的内容。
3.存储优化
extent存储节点面临两个问题:如何保证磁盘调度公平性以及避免磁盘随机写操
作。
很多硬盘通过牺牲公平性来最大限度地提高吞吐量,这些磁盘优先执行大块顺
序读写操作。而文件流层中既有大块顺序读写操作,也有大量的随机读取操作。随
机读写操作可能被大块顺序读写操作阻塞,在某些磁盘上甚至观察到随机IO被阻塞
高达2300ms的情况。为此,WAS改进了IO调度策略,如果存储节点上某个磁盘当前
已发出请求的期望完成时间超过100ms或者最近一段时间内某个请求的响应时间超过
200ms,避免将新的IO请求调度到该磁盘。这种策略适当牺牲了磁盘的吞吐量,但是
保证公平性。
文件流层客户端追加操作应答成功要求所有的副本都将数据持久化到磁盘。这
种策略提高了系统的可靠性,但增加了写操作延时。每个存储节点上有很多extent,
这些extent被大量分区层上的客户端并发追加,如果每次追加都需要将extent文件刷到
磁盘中,将导致大量的随机写。为了减少随机写,存储节点采用单独的日志盘
(journal drive)顺序保存节点上所有extent的追加数据,追加操作分为两步:a)将
待追加数据写入日志盘;b)将数据写入对应的extent文件。操作a)将随机写变为针
对日志盘的顺序写,一般来说,操作a)先成功,操作b)只是将数据保存到系统内
存中。如果节点发生故障,需要通过日志盘中的数据恢复extent文件。通过这种策
略,可以将针对同一个extent文件的连续多个写操作合并成一个针对磁盘的写操作,
提高了系统的吞吐量,同时降低了延时。
文件流层还有一种抹除码(erasure coding)机制用于减少extent副本占用的空
间,GFS以及开源的HDFS也采用了这个机制。每个数据中心的extent副本默认都需要
存储三份,为了降低存储成本,文件流层会对已经缝合的extent进行Reed-Solomon编
码 。具体来讲,文件流层在后台定期执行任务,将extent划分为N个长度大致相同
的数据段,并通过Reed-Solomon算法计算出M个纠错码段用于纠错。只要出现问题的
数据段或纠错码段总和小于或者等于M个,文件流层都能重建整个extent。推荐的配
置是N=10,M=4,也就是只需要1.4倍的存储空间,就能够容忍多达4个存储节点出
现故障。
一种纠错码,在分布式文件系统或者RAID技术中用于容忍多个副本或者磁盘同时
离线的情况。
6.3.3 分区层
分区层构建在文件流层之上,用于提供Table、Blob、Queue等数据服务。分区层
的一个重要特性是提供强一致性并保证事务操作顺序。
分区层内部支持一种称为对象表(Object Table,OT)的数据架构,每个OT是一
张最大可达若干PB的大表。对象表被动态地划分为连续的范围分区
(RangePartition,对应Bigtable中的子表),并分散到WAS存储区的多个分区服务器
(Partition Server)上。范围分区之间互相不重叠,每一行都确保只在一个范围分区
上。
WAS存储区包含的对象表包括账户表,Blob数据表,Entity数据表,Message数据
表。其中,账户表存储每个用户账户的元数据及配置信息;Blob、Entity、Message数
据表分别对应WAS中的Blob、Table、Message服务。
另外,分层区中还有一张全局的Schema表格(Schema Table),保证所有的对象
表格的schema信息,即每个对象表包含的每个列的名字,数据类型及其他属性。对
象表划分为很多行,每个行通过一个主键(Primary Key)来定位,每个对象表的行
主键包括用户账户名,分区名以及对象名三个部分。系统内部还维护了一张分区映
射表(Partition Map),用于记录每个范围分区当前所在的分区服务器。
WAS支持的数据类型包括bool、binary string、DateTime、double、GUID、int32、
int64、DictionaryType以及BlobType。DictionaryType允许每个行的某一列的值为一系
列<name,type,value>的元组。BlobType被Blob表格使用,用于表示图片、图像等
Blob数据。
1.架构
如图6-13所示,分区层包含如下四个部分:
图 6-13 Azure分区层架构
●客户端程序库(Client)
提供分区层到WAS前端的接口,前端通过客户端以对不同对象表的数据单元进
行增、删、查、改等操作。客户端通过分区映射表(Partition Map)获取分区映射信
息,但所有表格的数据内容都在客户端与分区服务器之间直接传送;
●分区服务器(Partition Server,PS)
PS实现分区的装载/卸出、分区内容的读和写,分区的合并和分裂。一般来说,
每个PS平均服务10个分区。
●分区管理器(Partition Manager,PM)
管理所有的PS,包括分配分区给PS,指导PS实现分区的分裂及合并,监控PS,
在PS之间进行负载均衡并实现PS的故障恢复等。每个WAS存储区有多个PM,他们之
间通过Lock Service进行选主,持有租约的PM是主PM。
●锁服务(Lock Service)
Paxos锁服务用于WAS存储区内选举主PM。另外,每个PS与锁服务之间都维持
了租约。锁服务监控租约状态,PS的租约快到期时,会向锁服务重新续约。如果PS
出现故障,PM需要首先等待PS上的租约过期才可以将它原来服务的分区分配出去,
PS租约如果过期也需要主动停止读写服务。否则,可能出现多个PS同时读写同一个
分区的情况。
2.分区数据结构
WAS分区层中的操作与Bigtable基本类似。如图6-14,用户写操作首先追加到操
作日志文件流(Commit Log Stream),接着修改内存表(Memory Table),等到内存
表到达一定大小后,需要执行快照(Checkpoint,对应Bigtable中的Minor
Compaction)操作。分区服务器会定期将多个小快照文件合并成更大的快照文件(对
应Bigtable中的Merge/Major Compaction)以减少读操作需要访问的文件数。分区服务
器会对每个快照文件维护热点行数据的缓存(Row Page Cache,对应Bigtable中的
Block Cache和Key Value Cache),另外,通过布隆过滤器过滤对快照文件不存在行的
随机读请求。
图 6-14 分区数据结构
与Bigtable的不同点如下:a)WAS中每个分区拥有一个专门的操作日志文件,
而Bigtable中同一个Tablet Server的所有子表共享同一个操作日志文件;b)WAS中每
个分区维护各自的元数据(例如分区包含哪些快照文件,持久化成元数据文件
流),分区管理器只管理每个分区与所在的分区服务器之间的映射关系;而Bigtable
专门维护了两级元数据表:元数据表(Meta Table)及根表(Root Table),每个分区
的元数据保存在上一级元数据表中;c)WAS专门引入了Blob数据文件流用于支持
Blob数据类型。
由于Blob数据一般比较大,如果行数据流中包含Blob数据,只记录每个Blob数
据块在操作日志文件流(Commit Log Stream)中的索引信息,即所在的操作日志文
件名及文件内的偏移。执行快照操作时,需要回收操作日志。如果操作日志的某些
extent包含Blob数据,需要将这些extent连接到Blob数据流的末尾。这个操作只是简单
地往Blob数据流文件追加extent指针,文件流层对此专门提供了快速操作接口。
3.负载均衡
PM记录每个PS及它服务的每个分区的负载。影响负载的因素包括:1)每秒事
务数;2)平均等待事务个数;3)节流率;4)CPU使用率;5)网络使用率;6)请
求延时;7)每个分区的数据大小。PM与PS之间维持了心跳,PS定期将负载信息通
过心跳包回复PM。如果PM检测到某个分区的负载过高,发送指令给PS执行分裂操
作;如果PS负载过高,而它服务的分区集合中没有过载的分区,PM从中选择一个或
者多个分区迁移到其他负载较轻的PS。
对某个分区负载均衡两个阶段:
●卸载:PM首先发送一个卸载指令给PS,PS会执行一次快照操作。一旦完成后,
PS停止待迁移分区的读写服务并告知PM卸载成功。如果卸载过程中PS出现异常,
PM需要查询锁服务,直到PS的服务租约过期才可以执行下一步操作。
●加载:PM发送加载指令给新的PS并且更新PM维护的分区映射表结构,将分区
指向新的PS。新的PS加载分区并且开始提供服务。由于卸载时执行了一次快照操
作,加载时需要回放的操作日志很少,保证了加载的快速。
4.分裂与合并
有两种可能导致WAS对某个分区执行分裂操作,一种可能是分区太大,另外一
种可能是分区的负载过高。PM发起分裂操作,并由PS确定分裂点。如果是基于分区
大小的分裂操作,PS维护了每个分区的大小以及大致的中间位置,并将这个中间位
置作为分裂点;如果是基于负载的分裂操作,PS自适应地计算分区中哪个主键范围
的负载最高并通过它来确定分裂点。
假设需要把分区B分裂为两个新的分区C和D,操作步骤如下:
1)PM告知PS将分区B分裂为C和D。
2)PS对B执行快照操作,接着停止分区B的读写服务;
3)PS发起一个"MultiModify" 操作将分区B的元数据,操作日志及行数据流复
制到C和D。这一步只需要拷贝每个文件的extent指针列表,不需要拷贝extent的内
容。接着PS分别往C和D的元数据流写入新的分区范围。
4)PS开始对C和D这两个分区提供读写服务。
5)PS通知PM分裂成功,PM相应地更新分区映射表及元数据信息。接着PM会把
C或者D中的其中一个分区迁移到另外一个不同的PS。
合并操作需要选择两个连续的负载较低的分区。假设需要把分区C和D合并成为
新的分区E。操作步骤如下:
1)PM迁移C或者D,使得这两个分区被同一个PS服务。接着PM通知PS将分区C
和D合并成为E。
2)PS分别对分区C和D执行快照操作,接着停止分区C和D的读写服务;
3)PS发起一个"MultiModify"操作合并分区C和D的操作日志及行数据流,生成E
的操作日志和行数据流。假设分区C的操作日志文件包含<C1,C2>两个extent,分
区D的操作日志文件包含<D1,D2,D3>三个extent,则分区E的操作日志文件包含
<C1,C2,D1,D2,D3>这五个extent。行数据流及Blob数据流也是类似的。与分
裂操作类似,这里只需要修改文件的extent指针列表,不需要拷贝extent的实际内容。
4)PS对E构造新的元数据流,包含新的操作日志文件,行数据文件,C和D合并
后的新的分区范围以及操作日志回放点和行数据文件索引信息。
5)PS加载新分区E并提供读写服务。
6)PS通知PM合并成功,接着PM相应地更新分区映射表及元数据信息。
MultiModify指在一次调用中实现多步修改操作。
6.3.4 讨论
WAS整体架构借鉴GFS+Bigtable并有所创新。主要的不同点包括:
1)Chunk大小选择。GFS中每个Chunk大小为64MB,随着服务器性能的提升,
WAS每个extent大小提高到1GB从而减少元数据。
2)元数据层次。Bigtable中元数据包括根表和元数据表两级,而WAS中只有一
级元数据,实现更加简便。
3)GFS的多个Chunk副本之间是弱一致的,不保证每个Chunk的不同副本之间每
个字节都完全相同,而WAS能够保证这一点。
4)Bigtable每个Tablet Server的所有子表共享一个操作日志文件从而提高写入性
能,而WAS将每个范围分区的操作写入到不同的操作日志文件。


页: [1]
查看完整版本: 《大规模分布式存储系统》第6章 分布式表格系统【6.3】