java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2503|回复: 0

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

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

    [LV.Master]出神入化

    2096

    主题

    3754

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66788

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

    发表于 2017-3-3 20:20:23 | 显示全部楼层 |阅读模式
    分布式文件系统的主要功能有两个:一个是存储文档、图像、视频之类的Blob6 c4 p) {+ K9 h+ T
    类型数据;另外一个是作为分布式表格系统的持久化层。
      X( G$ R& ?- i$ G  s1 f分布式文件系统中最为著名的莫过于Google File System(GFS),它构建在廉价) k$ ?2 e6 [; O2 y7 O8 r
    的普通PC服务器之上,支持自动容错。GFS内部将大文件划分为大小约为64MB的数- ]0 z% z$ ]! L9 _; Y( T
    据块(chunk),并通过主控服务器(Master)实现元数据管理、副本管理、自动负5 v( P6 U* f  m4 k3 r: o3 {
    载均衡等操作。其他文件系统,例如Taobao File System(TFS)、Facebook Haystack
    ' z3 Z/ m2 G8 F& @或多或少借鉴了GFS的思路,架构上都比较相近。
    ' T$ z, K- q- F本章首先重点介绍GFS的内部实现机制,接着介绍TFS和Face book Haystack的内) _# ~' T- A- k, R+ F
    部实现。最后,本章还会简单介绍内容分发网络(Content Delivery Network,CDN)技
    % r: Z5 ^  b% v4 \. C+ ?术,这种技术能够将图像、视频之类的数据缓存在离用户“最近”的网络节点上,从0 A) Z6 y: V7 P7 v9 y: j
    而降低访问延时,节省带宽。
    ; t% O' N1 _, M4.1 Google文件系统8 a0 h! @! s8 i- a6 S6 R
    Google文件系统(GFS)是构建在廉价服务器之上的大型分布式系统。它将服务
    " V8 d# c+ K+ U* C4 T  r器故障视为正常现象,通过软件的方式自动容错,在保证系统可靠性和可用性的同5 i; R2 q& f' g& Z
    时,大大降低系统的成本。
    ! D+ h5 \4 E! oGFS是Google分布式存储的基石,其他存储系统,如Google Bigtable、Google* I6 I2 }1 U# ^0 A4 K
    Megastore、Google Percolator均直接或者间接地构建在GFS之上。另外,Google大规5 ^$ P( x, a- V1 q. D4 S
    模批处理系统MapReduce也需要利用GFS作为海量数据的输入输出。7 E) W# B4 l0 w7 m- Q+ w
    4.1.1 系统架构+ g& I/ M& C+ M; ?2 z; }- z
    如图4-1所示,GFS系统的节点可分为三种角色:GFS Master(主控服务器)、8 B( H: X& }; {+ x
    GFS ChunkServer(CS,数据块服务器)以及GFS客户端。
    , w' a5 [( X. }. d图 4-1 GFS整体架构1 t; I& C: e5 e% @. R0 i6 P
    GFS文件被划分为固定大小的数据块(chunk),由主服务器在创建时分配一个" ]" F, C. [3 l4 W* o
    64位全局唯一的chunk句柄。CS以普通的Linux文件的形式将chunk存储在磁盘中。为  g5 I1 V2 A' o( y" |
    了保证可靠性,chunk在不同的机器中复制多份,默认为三份。& P/ a$ {" ]4 j  H% Z  l5 i2 X  L
    主控服务器中维护了系统的元数据,包括文件及chunk命名空间、文件到chunk之
    9 K2 f; b( u: M2 w1 m5 ]间的映射、chunk位置信息。它也负责整个系统的全局控制,如chunk租约管理、垃圾
    ! K! K9 T& ^4 I回收无用chunk、chunk复制等。主控服务器会定期与CS通过心跳的方式交换信息。# [: @) O9 G2 t( [4 ^0 x1 h& y" n/ `% x
    客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规
    ; v! u1 g- o! N7 X& K! u5 c范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之* t( D2 `! D: w# D" V$ t. g8 D
    进行交互的CS信息,然后直接访问这些CS,完成数据存取工作。- [! P9 b( ]7 E; p
    需要注意的是,GFS中的客户端不缓存文件数据,只缓存主控服务器中获取的元
    - u* H$ k9 }& ^2 v. _) F数据,这是由GFS的应用特点决定的。GFS最主要的应用有两个:MapReduce与6 \& b- B4 T- _) h
    Bigtable。对于MapReduce,GFS客户端使用方式为顺序读写,没有缓存文件数据的必7 t  d$ K0 v) Z* ?
    要;而Bigtable作为分布式表格系统,内部实现了一套缓存机制。另外,如何维护客
      y; y# U* C0 C: @# x4 R户端缓存与实际数据之间的一致性是一个极其复杂的问题。
    # _5 f9 d3 n8 y0 T8 G, Y- }+ i4.1.2 关键问题. `/ R  `$ Y+ q6 q; t% v  d1 U
    1.租约机制5 v7 C5 `* H4 Q9 A- `1 f
    GFS数据追加以记录为单位,每个记录的大小为几十KB到几MB不等,如果每次
    8 b) L7 R+ ]- c5 _记录追加都需要请求Master,那么Master显然会成为系统的性能瓶颈,因此,GFS系; L, T; F7 \+ P$ p
    统中通过租约(lease)机制将chunk写操作授权给ChunkServer。拥有租约授权的
    * \6 A! r* g  ^2 M% OChunkServe称为主ChunkServer,其他副本所在的ChunkServer称为备ChunkServer。租
      R" r+ Q$ j, N/ Z4 r约授权针对单个chunk,在租约有效期内,对该chunk的写操作都由主ChunkServer负# L4 d  ^+ b! {" k; ]
    责,从而减轻Master的负载。一般来说,租约的有效期比较长,比如60秒,只要没有- O, g6 j: A3 j1 {
    出现异常,主ChunkServer可以不断向Master请求延长租约的有效期直到整个chunk写0 g; y2 X2 j+ _
    满。
    & m  b+ c, a: T$ m: r# O假设chunk A在GFS中保存了三个副本A1、A2、A3,其中,A1是主副本。如果副- u# F9 w$ `9 {9 Z# d6 O' S: z
    本A2所在ChunkServer下线后又重新上线,并且在A2下线的过程中,副本A1和A3有
    $ `9 l5 F( n9 i, g0 m更新,那么A2需要被Master当成垃圾回收掉。GFS通过对每个chunk维护一个版本号. l- z* P! J0 ]7 g3 v% o; Z) D
    来解决,每次给chunk进行租约授权或者主ChunkServer重新延长租约有效期时,
    6 u. b- T* Y* |1 gMaster会将chunk的版本号加1。A2下线的过程中,副本A1和A3有更新,说明主
    0 `5 B$ w% ~" _/ S2 tChunkServer向Master重新申请租约并增加了A1和A3的版本号,等到A2重新上线后,3 L) f1 H, h6 b$ d
    Master能够发现A2的版本号太低,从而将A2标记为可删除的chunk,Master的垃圾回收' |/ ~' ]/ k, d7 \
    任务会定时检查,并通知ChunkServer将A2回收掉。1 x/ L' C& k- u; _6 z  x
    2.一致性模型
    & H' e/ n( J9 D9 ]5 w& EGFS主要是为了追加(append)而不是改写(overwrite)而设计的。一方面是因
    ; m  j. h4 B4 K+ @7 E为改写的需求比较少,或者可以通过追加来实现,比如可以只使用GFS的追加功能构
    " R& I. @) Y% k" e& y" z& O$ ^建分布式表格系统Bigtable;另一方面是因为追加的一致性模型相比改写要更加简单
    ( K7 w, m) G9 o' c$ I* ^8 r; Z有效。考虑chunk A的三个副本A1、A2、A3,有一个改写操作修改了A1、A2但没有: E" t* n- q: ~% A7 z
    修改A3,这样,落到副本A3的读操作可能读到不正确的数据;相应地,如果有一个  C' W* J6 u3 ?! Y- R# M
    追加操作往A1、A2上追加了一个记录,但是追加A3失败,那么即使读操作落到副本
    # B% G$ W5 H6 |A3也只是读到过期而不是错误的数据。
    * R( g1 D4 e! [) T我们只讨论追加的一致性。如果不发生异常,追加成功的记录在GFS的各个副本
    0 U7 [' v! \9 w5 I中是确定并且严格一致的;但是如果出现了异常,可能出现某些副本追加成功而某- a: Q- G, s1 [/ ^6 `6 C( \! ^- _
    些副本没有成功的情况,失败的副本可能会出现一些可识别的填充(padding)记9 \+ R% p4 q2 N) l* h+ j# A! `
    录。GFS客户端追加失败将重试,只要返回用户追加成功,说明在所有副本中都至少
    1 n1 Z8 j6 g& [追加成功了一次。当然,可能出现记录在某些副本中被追加了多次,即重复记录;8 F$ ]: u- V+ t0 u% d% B
    也可能出现一些可识别的填充记录,应用层需要能够处理这些问题。8 V( B% i) N# p5 Y
    另外,由于GFS支持多个客户端并发追加,多个客户端之间的顺序是无法保证$ Q; f9 J+ ^; `) n$ B( C6 S
    的,同一个客户端连续追加成功的多个记录也可能被打断,比如客户端先后追加成
    7 U2 O. R& z  A功记录R1和R2,由于追加R1和R2这两条记录的过程不是原子的,中途可能被其他客
    / x4 _  ^1 `7 d  b7 Q" M3 m' B户端打断,那么GFS的chunk中记录的R1和R2可能不连续,中间夹杂着其他客户端追1 v! O; B: \! t7 U: Q
    加的数据。
    ( {/ `# U2 u; N5 H% I7 pGFS的这种一致性模型是追求性能导致的,这增加了应用程序开发的难度。对于
    3 Q( n0 g) E9 q# K: `6 N- vMapReduce应用,由于其批处理特性,可以先将数据追加到一个临时文件,在临时文8 N8 u4 W' f5 D7 |' K
    件中维护索引记录每个追加成功的记录的偏移,等到文件关闭时一次性将临时文件
    % V: K/ d7 J# @改名为最终文件。对于上层的Bigtable,有两种处理方式,后面将会介绍。' V( P. A- k- ^7 @$ B1 `" u" {0 X$ F
    3.追加流程1 @) a" b. y3 M) W7 G* ?
    追加流程是GFS系统中最为复杂的地方,而且,高效支持记录追加对基于GFS实
    0 G( V8 b, j0 K/ g现的分布式表格系统Bigtable是至关重要的。如图4-2所示,追加流程大致如下:2 a% O: z6 }7 A" N! [/ r! q
    图 4-2 GFS追加流程, r7 p$ N5 _4 [/ q" P
    1)客户端向Master请求chunk每个副本所在的ChunkServer,其中主ChunkServer持
    3 Z' y1 T9 [7 f) Y1 j) y1 C/ V有修改租约。如果没有ChunkServer持有租约,说明该chunk最近没有写操作,Master
    0 M3 I  v/ q5 v3 }* G- P  I会发起一个任务,按照一定的策略将chunk的租约授权给其中一台ChunkServer。
    8 E( {1 y7 `  X5 u4 F" y7 y2)Master返回客户端主副本和备副本所在的ChunkServer的位置信息,客户端将. S6 c; k3 Q0 e4 K0 C7 \2 n
    缓存这些信息供以后使用。如果不出现故障,客户端以后读写该chunk都不需要再次! J7 x9 a! I( E' @2 J7 }6 p; m
    请求Master。4 u; w3 V0 ^% E. {) T' K7 o
    3)客户端将要追加的记录发送到每一个副本,每一个ChunkServer会在内部的
    4 @- [! c1 S# QLRU结构中缓存这些数据。GFS中采用数据流和控制流分离的方法,从而能够基于网8 a+ b) t3 o: N3 X2 B
    络拓扑结构更好地调度数据流的传输。" T( I: U8 ]/ @, S: y$ U3 B' V  I
    4)当所有副本都确认收到了数据,客户端发起一个写请求控制命令给主副本。) q# s2 t! B+ Q5 g1 B% e) O/ _
    由于主副本可能收到多个客户端对同一个chunk的并发追加操作,主副本将确定这些, a4 `0 e2 }" U8 l# ?
    操作的顺序并写入本地。8 G# ]6 W" m4 r7 O: D+ d" \0 h
    5)主副本把写请求提交给所有的备副本。每一个备副本会根据主副本确定的顺/ s' H1 b. H. ?  a" Y$ |  Z9 L
    序执行写操作。; R  c' m% F) Y7 i
    6)备副本成功完成后应答主副本。8 }6 ]. A8 v% U+ m3 @: d& U$ R
    7)主副本应答客户端,如果有副本发生错误,将出现主副本写成功但是某些备
    : z  V( j: w0 x; r3 F3 o副本不成功的情况,客户端将重试。# v, _4 O/ T5 H0 |/ |; z
    GFS追加流程有两个特色:流水线及分离数据流与控制流。流水线操作用来减少
    1 d7 M. M. |  b延时。当一个ChunkServer接收到一些数据,它就立即开始转发。由于采用全双工网
    & j0 E* _" a8 {8 [: U络,立即发送数据并不会降低接收数据的速率。抛开网络阻塞,传输B个字节到R个; E  @! l! A) N" i! k; }( }  {
    副本的理想时间是B/T+RL,其中T是网络吞吐量,L是节点之间的延时。假设采用千
    9 M& h- w) e/ Y兆网络,L通常小于1ms,传输1MB数据到多个副本的时间小于80ms。分离数据流与
    " p. a  I! y! _2 Y+ u* D3 X) R控制流主要是为了优化数据传输,每一台机器都是把数据发送给网络拓扑图上“最
    ' i! }7 b" h; H6 l. x/ \$ |近”的尚未收到数据的数据。举个例子,假设有三台ChunkServer:S1、S2和S3,S1与
    4 g3 ^; C: C8 Q8 ?S3在同一个机架上,S2在另外一个机架上,客户端部署在机器S1上。如果数据先从4 C8 q) }, c8 d2 b; F
    S1转发到S2,再从S2转发到S3,需要经历两次跨机架数据传输;相对地,按照GFS
    5 k! D' V7 d( P中的策略,数据先发送到S1,接着从S1转发到S3,最后转发到S2,只需要一次跨机
    1 {! r* c7 |4 W; k. ~+ B. K" e架数据传输。
    + [; W0 x# W9 P8 l2 ]分离数据流与控制流的前提是每次追加的数据都比较大,比如MapReduce批处理
    ' `8 `- j: a7 r8 f! g7 S+ o系统,而且这种分离增加了追加流程的复杂度。如果采用传统的主备复制方法,追! D. i0 S# q6 L, V: x+ a5 r, G2 a+ O
    加流程会在一定程度上得到简化,如图4-3所示:
    - B: N  E2 t5 I+ Q, Y( g7 C/ a$ H& l) t0 z图 4-3 GFS追加流程(数据流与控制流合并)3 W  j1 G7 V' b* L+ j' o
    1)同图4-2 GFS追加流程:客户端向Master请求chunk每个副本所在的1 r  e- m' P9 X- `0 b& m6 o
    ChunkServer。) b. J; K' p- k( E
    2)同图4-2 GFS追加流程:Master返回客户端主副本和备副本所在ChunkServer的. P7 Z' v* @& i
    位置信息。
    ) I3 E* s! m1 C" ]* {  S/ z. A* v3)Client将待追加数据发送到主副本,主副本可能收到多个客户端的并发追加* V+ l- s4 R& a# h( d- W) X( U
    请求,需要确定操作顺序,并写入本地。
    * N) a# _: C. W. G# b) j. B, c4)主副本将数据通过流水线的方式转发给所有的备副本。- Z  Y  {" |& N# y* Z" A
    5)每个备副本收到待追加的记录数据后写入本地,所有副本都在本地写成功并+ y5 e  c, y) }/ Z1 N$ m
    且收到后一个副本的应答消息时向前一个副本回应,比如图4-3中备副本A需要等待# d9 f& P8 M& G; h9 t. `4 S9 M2 P
    备副本B应答成功且本地写成功后才可以应答主副本。( E: c: u9 n3 P9 ^5 ^
    6)主副本应答客户端。如果客户端在超时时间之内没有收到主副本的应答,说
    2 V) N3 V3 I; m- F3 [* |! @明发生了错误,需要重试。
    * W3 I: M9 A# M, y当然,实际的追加流程远远没有这么简单。追加的过程中可能出现主副本租约" ?' L$ n# e/ K- _: h
    过期而失去chunk修改操作的授权,以及主副本或者备副本所在的ChunkServer出现故
    , D5 J3 W4 [. E' N9 Q  b障,等等。由于篇幅有限,追加流程的异常处理留作读者思考。( n# U" h* x* |2 T
    4.容错机制
    - ]" D8 i$ K# E(1)Master容错6 b: ~2 `( U* u# n# B; B) `
    Master容错与传统方法类似,通过操作日志加checkpoint的方式进行,并且有一
    2 F! \2 F  ?2 @1 T, x6 `台称为"Shadow Master"的实时热备。" ^2 \* K+ O# {
    Master上保存了三种元数据信息:# c! _5 A+ C8 D9 Z
    ●命名空间(Name Space),也就是整个文件系统的目录结构以及chunk基本信4 w5 T$ i" o& f2 x+ D
    息;. z$ R. m1 g/ u. w2 d5 ^$ J4 D
    ●文件到chunk之间的映射;
    1 Z2 @- W: \1 D0 i3 f- ^●chunk副本的位置信息,每个chunk通常有三个副本。( H( Q1 c& u. L! w- N2 ]" c: W
    GFS Master的修改操作总是先记录操作日志,然后修改内存。当Master发生故障
    " L2 f2 g" L$ k0 N! D3 \( |  O重启时,可以通过磁盘中的操作日志恢复内存数据结构。另外,为了减少Master宕机
    9 B9 b  I) v2 T$ U恢复时间,Master会定期将内存中的数据以checkpoint文件的形式转储到磁盘中,从0 a2 u: d& R+ h' N5 S
    而减少回放的日志量。为了进一步提高Master的可靠性和可用性,GFS中还会执行实
    8 p0 ~8 R, H% J时热备,所有的元数据修改操作都必须保证发送到实时热备才算成功。远程的实时
    . n1 S( b! b* F) e- h热备将实时接收Master发送的操作日志并在内存中回放这些元数据操作。如果Master
    . \% ~' N5 q/ U" E/ \宕机,还可以秒级切换到实时备机继续提供服务。为了保证同一时刻只有一台+ d3 ^$ {" ~- Q
    Master,GFS依赖Google内部的Chubby服务进行选主操作。% j9 x# k% a1 ~
    Master需要持久化前两种元数据,即命名空间及文件到chunk之间的映射;对于
    " C/ q+ k, I8 ^' a3 _第三种元数据,即chunk副本的位置信息,Master可以选择不进行持久化,这是因为1 L* ]2 L0 a) a; G! r3 d
    ChunkServer维护了这些信息,即使Master发生故障,也可以在重启时通过0 s2 R" n3 b) J2 C
    ChunkServer汇报来获取。
    % |6 D# H  f* K(2)ChunkServer容错
    & m9 z0 ^4 K2 h( M1 W' Y, ?GFS采用复制多个副本的方式实现ChunkServer的容错,每个chunk有多个存储副
    $ i; j/ z, f* A7 h; d本,分别存储在不同的ChunkServer上。对于每个chunk,必须将所有的副本全部写入
    - v, Z% |6 `* @. A成功,才视为成功写入。如果相关的副本出现丢失或不可恢复的情况,Master自动将! j7 P$ }" d7 f  D
    副本复制到其他ChunkServer,从而确保副本保持一定的个数。' d9 _3 j4 s2 [2 I
    另外,ChunkServer会对存储的数据维持校验和。GFS以64MB为chunk大小来划分
      ^1 _# a- o# c  V. k文件,每个chunk又以Block为单位进行划分,Block大小为64KB,每个Block对应一个
    : o  |' E, L1 p& j! p' D32位的校验和。当读取一个chunk副本时,ChunkServer会将读取的数据和校验和进行
    3 i5 O+ Z$ h" m1 ?! i6 ?比较,如果不匹配,就会返回错误,客户端将选择其他ChunkServer上的副本。! D; c' r, g3 i; M' J" B
    4.1.3 Master设计6 Z. d% o7 s% P
    1.Master内存占用5 J2 p4 E6 _+ f0 C0 [( R
    Master维护了系统中的元数据,包括文件及chunk命名空间、文件到chunk之间的
    " {: m, W  N" e! j* ?/ S7 G映射、chunk副本的位置信息。其中前两种元数据需要持久化到磁盘,chunk副本的位/ E. g4 v6 ?9 a, @; e6 |, J
    置信息不需要持久化,可以通过ChunkServer汇报获取。2 W7 H: |. k+ V, C' N" f$ [
    内存是Master的稀有资源,接下来介绍如何估算Master的内存使用量。chunk的元
    6 c" a0 F- c. Q8 [! c信息包括全局唯一的ID、版本号、每个副本所在的ChunkServer编号、引用计数等。
    - x5 s* X4 f& {" M3 [5 W9 jGFS系统中每个chunk大小为64MB,默认存储3份,每个chunk的元数据小于64字节。  x1 N# D5 x, h+ m+ \0 F0 L# W5 F
    那么1PB数据的chunk元信息大小不超过1PB×3/64MB×64=3GB。另外,Master对命名
    ( [' [) K0 A; z0 u# A6 J空间进行了压缩存储,例如有两个文件foo1和foo2都存放在目
    # u& \% _4 S5 U$ Z1 J录/home/very_long_directory_name/中,那么目录名在内存中只需要存放一次。压缩存" a8 b# {' G9 e" T4 q+ x; A
    储后,每个文件在文件命名空间的元数据也不超过64字节,由于GFS中的文件一般都! k' a2 U8 v8 ^" @
    是大文件,因此,文件命名空间占用内存不多。这也就说明了Master内存容量不会成
    & L5 a& Y4 Z4 ^0 P为GFS的系统瓶颈。$ `: W# ]2 ^1 q- L
    2.负载均衡
    ' r( \5 u" }: g: ?3 l0 `0 n! DGFS中副本的分布策略需要考虑多种因素,如网络拓扑、机架分布、磁盘利用率5 Q. }. |1 L7 g, U$ l/ M) l
    等。为了提高系统的可用性,GFS会避免将同一个chunk的所有副本都存放在同一个
      H1 n0 O' a& J1 {机架的情况。
    $ ^9 G0 w' [; Y) c6 u系统中需要创建chunk副本的情况有三种:chunk创建、chunk复制(re-9 ]) A( p6 L5 Z: {, k) ^- a
    replication)以及负载均衡(rebalancing)。
    1 S8 s- R; K8 F* r0 t6 q当Master创建了一个chunk,它会根据如下因素来选择chunk副本的初始位置:1)
    ( M* f# i9 x4 W7 x3 n! W3 O4 w新副本所在的ChunkServer的磁盘利用率低于平均水平;2)限制每个Chunk-Server“最
    $ @+ k  m# m9 E0 @6 R近”创建的数量;3)每个chunk的所有副本不能在同一个机架。第二点容易忽略但却3 J! P- i0 u0 t# w, Q& Q
    很重要,因为创建完chunk以后通常需要马上写入数据,如果不限制“最近”创建的数2 k, p5 ?  ?6 A2 @
    量,当一台空的ChunkServer上线时,由于磁盘利用率低,可能导致大量的chunk瞬间  Y  j: j  U0 K  M7 K1 h$ f
    迁移到这台机器从而将它压垮。
    $ O8 n" F. {' r0 x6 E当chunk的副本数量小于一定的数量后,Master会尝试重新复制一个chunk副本。
    2 W# [6 U. z  I8 y8 m5 i4 o3 }9 k可能的原因包括ChunkServer宕机或者ChunkServer报告自己的副本损坏,或者4 j. L% t% v, _% r4 r
    ChunkServer的某个磁盘故障,或者用户动态增加了chunk的副本数,等等。每个chunk
    ; N8 Y/ n: W* ^3 j! J" E复制任务都有一个优先级,按照优先级从高到低在Master排队等待执行。例如,只有6 J" G/ N0 H% j# Y
    一个副本的chunk需要优先复制。另外,GFS会提高所有阻塞客户端操作的chunk复制( K, Q# q1 s: W$ u; f  h4 F
    任务的优先级,例如客户端正在往一个只有一个副本的chunk追加数据,如果限制至
    ( ~/ ]# y2 W: {1 \少需要追加成功两个副本,那么这个chunk复制任务会阻塞客户端写操作,需要提高
    4 Z* G+ d# e/ i  I$ d* |优先级。
    4 t) |7 p$ n0 i7 s. s, H$ y最后,Master会定期扫描当前副本的分布情况,如果发现磁盘使用量或者机器负6 j( f8 a- k5 X, t- @; ?1 w
    载不均衡,将执行重新负载均衡操作。
    # ~& n' t9 f3 S无论是chunk创建,chunk重新复制,还是重新负载均衡,这些操作选择chunk副本, ?4 f) V" {4 m' Q; L
    位置的策略都是相同的,并且需要限制重新复制和重新负载均衡任务的拷贝速度,5 W: W( u& o9 U; Y$ R% ?
    否则可能影响系统正常的读写服务。% ?: l/ e0 }' m
    3.垃圾回收
    . u4 k9 H3 ]8 V' f& PGFS采用延迟删除的机制,也就是说,当删除文件后,GFS并不要求立即归还可& t: u4 o, }) d0 v. ~4 O
    用的物理存储,而是在元数据中将文件改名为一个隐藏的名字,并且包含一个删除! U; S! U+ ?+ v1 H& ?4 f7 y
    时间戳。Master定时检查,如果发现文件删除超过一段时间(默认为3天,可配
    . ?- d5 D  E$ ^' M; Y- k置),那么它会把文件从内存元数据中删除,以后ChunkServer和Master的心跳消息7 w/ M  O9 D3 S, k
    中,每一个ChunkServer都将报告自己的chunk集合,Master会回复在Master元数据中
    0 q/ |2 X: |) z9 B0 p4 e. i  }3 D已经不存在的chunk信息,这时,ChunkServer会释放这些chunk副本。为了减轻系统的: M3 I& j$ v) f+ O! o; I- g
    负载,垃圾回收一般在服务低峰期执行,比如每天晚上凌晨1:00开始。! Y" T- \2 q* `
    另外,chunk副本可能会因为ChunkServer失效期间丢失了对chunk的修改操作而导
      G8 \5 f1 _* K致过期。系统对每个chunk都维护了版本号,过期的chunk可以通过版本号检测出来。
    + k! k  t  T. {* r! _Master仍然通过正常的垃圾回收机制来删除过期的副本。
    ' x% T" g" b. I0 J+ z4.快照# A, A7 o8 F/ N
    快照(Snapshot)操作是对源文件/目录进行一个“快照”操作,生成该时刻源文  B4 }! W" L% V1 ~% n
    件/目录的一个瞬间状态存放于目标文件/目录中。GFS中使用标准的写时复制机制生
    * b3 V& b1 k# j; U$ t1 f9 p成快照,也就是说,“快照”只是增加GFS中chunk的引用计数,表示这个chunk被快照) f" l; C6 W) }. t7 N+ J! N
    文件引用了,等到客户端修改这个chunk时,才需要在ChunkServer中拷贝chunk的数据
      k4 X7 `7 i4 c+ r生成新的chunk,后续的修改操作落到新生成的chunk上。
    * q. K  B/ o7 t- K为了对某个文件做快照,首先需要停止这个文件的写服务,接着增加这个文件
    5 a% @' E: T& ^8 P的所有chunk的引用计数,以后修改这些chunk时会拷贝生成新的chunk。对某个文件执
    : D% l9 r2 f! ]5 o+ H% ~0 X" d行快照的大致步骤如下:
    & {) C* R! Y6 A) f9 n1)通过租约机制收回对文件的每个chunk写权限,停止对文件的写服务;
    % x9 g" _0 |7 q, ?& n! v, B2)Master拷贝文件名等元数据生成一个新的快照文件;& K7 G9 O% H/ `! K1 e/ r
    3)对执行快照的文件的所有chunk增加引用计数。# |# q8 r  H$ [, @* W
    例如,对文件foo执行快照操作生成foo_backup,foo在GFS中有三个chunk:C1、C2+ {6 ]5 T9 [% b6 Q: N: _) O8 k( A' e
    和C3(简单起见,假设每个chunk只有一个副本)。Master首先需要收回C1、C2和C3
    * o! D0 a( N- m6 H的写租约,从而保证文件foo处于一致的状态,接着Master复制foo文件的元数据用于
    ; x( T0 N/ x! R7 P生成foo_backup,foo_backup同样指向C1、C2和C3。快照前,C1、C2和C3只被一个文
    * s0 {$ N/ o$ h+ U. _' `& R7 Q件foo引用,因此引用计数为1;执行快照操作后,这些chunk的引用计数增加为2。以
    8 D& e# f6 K% y" [- _3 ]后客户端再次向C3追加数据时,Master发现C3的引用计数大于1,通知C3所在的
    / V+ w* ?" i  ~9 x1 M  xChunkServer本次拷贝C3生成C3',客户端的追加操作也相应地转向C3'。- n/ G7 u& w; a3 P- b4 D8 D! {8 [
    4.1.4 ChunkServer设计" {+ e) O8 {6 n1 k" ?2 y
    ChunkServer管理大小约为64MB的chunk,存储的时候需要保证chunk尽可能均匀5 R; b2 f& y/ Z$ Y0 G% l0 X8 [
    地分布在不同的磁盘之中,需要考虑的可能因素包括磁盘空间、最近新建chunk数; z/ [% a* [+ m3 c( z% _) {+ x
    等。另外,Linux文件系统删除64MB大文件消耗的时间太长且没有必要,因此,删除4 b" Y$ K9 h# k2 _
    chunk时可以只将对应的chunk文件移动到每个磁盘的回收站,以后新建chunk的时候可1 W" L3 K) @- p
    以重用。
    ! Y% f4 R2 y" s, s; A% d; J; O/ EChunkServer是一个磁盘和网络IO密集型应用,为了最大限度地发挥机器性能,
    , Z' p3 x; B5 E. D& K# s+ L需要能够做到将磁盘和网络操作异步化,但这会增加代码实现的难度。" a+ \" r6 ?; P+ ]4 H
    4.1.5 讨论
    ( I2 D4 t2 N. k6 O从GFS的架构设计可以看出,GFS是一个具有良好可扩展性并能够在软件层面自' m: z5 P5 y. z/ o# k# l
    动处理各种异常情况的系统。Google是一家很重视自动化的公司,从早期的GFS,再
    % N/ w- Z; z) U9 e3 e到Bigtable、Megastore,以及最近的Spanner,Google的分布式存储系统在这一点上一脉) `1 {7 q4 O, o$ q2 }5 K& F/ c4 L
    相承。由于Google的系统一开始能很好地解决可扩展性问题,所以后续的系统能够
    + E3 r% D, s* {- F( {/ b构建在前一个系统之上并且一步一步引入新的功能,如Bigtable在GFS之上将海量数
    1 h' h8 W; Y! o0 V9 j  n+ M# |据组织成表格形式,Megastore、Spanner又进一步在Bigtable之上融合一些关系型数据
    & ^! K  ~- S5 N$ P% O库的功能,整个解决方案完美华丽。
    1 ]$ `( d9 n/ |8 C- Y& b. y  {* Y自动化对系统的容错能力提出了很高的要求,在设计GFS时认为节点失效是常
    ) l& B  R  \: H6 f态,通过在软件层面进行故障检测,并且通过chunk复制操作将原有故障节点的服务: i* k5 \2 ~( ~$ K
    迁移到新的节点。系统还会根据一定的策略,如磁盘使用情况、机器负载等执行负
    , C2 g) l. C8 c! {3 }0 e5 n载均衡操作。Google在软件层面的努力获得了巨大的回报,由于软件层面能够做到  T1 C/ B. q: Q' n
    自动化容错,底层的硬件可以采用廉价的错误率较高的硬件,比如廉价的SATA盘,, y4 D1 T2 I; t: d; |- }2 w
    这大大降低了云服务的成本,在和其他厂商的竞争中表现出价格优势。比较典型的
    9 f) `& J, ], d7 a) ?0 j1 f例子就是Google的邮箱服务,由于基础设施成本低,Gmail服务能够免费给用户提供
    ; p* Z8 @/ \- W6 H3 M' O更大的容量,令其他厂商望尘莫及。2 U) o( i9 u+ w- ]: x: ?
    Google的成功经验也表明了一点:单Master的设计是可行的。单Master的设计不0 b: H  L  r0 Y* a4 A# n
    仅简化了系统,而且能够较好地实现一致性,后面我们将要看到的绝大多数分布式8 e* H6 l) r2 Q! a7 q3 B6 ^
    存储系统都和GFS一样依赖单总控节点。然而,单Master的设计并不意味着实现GFS
    : E) G8 |# n+ @/ _( \% J0 e只是一些比较简单琐碎的工作。基于性能考虑,GFS提出了“记录至少原子性追加一
    " F$ S4 ~4 H7 N: w( N$ ^5 V, R次”的一致性模型,通过租约的方式将每个chunk的修改授权下放到ChunkServer从而减
      C- |, a% o3 N6 h少Master的负载,通过流水线的方式复制多个副本以减少延时,追加流程复杂繁琐。- H. n+ r# ^4 }) D
    另外,Master维护的元数据有很多,需要设计高效的数据结构,占用内存小,并且能/ i3 @; u% L& Q  K, Y( g
    够支持快照操作。支持写时复制的B树能够满足Master的元数据管理需求,然而,它) G) N8 Y' s& i! E$ E
    的实现是相当复杂的。
    / v: B; a5 O) O  c8 e4 x. f5 l4 |0 Z) m0 L7 m1 e5 j  N  m; D
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-1 14:23 , Processed in 0.162673 second(s), 27 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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