java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2216|回复: 0

《大规模分布式存储系统》 第4章 分布式文件系统【4.1】

[复制链接]
  • TA的每日心情
    开心
    2021-5-25 00:00
  • 签到天数: 1917 天

    [LV.Master]出神入化

    2025

    主题

    3683

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66105

    宣传达人突出贡献优秀版主荣誉管理论坛元老

    发表于 2017-3-3 20:20:23 | 显示全部楼层 |阅读模式
    分布式文件系统的主要功能有两个:一个是存储文档、图像、视频之类的Blob) p3 w# q) v# r( ~  U& `  V
    类型数据;另外一个是作为分布式表格系统的持久化层。
    % I& y! G2 O1 `9 N6 O分布式文件系统中最为著名的莫过于Google File System(GFS),它构建在廉价
    8 X9 F4 e5 Y+ T的普通PC服务器之上,支持自动容错。GFS内部将大文件划分为大小约为64MB的数
    $ a3 ^, w4 K* g据块(chunk),并通过主控服务器(Master)实现元数据管理、副本管理、自动负& Q, \6 q' q  n1 ]0 ^
    载均衡等操作。其他文件系统,例如Taobao File System(TFS)、Facebook Haystack1 O4 L" l  q* t* I' m, w/ N9 y
    或多或少借鉴了GFS的思路,架构上都比较相近。
      A' q5 P' W$ K4 J本章首先重点介绍GFS的内部实现机制,接着介绍TFS和Face book Haystack的内
    3 N& N$ S8 _; ?5 ?2 }部实现。最后,本章还会简单介绍内容分发网络(Content Delivery Network,CDN)技4 _" B# o3 s; `& s
    术,这种技术能够将图像、视频之类的数据缓存在离用户“最近”的网络节点上,从  _3 A6 I) h: j$ e
    而降低访问延时,节省带宽。* \4 F2 R1 _; L6 Q. a3 S# h
    4.1 Google文件系统. G& j' c# I! R+ x9 q. ?& r
    Google文件系统(GFS)是构建在廉价服务器之上的大型分布式系统。它将服务
    & z5 r! E* l0 v' \( x器故障视为正常现象,通过软件的方式自动容错,在保证系统可靠性和可用性的同
      Z, H; @5 H  O+ s; @时,大大降低系统的成本。5 P( P. b9 L% t
    GFS是Google分布式存储的基石,其他存储系统,如Google Bigtable、Google0 H6 X, l8 h% {1 g/ ?( D) u
    Megastore、Google Percolator均直接或者间接地构建在GFS之上。另外,Google大规
    " Q) T2 j. D$ ^0 ]1 ~- f- W模批处理系统MapReduce也需要利用GFS作为海量数据的输入输出。+ O5 y' w' W. [1 r2 d
    4.1.1 系统架构7 C& \$ z$ [+ }
    如图4-1所示,GFS系统的节点可分为三种角色:GFS Master(主控服务器)、
      r: i- U; f1 eGFS ChunkServer(CS,数据块服务器)以及GFS客户端。' C9 _* N# q; I/ V7 G$ \2 J
    图 4-1 GFS整体架构
    9 b- J  ^- h' ~0 dGFS文件被划分为固定大小的数据块(chunk),由主服务器在创建时分配一个7 x2 i" E! i( g' U  |; O3 P
    64位全局唯一的chunk句柄。CS以普通的Linux文件的形式将chunk存储在磁盘中。为: l% G( \  e7 P5 I& j
    了保证可靠性,chunk在不同的机器中复制多份,默认为三份。
    8 C% Q6 y% ~) q- p9 g3 k. Y# \) Q主控服务器中维护了系统的元数据,包括文件及chunk命名空间、文件到chunk之: ^* x  ?+ d- o
    间的映射、chunk位置信息。它也负责整个系统的全局控制,如chunk租约管理、垃圾9 q% ~8 F& N# D; J
    回收无用chunk、chunk复制等。主控服务器会定期与CS通过心跳的方式交换信息。6 E" d1 V: z" |% ]" s. K( P  C$ M
    客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规2 R2 S; I: I9 _
    范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之2 Y: }5 D4 E6 Z8 [+ B, U
    进行交互的CS信息,然后直接访问这些CS,完成数据存取工作。
    , o6 b' x" Z# T) L( m9 D6 H需要注意的是,GFS中的客户端不缓存文件数据,只缓存主控服务器中获取的元  N/ X" h% p+ }9 E
    数据,这是由GFS的应用特点决定的。GFS最主要的应用有两个:MapReduce与2 |( |+ ?$ I0 C8 j7 b2 S+ L
    Bigtable。对于MapReduce,GFS客户端使用方式为顺序读写,没有缓存文件数据的必7 w- v, u3 t' H& m! z
    要;而Bigtable作为分布式表格系统,内部实现了一套缓存机制。另外,如何维护客% V6 f/ z$ L9 e
    户端缓存与实际数据之间的一致性是一个极其复杂的问题。
    5 ]) {* n. F- S! J2 p4.1.2 关键问题" ]7 D. |! T8 s9 j7 _4 T
    1.租约机制$ _7 e# b+ j8 M/ N
    GFS数据追加以记录为单位,每个记录的大小为几十KB到几MB不等,如果每次
    , b& b& y) q* V1 S记录追加都需要请求Master,那么Master显然会成为系统的性能瓶颈,因此,GFS系8 J# e# g* ~& v! W( F
    统中通过租约(lease)机制将chunk写操作授权给ChunkServer。拥有租约授权的- q! N* _; O8 |9 o1 ?: |! F" K0 d
    ChunkServe称为主ChunkServer,其他副本所在的ChunkServer称为备ChunkServer。租! Z8 ^. S, U! u$ x# R( M$ v6 H4 l+ ?
    约授权针对单个chunk,在租约有效期内,对该chunk的写操作都由主ChunkServer负. g) L( c! M3 a3 ~/ F: g- B
    责,从而减轻Master的负载。一般来说,租约的有效期比较长,比如60秒,只要没有
      n' \! P$ a( k$ f) S0 |出现异常,主ChunkServer可以不断向Master请求延长租约的有效期直到整个chunk写; i; C  [% W! L* V5 E
    满。. ~( D8 h& R' I2 @& L# F4 u
    假设chunk A在GFS中保存了三个副本A1、A2、A3,其中,A1是主副本。如果副0 s8 E( ~6 D' l; W  N* o" y
    本A2所在ChunkServer下线后又重新上线,并且在A2下线的过程中,副本A1和A3有! D* L' _1 f/ m+ B
    更新,那么A2需要被Master当成垃圾回收掉。GFS通过对每个chunk维护一个版本号( Z: g6 [3 I" @: v' K" ^. [! d
    来解决,每次给chunk进行租约授权或者主ChunkServer重新延长租约有效期时,: ^+ F# X% O+ b* _! u" [
    Master会将chunk的版本号加1。A2下线的过程中,副本A1和A3有更新,说明主3 q0 @# ?4 L" P0 c, @; Z
    ChunkServer向Master重新申请租约并增加了A1和A3的版本号,等到A2重新上线后,0 p5 a( ^- M  T' A- t$ [
    Master能够发现A2的版本号太低,从而将A2标记为可删除的chunk,Master的垃圾回收; J. W& H7 [7 ~$ c: t' Q
    任务会定时检查,并通知ChunkServer将A2回收掉。1 v. a+ B+ z: l) ?7 {6 I
    2.一致性模型
    ! E" |% ]/ Z0 q9 y. E* R! \2 `GFS主要是为了追加(append)而不是改写(overwrite)而设计的。一方面是因& `' R3 J& Y# r) ^) O
    为改写的需求比较少,或者可以通过追加来实现,比如可以只使用GFS的追加功能构- [( I  P, W# R
    建分布式表格系统Bigtable;另一方面是因为追加的一致性模型相比改写要更加简单* i. r0 e& F& y
    有效。考虑chunk A的三个副本A1、A2、A3,有一个改写操作修改了A1、A2但没有
    2 C7 I9 u9 F; Z2 S修改A3,这样,落到副本A3的读操作可能读到不正确的数据;相应地,如果有一个7 |* r9 J, ?7 Q% r6 \. D- f* b
    追加操作往A1、A2上追加了一个记录,但是追加A3失败,那么即使读操作落到副本$ E7 u% k0 x& z  b; T) H( p
    A3也只是读到过期而不是错误的数据。& p# a0 m- f9 o( {
    我们只讨论追加的一致性。如果不发生异常,追加成功的记录在GFS的各个副本/ G4 N' x: O* h
    中是确定并且严格一致的;但是如果出现了异常,可能出现某些副本追加成功而某. e$ O7 [( d) p: }
    些副本没有成功的情况,失败的副本可能会出现一些可识别的填充(padding)记# t; t! c/ M. X0 n5 Q
    录。GFS客户端追加失败将重试,只要返回用户追加成功,说明在所有副本中都至少
    ) X! R2 a9 @: |4 K3 {追加成功了一次。当然,可能出现记录在某些副本中被追加了多次,即重复记录;9 E% |" d! f9 A6 l0 ^5 E# d
    也可能出现一些可识别的填充记录,应用层需要能够处理这些问题。/ [- R6 u3 r' I: ~
    另外,由于GFS支持多个客户端并发追加,多个客户端之间的顺序是无法保证
    7 Y; \& K9 y6 j  G$ c7 q的,同一个客户端连续追加成功的多个记录也可能被打断,比如客户端先后追加成5 Q& m4 Y$ R$ c) x8 }
    功记录R1和R2,由于追加R1和R2这两条记录的过程不是原子的,中途可能被其他客
    ! q$ j3 s# S) B$ N5 _* V  D  i0 i户端打断,那么GFS的chunk中记录的R1和R2可能不连续,中间夹杂着其他客户端追
    + x* F% P# O  l: |1 w加的数据。  ~; o5 {4 i) j' j+ o& K
    GFS的这种一致性模型是追求性能导致的,这增加了应用程序开发的难度。对于
    2 f2 m+ u& J: \' aMapReduce应用,由于其批处理特性,可以先将数据追加到一个临时文件,在临时文5 e3 U( x3 G! L6 [  I( i
    件中维护索引记录每个追加成功的记录的偏移,等到文件关闭时一次性将临时文件# i( b" c7 A/ }( I0 k* x1 U
    改名为最终文件。对于上层的Bigtable,有两种处理方式,后面将会介绍。
    ; g, s$ t# _. B; O6 Z$ C3.追加流程) ^: v5 C' |' T: ?
    追加流程是GFS系统中最为复杂的地方,而且,高效支持记录追加对基于GFS实
    9 e- B( Q. ]. n$ n9 `现的分布式表格系统Bigtable是至关重要的。如图4-2所示,追加流程大致如下:
    " A' x" F6 Y" M( ?8 P图 4-2 GFS追加流程
    & Z) x; L+ t6 K$ n1)客户端向Master请求chunk每个副本所在的ChunkServer,其中主ChunkServer持
    ' b( q7 Q1 o: {% R有修改租约。如果没有ChunkServer持有租约,说明该chunk最近没有写操作,Master* {& Q' Q% A/ t4 l8 h$ v+ u" u
    会发起一个任务,按照一定的策略将chunk的租约授权给其中一台ChunkServer。
    , O! j7 v; T: ?1 k2)Master返回客户端主副本和备副本所在的ChunkServer的位置信息,客户端将5 R2 h' w" l; ~8 r, Q& y
    缓存这些信息供以后使用。如果不出现故障,客户端以后读写该chunk都不需要再次
    5 z/ c7 V  X2 S请求Master。
    1 k7 ]7 m9 x6 c6 X' I0 r3)客户端将要追加的记录发送到每一个副本,每一个ChunkServer会在内部的
    1 E: I" d& ?: bLRU结构中缓存这些数据。GFS中采用数据流和控制流分离的方法,从而能够基于网6 T6 E. q  b- e* l
    络拓扑结构更好地调度数据流的传输。8 n: v. I' ]5 c: ]* A9 a0 F" x
    4)当所有副本都确认收到了数据,客户端发起一个写请求控制命令给主副本。, u1 t- u/ D- Z
    由于主副本可能收到多个客户端对同一个chunk的并发追加操作,主副本将确定这些0 H' z! A% [1 t: k) h
    操作的顺序并写入本地。
    9 \, J( d3 b+ Q3 p  U7 X3 D5)主副本把写请求提交给所有的备副本。每一个备副本会根据主副本确定的顺
    & Y0 S& F3 O$ `- r/ d; ]5 h序执行写操作。/ g8 R$ H) ~# ~+ K, n
    6)备副本成功完成后应答主副本。
    ( ]* g# s8 ?/ q0 A' \) Z3 L  y7)主副本应答客户端,如果有副本发生错误,将出现主副本写成功但是某些备
    ; G/ _" t% m5 c副本不成功的情况,客户端将重试。0 I4 A; N6 a. h  f! }/ s7 P# s; H
    GFS追加流程有两个特色:流水线及分离数据流与控制流。流水线操作用来减少
    9 ^+ }' ~$ ?2 g  q3 a: u1 N. a延时。当一个ChunkServer接收到一些数据,它就立即开始转发。由于采用全双工网  ?0 E4 s! k, {* u" x" ]8 Z
    络,立即发送数据并不会降低接收数据的速率。抛开网络阻塞,传输B个字节到R个
    7 B! O, `- y. Q+ y2 e, p: e1 P副本的理想时间是B/T+RL,其中T是网络吞吐量,L是节点之间的延时。假设采用千  [, h' v. |) R
    兆网络,L通常小于1ms,传输1MB数据到多个副本的时间小于80ms。分离数据流与. g3 S0 C, \+ t' G* n# a
    控制流主要是为了优化数据传输,每一台机器都是把数据发送给网络拓扑图上“最3 _8 F6 T+ }$ v
    近”的尚未收到数据的数据。举个例子,假设有三台ChunkServer:S1、S2和S3,S1与  f$ j$ u. P5 R& y* z0 o! ~
    S3在同一个机架上,S2在另外一个机架上,客户端部署在机器S1上。如果数据先从
    & c* {1 g: F; cS1转发到S2,再从S2转发到S3,需要经历两次跨机架数据传输;相对地,按照GFS
      D1 [) `) t7 s  C0 B: K中的策略,数据先发送到S1,接着从S1转发到S3,最后转发到S2,只需要一次跨机
    ! \" x9 C4 \3 @+ e$ h架数据传输。& @8 S8 S+ K+ u% U; Y
    分离数据流与控制流的前提是每次追加的数据都比较大,比如MapReduce批处理
    ! n5 }. q1 b$ w9 O系统,而且这种分离增加了追加流程的复杂度。如果采用传统的主备复制方法,追
    ; P, @1 S4 Q) F7 N/ \( V加流程会在一定程度上得到简化,如图4-3所示:! q' ]0 E# o& t6 i0 e3 Y
    图 4-3 GFS追加流程(数据流与控制流合并)$ D# t2 `- f- K6 c
    1)同图4-2 GFS追加流程:客户端向Master请求chunk每个副本所在的
    * j9 r" F; L- K3 F! _ChunkServer。
    6 K. T! s/ X) ?) Y9 F: [2)同图4-2 GFS追加流程:Master返回客户端主副本和备副本所在ChunkServer的
    / J5 t. D. b9 y. o& n6 i位置信息。4 u# X; |# I% d" z9 W2 U; Q
    3)Client将待追加数据发送到主副本,主副本可能收到多个客户端的并发追加
    $ O. O  \- V& }! V' J2 W0 i请求,需要确定操作顺序,并写入本地。
    5 Q5 W, m: Z2 s. ]* }, v( @4)主副本将数据通过流水线的方式转发给所有的备副本。
    . @. w9 ?, ?( S1 L0 P! M( S5)每个备副本收到待追加的记录数据后写入本地,所有副本都在本地写成功并( k" g; U* Z% j! o0 z% |0 C
    且收到后一个副本的应答消息时向前一个副本回应,比如图4-3中备副本A需要等待
    0 _1 ~( l' C' B- J备副本B应答成功且本地写成功后才可以应答主副本。
    $ u1 x' s; L( a- z  p9 R. i6)主副本应答客户端。如果客户端在超时时间之内没有收到主副本的应答,说) {' j7 T% S, _" {5 B
    明发生了错误,需要重试。
    4 V6 w% i7 D3 R- g; Z当然,实际的追加流程远远没有这么简单。追加的过程中可能出现主副本租约& c# `  l# L  w2 Y' o
    过期而失去chunk修改操作的授权,以及主副本或者备副本所在的ChunkServer出现故: q& F/ C- L  k
    障,等等。由于篇幅有限,追加流程的异常处理留作读者思考。
    / K; h2 L1 f' [' u0 U7 v4.容错机制
    % H( z; f4 ]: e2 O- v(1)Master容错1 i( B2 v5 x9 @* X2 n- P
    Master容错与传统方法类似,通过操作日志加checkpoint的方式进行,并且有一' W5 |! n/ Z. t/ ^, [
    台称为"Shadow Master"的实时热备。* U* j2 O$ o: q0 z2 r
    Master上保存了三种元数据信息:
    * D9 T; j+ y: r2 f2 |0 x  b●命名空间(Name Space),也就是整个文件系统的目录结构以及chunk基本信! t  N7 K6 H) P+ I% \7 h5 u
    息;
    * Q: s" G' [; X, \●文件到chunk之间的映射;, M9 h) _! `% T7 w) T  Y7 Q# E" s4 c
    ●chunk副本的位置信息,每个chunk通常有三个副本。
    % k( ~- D2 m' i0 c/ I4 x4 P  _GFS Master的修改操作总是先记录操作日志,然后修改内存。当Master发生故障( l2 G' H7 I( y; E4 ]) n
    重启时,可以通过磁盘中的操作日志恢复内存数据结构。另外,为了减少Master宕机
    & `. j  D; \4 ~恢复时间,Master会定期将内存中的数据以checkpoint文件的形式转储到磁盘中,从
    0 n% b: u, [6 e而减少回放的日志量。为了进一步提高Master的可靠性和可用性,GFS中还会执行实
    6 q' L4 v! Q! n. _; q时热备,所有的元数据修改操作都必须保证发送到实时热备才算成功。远程的实时
    9 _( F- J- C" P; M+ O3 l热备将实时接收Master发送的操作日志并在内存中回放这些元数据操作。如果Master
    + O! p4 p4 V. d6 a" n宕机,还可以秒级切换到实时备机继续提供服务。为了保证同一时刻只有一台
    - ~  n+ n/ P, f! F0 FMaster,GFS依赖Google内部的Chubby服务进行选主操作。
    4 y+ Q- J# g: h  Z* kMaster需要持久化前两种元数据,即命名空间及文件到chunk之间的映射;对于
    % [7 K; O1 ~! |第三种元数据,即chunk副本的位置信息,Master可以选择不进行持久化,这是因为
    * k7 |& q0 V" b, {6 N* B  sChunkServer维护了这些信息,即使Master发生故障,也可以在重启时通过
    1 n# R/ h1 e: ~1 ?8 M% zChunkServer汇报来获取。
    % F5 C& A$ b6 `- |) o* r(2)ChunkServer容错! E( M) F! R% k- q6 j) G
    GFS采用复制多个副本的方式实现ChunkServer的容错,每个chunk有多个存储副
    + G! o3 |& G( p: N本,分别存储在不同的ChunkServer上。对于每个chunk,必须将所有的副本全部写入
    6 m+ \* h: N$ @% C: e成功,才视为成功写入。如果相关的副本出现丢失或不可恢复的情况,Master自动将
    3 [/ `9 [6 r4 k( _5 h$ D; C! H副本复制到其他ChunkServer,从而确保副本保持一定的个数。
    . o! M; y3 x- n9 t0 e$ ~, z5 P另外,ChunkServer会对存储的数据维持校验和。GFS以64MB为chunk大小来划分! Q, R1 P8 A# z( j0 h
    文件,每个chunk又以Block为单位进行划分,Block大小为64KB,每个Block对应一个
    # s- B) N: b8 j+ n: ]32位的校验和。当读取一个chunk副本时,ChunkServer会将读取的数据和校验和进行
    % z, j; c% ^3 }9 y9 a2 K0 S比较,如果不匹配,就会返回错误,客户端将选择其他ChunkServer上的副本。  S0 T! T- y% k! P  W# T
    4.1.3 Master设计" k! K. ~$ B$ ]5 |4 p
    1.Master内存占用4 [5 {9 ?- _! j- E
    Master维护了系统中的元数据,包括文件及chunk命名空间、文件到chunk之间的% _" f9 H3 {  N9 B- V  l* F; v
    映射、chunk副本的位置信息。其中前两种元数据需要持久化到磁盘,chunk副本的位
      v  k  b) {9 D# M& f置信息不需要持久化,可以通过ChunkServer汇报获取。
    9 F$ C- W+ X9 l内存是Master的稀有资源,接下来介绍如何估算Master的内存使用量。chunk的元6 c% O8 L+ h! \# {( T6 Y
    信息包括全局唯一的ID、版本号、每个副本所在的ChunkServer编号、引用计数等。
    6 O0 Q, U4 {" e0 G3 a' G* j( QGFS系统中每个chunk大小为64MB,默认存储3份,每个chunk的元数据小于64字节。
    ' V7 p( Y, w0 A$ a, ?" f那么1PB数据的chunk元信息大小不超过1PB×3/64MB×64=3GB。另外,Master对命名6 H, K( t# {# @6 E& r  h
    空间进行了压缩存储,例如有两个文件foo1和foo2都存放在目  s9 ^/ ~* Y* h1 l9 T" \+ v7 o
    录/home/very_long_directory_name/中,那么目录名在内存中只需要存放一次。压缩存
    . O. ]6 a+ v0 z& h储后,每个文件在文件命名空间的元数据也不超过64字节,由于GFS中的文件一般都6 q. w8 j7 K- P1 B7 p( Q7 x
    是大文件,因此,文件命名空间占用内存不多。这也就说明了Master内存容量不会成
    # m% J! y9 X" p  w0 k$ G, y$ f# Z为GFS的系统瓶颈。
    ' q6 N5 n' o, B2 z; x2.负载均衡6 j& ]. S1 h; {$ g  `8 K4 {
    GFS中副本的分布策略需要考虑多种因素,如网络拓扑、机架分布、磁盘利用率
    : w- k7 z; k, e等。为了提高系统的可用性,GFS会避免将同一个chunk的所有副本都存放在同一个
    ' K4 _7 N. }+ N5 k3 i# C+ Q8 Q机架的情况。
    9 m6 c0 k& U; E5 }6 _1 `, d系统中需要创建chunk副本的情况有三种:chunk创建、chunk复制(re-
    7 N0 k9 o% V' V. o; N9 J. `replication)以及负载均衡(rebalancing)。; N) H0 M2 I" ^) H  R$ r' z
    当Master创建了一个chunk,它会根据如下因素来选择chunk副本的初始位置:1)
    . f( m5 [- `2 a8 `% g4 m+ `7 f新副本所在的ChunkServer的磁盘利用率低于平均水平;2)限制每个Chunk-Server“最/ ?5 V4 Q* R$ C( }7 z/ f8 I
    近”创建的数量;3)每个chunk的所有副本不能在同一个机架。第二点容易忽略但却
    . A2 |! V- C, V/ m# i' L5 z很重要,因为创建完chunk以后通常需要马上写入数据,如果不限制“最近”创建的数! W1 J9 H3 [; v6 h& h) t
    量,当一台空的ChunkServer上线时,由于磁盘利用率低,可能导致大量的chunk瞬间6 ?) U( y- a& F5 H
    迁移到这台机器从而将它压垮。
    : j  r0 s% ]3 s- ]) C当chunk的副本数量小于一定的数量后,Master会尝试重新复制一个chunk副本。1 N: |, k  S# x! b0 Q
    可能的原因包括ChunkServer宕机或者ChunkServer报告自己的副本损坏,或者" Z+ [! B$ F5 ?8 x
    ChunkServer的某个磁盘故障,或者用户动态增加了chunk的副本数,等等。每个chunk
    - A* x" s7 S& m* M复制任务都有一个优先级,按照优先级从高到低在Master排队等待执行。例如,只有
    0 D. |+ W# x& [3 ]7 f7 \一个副本的chunk需要优先复制。另外,GFS会提高所有阻塞客户端操作的chunk复制: |6 O( [% F9 j. V4 u7 y$ }6 [8 w2 T
    任务的优先级,例如客户端正在往一个只有一个副本的chunk追加数据,如果限制至
    4 Q' Y4 D6 W9 x: x' l少需要追加成功两个副本,那么这个chunk复制任务会阻塞客户端写操作,需要提高
    3 z  z6 _# Q7 T7 T1 F9 j8 i优先级。
    + K5 d! M3 ~% m/ f最后,Master会定期扫描当前副本的分布情况,如果发现磁盘使用量或者机器负8 g# W  n6 f' _$ B/ a3 U4 n
    载不均衡,将执行重新负载均衡操作。
    . s% v9 C: _) `) F无论是chunk创建,chunk重新复制,还是重新负载均衡,这些操作选择chunk副本( X9 \* m2 d8 r4 _" _' m' ^
    位置的策略都是相同的,并且需要限制重新复制和重新负载均衡任务的拷贝速度,  [7 ~2 X: M, Z" r5 G" `
    否则可能影响系统正常的读写服务。  h$ v8 O- P0 I4 \
    3.垃圾回收
    / q4 U+ j. b7 |$ e( I" {% y. sGFS采用延迟删除的机制,也就是说,当删除文件后,GFS并不要求立即归还可
    3 C3 o+ b7 N+ f用的物理存储,而是在元数据中将文件改名为一个隐藏的名字,并且包含一个删除( d. O! {: }" v/ u5 O9 t
    时间戳。Master定时检查,如果发现文件删除超过一段时间(默认为3天,可配
    $ g" g- M( _9 n7 U* M! P- A. t1 r! A置),那么它会把文件从内存元数据中删除,以后ChunkServer和Master的心跳消息- X- d0 \4 a- I. `
    中,每一个ChunkServer都将报告自己的chunk集合,Master会回复在Master元数据中
    4 p' R- I, k& i4 u$ J已经不存在的chunk信息,这时,ChunkServer会释放这些chunk副本。为了减轻系统的# `) E( g0 O7 X/ d4 p
    负载,垃圾回收一般在服务低峰期执行,比如每天晚上凌晨1:00开始。
    1 c  |; K; z9 [0 y2 a另外,chunk副本可能会因为ChunkServer失效期间丢失了对chunk的修改操作而导5 N1 f: X) B. R1 E; S
    致过期。系统对每个chunk都维护了版本号,过期的chunk可以通过版本号检测出来。
    ( z, n* ~% l7 A. s& z3 X' p  `5 V8 WMaster仍然通过正常的垃圾回收机制来删除过期的副本。
    ) g8 `. l' Y5 a4.快照3 ^% n: i+ t+ Z2 r: @
    快照(Snapshot)操作是对源文件/目录进行一个“快照”操作,生成该时刻源文1 c# @, a( x+ N  ]9 M! x8 n
    件/目录的一个瞬间状态存放于目标文件/目录中。GFS中使用标准的写时复制机制生
    9 g: g3 s% e4 H# F' c成快照,也就是说,“快照”只是增加GFS中chunk的引用计数,表示这个chunk被快照6 A- K/ G$ N1 h, c- x
    文件引用了,等到客户端修改这个chunk时,才需要在ChunkServer中拷贝chunk的数据, i/ F; c; t: i! R0 `( u
    生成新的chunk,后续的修改操作落到新生成的chunk上。3 B9 ]& U( e% Z- K5 q' v/ J
    为了对某个文件做快照,首先需要停止这个文件的写服务,接着增加这个文件
    7 `; i3 T4 |$ N的所有chunk的引用计数,以后修改这些chunk时会拷贝生成新的chunk。对某个文件执: H5 d6 `  E; V4 Z8 p5 H" x6 q
    行快照的大致步骤如下:. K, \/ ?" j$ `+ b$ U1 O
    1)通过租约机制收回对文件的每个chunk写权限,停止对文件的写服务;; S* P& A$ {! ]3 P
    2)Master拷贝文件名等元数据生成一个新的快照文件;7 d' F) ^* M, S; h
    3)对执行快照的文件的所有chunk增加引用计数。+ }* ?  k3 T+ E+ d
    例如,对文件foo执行快照操作生成foo_backup,foo在GFS中有三个chunk:C1、C2* u9 c) _: M# U; s* `, a( f
    和C3(简单起见,假设每个chunk只有一个副本)。Master首先需要收回C1、C2和C3' m( x, |: i2 P8 J6 V/ h
    的写租约,从而保证文件foo处于一致的状态,接着Master复制foo文件的元数据用于
    # q: u. X/ d( A4 X8 R生成foo_backup,foo_backup同样指向C1、C2和C3。快照前,C1、C2和C3只被一个文
    , m( ~! t  f/ L6 j' \" m件foo引用,因此引用计数为1;执行快照操作后,这些chunk的引用计数增加为2。以
    ; l7 W+ M3 x2 M% ?0 U9 I) }后客户端再次向C3追加数据时,Master发现C3的引用计数大于1,通知C3所在的
    1 v/ ~6 ?* }9 O# [9 TChunkServer本次拷贝C3生成C3',客户端的追加操作也相应地转向C3'。  C/ y$ b$ i0 W9 S8 o! W
    4.1.4 ChunkServer设计8 g! Y/ }2 ~6 \
    ChunkServer管理大小约为64MB的chunk,存储的时候需要保证chunk尽可能均匀
    1 W) q) R& E& m) l0 ^地分布在不同的磁盘之中,需要考虑的可能因素包括磁盘空间、最近新建chunk数  D/ G9 R# N7 i' |% f. F
    等。另外,Linux文件系统删除64MB大文件消耗的时间太长且没有必要,因此,删除
    $ v" i: g3 {8 {% [- Qchunk时可以只将对应的chunk文件移动到每个磁盘的回收站,以后新建chunk的时候可
    % A: `) O$ ~/ v" q  C* ~以重用。
    4 F5 b& r3 A! G  U. G7 Q; l; V/ [ChunkServer是一个磁盘和网络IO密集型应用,为了最大限度地发挥机器性能,/ U" D0 [. P! m$ B1 W
    需要能够做到将磁盘和网络操作异步化,但这会增加代码实现的难度。
    3 s% p+ a! G2 k; E( X' g4.1.5 讨论7 s- ]3 P) v' E) I) [/ F- |% s
    从GFS的架构设计可以看出,GFS是一个具有良好可扩展性并能够在软件层面自4 P5 n6 V: g, r5 w. ]. w
    动处理各种异常情况的系统。Google是一家很重视自动化的公司,从早期的GFS,再* V- s& s# [5 y
    到Bigtable、Megastore,以及最近的Spanner,Google的分布式存储系统在这一点上一脉
    6 Q0 A- K/ X0 g$ ^/ \0 `相承。由于Google的系统一开始能很好地解决可扩展性问题,所以后续的系统能够
    ( ^% X, X# p) J8 Q构建在前一个系统之上并且一步一步引入新的功能,如Bigtable在GFS之上将海量数
    ) a( r3 d% U2 ~1 X+ ]% w据组织成表格形式,Megastore、Spanner又进一步在Bigtable之上融合一些关系型数据
    ' |) z, }! J- W' T' I库的功能,整个解决方案完美华丽。* Q! P2 ]) y8 {+ R8 c- \. A! \( u
    自动化对系统的容错能力提出了很高的要求,在设计GFS时认为节点失效是常! X# D) k/ M( @: m& @7 M3 \3 M
    态,通过在软件层面进行故障检测,并且通过chunk复制操作将原有故障节点的服务
    ) |" [& o# k$ U; f迁移到新的节点。系统还会根据一定的策略,如磁盘使用情况、机器负载等执行负
    , f0 t5 E3 L( h# g$ C载均衡操作。Google在软件层面的努力获得了巨大的回报,由于软件层面能够做到
    ' h/ z7 U! j( ~" x1 j自动化容错,底层的硬件可以采用廉价的错误率较高的硬件,比如廉价的SATA盘,% L+ Z4 y- @9 V
    这大大降低了云服务的成本,在和其他厂商的竞争中表现出价格优势。比较典型的
    ) B% }# c  ^/ m例子就是Google的邮箱服务,由于基础设施成本低,Gmail服务能够免费给用户提供
    ) A1 _) [6 d# X( P) H; \更大的容量,令其他厂商望尘莫及。) o( ~4 X- _2 M
    Google的成功经验也表明了一点:单Master的设计是可行的。单Master的设计不  x' f5 a! M+ Z
    仅简化了系统,而且能够较好地实现一致性,后面我们将要看到的绝大多数分布式1 B1 e3 T6 `, E
    存储系统都和GFS一样依赖单总控节点。然而,单Master的设计并不意味着实现GFS5 o0 t+ r5 h& W! g' n. \7 ^, ?
    只是一些比较简单琐碎的工作。基于性能考虑,GFS提出了“记录至少原子性追加一  q# q6 M/ p: c  l0 i; g
    次”的一致性模型,通过租约的方式将每个chunk的修改授权下放到ChunkServer从而减
    ! k, p6 d! q: Z5 o' \8 u& E少Master的负载,通过流水线的方式复制多个副本以减少延时,追加流程复杂繁琐。
    , c5 B6 K4 \2 \1 o另外,Master维护的元数据有很多,需要设计高效的数据结构,占用内存小,并且能
    ) h  {8 A: N$ N* E" `够支持快照操作。支持写时复制的B树能够满足Master的元数据管理需求,然而,它
    3 c/ s/ }6 m$ f  V5 \4 I的实现是相当复杂的。2 v* d4 G$ x0 h. D
    7 P$ T4 m$ e; s$ ^
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|Java自学网

    GMT+8, 2024-5-7 03:34 , Processed in 0.058787 second(s), 28 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

    快速回复 返回顶部 返回列表