Windows Azure Storage设计原理,微软azure存储架构Windows Azure Storage设计原理Windows Azure Storage(WAS)是微软提供的云存储服务。WAS设计的主要目标强一致性,号称CAP都能满足提供全球统一的存储服务提供完善的异地容灾支持WAS的名字空间WAS提供三......
Windows Azure Storage(WAS)是微软提供的云存储服务。
WAS设计的主要目标
强一致性,号称CAP都能满足
提供全球统一的存储服务
提供完善的异地容灾支持
WAS的名字空间
WAS提供三种存储抽象,分别是表格(Table)、消息队列(Queue)、文件(Blob),WAS存储的每个对象(表格里的一行、队列里的一条消息、一个文件)都对应一个全局唯一的资源URI,其中AccountName为用户账户,service为存储服务类型(table、queue、blob中的一种)。
http(s)://https://AccountName.1.core.windows.net/PartitionName/ObjectName
对于Table,PartitionName为表名,ObjectName为表内行的primary key
对于Queue,PartitioinName为队列名字,ObjectName为队列里消息的id
对于Blob,ObjectName为文件名,PartitionName与ObjectName相同
WAS总体架构
WAS借助DNS服务来实现全局存储服务,Location Service负责管理用户的账户信息,当用户注册了一个WAS账户后,Location Service会为用户分配一或多个stamp来提供存储服务,同时更新DNS里的记录,将https://AccountName.1.core.windows.net解析到stamp对应的访问入口。
WAS里stamp类似于集群的概念,请看下图,MS在全球有多个机房,每个机房会部署多个WAS存储集群(stamp),stamp内部通过副本机制来保证数据安全性,stamp间会有数据备份机制,用于异地容灾,比如stamp001在美国、欧洲、亚洲的机房各有一份数据,任意一个机房故障,都能从其他机房的对等stamp里读到用户数据。
一个stamp典型的规模,1020个机架,每个机架18个存储节点,约提供2PB的存储空间;下一代WAS,每个stamp将提供30PB的存储空间(猜想主要是单块盘存储空间增加)。
Stamp内部架构
单个stamp内部,主要分为三个层次
Stream Layer:提供可靠的文件存储(类比GFS)
Partion Layer:提供Table、Queue、Blob存储的逻辑抽象,实际数据存储依赖Stream Layer(类比bigtable)
Front End:存储资源访问代理,接受用户的请求,通过Partition Layer获取到数据,返回给用户
Stream Layer设计
Stream Layer可以理解为提供可靠存储的分布式文件系统,提供层次性的命名空间,如下图,Stream Layer存储的Foo文件。
Foo文件由多个extent组成(类似GFS里的block的概念,但非定长,每个extent存储时对应一个NTFS文件),extent由多个block组成。extent创建时,会对应多个副本,客户端可以不断以block为单位(1或多个block)向extent追加数据,每个block会计算一份校验信息用于检查数据完整性,每次从extent读取数据时,都需要读取整个block的数据来校验数据完整性;每个extent还对应一个index文件,用于映射[extent,offset]到block。(partition layer来说,它会维护每个对象存储在stream layer的[文件,extent,offset]作为对象的位置索引信息。)
Stream Layer主要包含Stream Manager(SM,相当于元数据服务器)和Extent Node(EN,相当于存储节点)。
SM的主要职责:
维护名字空间以及所有文件及extent的状态
管理所有EN的运行状态
为EN创建和分配extent
当有EN宕机时,复制缺少副本的extent
对只读的extent进行earsure code编码
extent一旦创建,便不可更改,只能追加数据,当extent到达一定长度时,客户端(Partition Layer)可以将extent封装(seal)起来,封装后的extent不能再被更新,如果文件要继续追加数据,客户端可以向SM请求创建新的extent,然后往新的extent里追加数据,在SM看来,文件就是由多个extent顺序连接而成。
extent的多个副本中,有一个是master,其它的副本是slave,每次针对extent的追加操作,客户端都会将请求发快递至master,由master完成整个追加过程,master负责对所有的追加操作进行排序,然后决定追加操作在extent上的偏移(offset信息),同时请求多个slave在同样的offset上往extent追加数据,当所有副本都追加成功时,才认为追加操作成功。
如果在追加的过程种出现错误(只有部分副本追加成功),Stream Layer与客户端(Partition Layer)的约定是,客户端进行重试或是封装当前extent(以多个副本中extent的commit length最小的为准,commit length表示当前extent追加了多少数据),创建新的extent来追加数据。这个约定也意味着,同一个条记录可能在extent上追加多次,这就要求上层业务能够处理这种重复的记录。
Stream Layer的一些优化:
对封装后的extent(只读)进行earsure code编码,用于节省存储空间。
接收到读请求时,如果当前EN有很多请求在排队,或是有请求排队超过一定时间,则直接拒绝服务,让客户端重试其它副本
每个EN使用一块单独的盘(通常是ssd)做日志盘(cache),当EN执行追加操作时,会将请求的数据先追加到日志盘,同时写到EN上的数据盘(不刷盘,等待OS后台刷盘)。
Partition Layer设计
Partition Layer在Stream Layter的基础上抽象出Table、Queue存储逻辑,主要由Partition Manager(PM)和Partition Server(PS)组成,PM是管理节点,负责维护一个全局的试图,而实际的读写操作都由PS完成。
为了方便描述,这里以存储Table为例说明。为了向用户提供表格的语义,在Partition layer会有一个有序的大表,存储所有用户的所有数据,每一行对应用户存储的一条表记录,考虑这张表非常大,单个server不可能服务过来,这张表被划分成很多个Range,然后均分到多个PS上,而PM维护一张Range==gt;PS的映射表,Front End接受到用户请求时,会先从PM拿到映射表,然后将请求定向至负责对应range的PS上,Front End拿到映射表后会缓存在本地,并在映射表变化时更新。
每个PS会负责多个Range的数据,PS实际不存储数据,数据存储是由底层的Stream Layer完成,每个Range包含一个用于存储操作日志的Commit Log文件和一个存储行数据的Row Data文件;同时Range被加载后,还会产生一些内存的数据结构。
Memory Table:内存表,记录对于该range的每一次更新。
Index Cache:表索引的缓存,索引每行数据在Row Data文件里的偏移位置。
Row Data Cache:行缓存,缓存行数据,与Index Cache分离的原因主要是尽量让所有Index的数据都能加载到内存。
当有新的行要写到某个Range时,首先会将行数据追加到Commit Log里,然后将行数据写到Memory Table,这时就可以向客户端(Front End)返回写成功。当Memory Table使用的内存超出阈值时,会做一次checkpoint操作,将Memory Table里的数据写至Row Data文件。
当Range里的数据太多时,会导致负责该Range的PS负载很高,这时PM可以将一些大的Range进行分裂,就部分Range交由负载较低的PS负责(PS本身不持久化数据,PS只需要加载Range对应的元数据即可服务针对该Range的请求);相反,当某些Range由于数据删除导致数据很少时,PM可以将相邻的Range进行合并;最终使得各个PS的负载尽量均衡。
特别声明:以上文章内容仅代表作者本人观点,不代表ESG跨境电商观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与ESG跨境电商联系。
二维码加载中...
使用微信扫一扫登录
使用账号密码登录
平台顾问
微信扫一扫
马上联系在线顾问
小程序
ESG跨境小程序
手机入驻更便捷
返回顶部