java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2441|回复: 0

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

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

    [LV.Master]出神入化

    2040

    主题

    3698

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66476

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

    发表于 2017-3-3 20:20:23 | 显示全部楼层 |阅读模式
    分布式文件系统的主要功能有两个:一个是存储文档、图像、视频之类的Blob# e0 @8 s$ r1 {, c8 a( w
    类型数据;另外一个是作为分布式表格系统的持久化层。; F4 N6 g/ Y9 t% O. p) h
    分布式文件系统中最为著名的莫过于Google File System(GFS),它构建在廉价
    ) I/ _8 p5 p9 A1 O* `. E+ U的普通PC服务器之上,支持自动容错。GFS内部将大文件划分为大小约为64MB的数
    + a8 P4 e& w5 |% g  i6 ~1 \据块(chunk),并通过主控服务器(Master)实现元数据管理、副本管理、自动负
    2 U) ]& D  K+ }$ J( F+ \载均衡等操作。其他文件系统,例如Taobao File System(TFS)、Facebook Haystack& y0 l5 p; o, j- I5 B8 U
    或多或少借鉴了GFS的思路,架构上都比较相近。
    # R  N8 j  `2 N4 m3 M0 K, b$ ^2 h本章首先重点介绍GFS的内部实现机制,接着介绍TFS和Face book Haystack的内9 _4 c" t9 f! V
    部实现。最后,本章还会简单介绍内容分发网络(Content Delivery Network,CDN)技5 H8 r' z# w5 _+ Y
    术,这种技术能够将图像、视频之类的数据缓存在离用户“最近”的网络节点上,从
    # s" P2 g7 |4 s( |% w, {+ }/ l9 H而降低访问延时,节省带宽。8 K/ q4 e' q: A: c; s
    4.1 Google文件系统" g6 Q( E! ^9 N, Z# _& [
    Google文件系统(GFS)是构建在廉价服务器之上的大型分布式系统。它将服务
    6 p1 o+ m- v, u! Q5 C5 A2 P  h( S器故障视为正常现象,通过软件的方式自动容错,在保证系统可靠性和可用性的同5 s5 A3 `6 c+ I# D
    时,大大降低系统的成本。& a8 O6 z" h3 d. `1 T
    GFS是Google分布式存储的基石,其他存储系统,如Google Bigtable、Google, n! r! ^0 @+ }' U
    Megastore、Google Percolator均直接或者间接地构建在GFS之上。另外,Google大规% y8 g) l6 z2 @4 S& b4 R$ z
    模批处理系统MapReduce也需要利用GFS作为海量数据的输入输出。9 x% F7 H' t6 F( x; E1 @
    4.1.1 系统架构2 b1 W5 k4 P4 n! ^0 z5 ~
    如图4-1所示,GFS系统的节点可分为三种角色:GFS Master(主控服务器)、
    + h2 n1 z; J3 V" |( UGFS ChunkServer(CS,数据块服务器)以及GFS客户端。
    ' d' }% x7 J( ^, w0 v2 y" z图 4-1 GFS整体架构
    & |1 {9 x. O# }' E; w* CGFS文件被划分为固定大小的数据块(chunk),由主服务器在创建时分配一个
    / {" X% o, x' b2 l' n# Z% q6 q64位全局唯一的chunk句柄。CS以普通的Linux文件的形式将chunk存储在磁盘中。为, H% T% P6 J" a
    了保证可靠性,chunk在不同的机器中复制多份,默认为三份。
    7 [, ^8 |  Q! M5 n# `1 t& X: |; b主控服务器中维护了系统的元数据,包括文件及chunk命名空间、文件到chunk之5 X  W  l$ p& w2 ~$ t+ J
    间的映射、chunk位置信息。它也负责整个系统的全局控制,如chunk租约管理、垃圾
    9 T+ @9 G# A/ S3 n7 K; e% c回收无用chunk、chunk复制等。主控服务器会定期与CS通过心跳的方式交换信息。  p! h; y2 E- G9 @9 O& V
    客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规8 p, _) E) S. N1 s; H3 s5 X
    范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之$ I7 Y3 r% `. r( \) J, v1 t2 {5 Q% s! @6 m
    进行交互的CS信息,然后直接访问这些CS,完成数据存取工作。* u4 U$ [' F% W/ J
    需要注意的是,GFS中的客户端不缓存文件数据,只缓存主控服务器中获取的元$ h5 c; [. _: n. f3 |# l
    数据,这是由GFS的应用特点决定的。GFS最主要的应用有两个:MapReduce与4 P2 q+ k  z8 I2 I. R0 m
    Bigtable。对于MapReduce,GFS客户端使用方式为顺序读写,没有缓存文件数据的必$ [0 w' ?( |# Z$ ?/ o! e4 ?
    要;而Bigtable作为分布式表格系统,内部实现了一套缓存机制。另外,如何维护客
    / q. {, \* q' h户端缓存与实际数据之间的一致性是一个极其复杂的问题。
    ' p7 P' H" r: Y' A6 H4.1.2 关键问题
    0 x6 I3 Q1 ^' x1.租约机制8 e8 T- @) ]4 l: Y" i: u; u5 S  Z  B, z
    GFS数据追加以记录为单位,每个记录的大小为几十KB到几MB不等,如果每次
    * P" S  a9 i! n记录追加都需要请求Master,那么Master显然会成为系统的性能瓶颈,因此,GFS系6 R. G" q1 G4 V' o2 |: T) e
    统中通过租约(lease)机制将chunk写操作授权给ChunkServer。拥有租约授权的
    % a8 _! W1 V/ yChunkServe称为主ChunkServer,其他副本所在的ChunkServer称为备ChunkServer。租
    1 D+ _. q- a4 c, {约授权针对单个chunk,在租约有效期内,对该chunk的写操作都由主ChunkServer负
    + z( Z9 N- |7 q" e* K责,从而减轻Master的负载。一般来说,租约的有效期比较长,比如60秒,只要没有8 Z3 ?7 ~* S1 J
    出现异常,主ChunkServer可以不断向Master请求延长租约的有效期直到整个chunk写
    . D9 N, f& |* R1 K6 h# [  f满。
    5 m7 V$ x; v5 F) }; t, c假设chunk A在GFS中保存了三个副本A1、A2、A3,其中,A1是主副本。如果副; X6 M7 y3 _6 ]5 @; c5 }! ]
    本A2所在ChunkServer下线后又重新上线,并且在A2下线的过程中,副本A1和A3有
    $ }  S$ b: a4 I& s& l6 ?- R# E. p3 d更新,那么A2需要被Master当成垃圾回收掉。GFS通过对每个chunk维护一个版本号
    & Z+ B. T& q3 F9 J! B* `) ], q来解决,每次给chunk进行租约授权或者主ChunkServer重新延长租约有效期时,8 x* K3 [! M( [
    Master会将chunk的版本号加1。A2下线的过程中,副本A1和A3有更新,说明主3 L' q' x7 O+ s+ d' W
    ChunkServer向Master重新申请租约并增加了A1和A3的版本号,等到A2重新上线后,
    3 j7 ~* w  x$ qMaster能够发现A2的版本号太低,从而将A2标记为可删除的chunk,Master的垃圾回收) P6 P0 W8 ?3 m% y% c8 r
    任务会定时检查,并通知ChunkServer将A2回收掉。/ v, E" N6 }$ _# ?0 T' D! f
    2.一致性模型: Q9 D% O' O; b' ^, Y# m- P
    GFS主要是为了追加(append)而不是改写(overwrite)而设计的。一方面是因
    " h/ T3 e5 |/ L为改写的需求比较少,或者可以通过追加来实现,比如可以只使用GFS的追加功能构
    7 s' n0 N. u3 m) X: s( C' C建分布式表格系统Bigtable;另一方面是因为追加的一致性模型相比改写要更加简单
    ; t! g  a- h6 y/ Q( Z有效。考虑chunk A的三个副本A1、A2、A3,有一个改写操作修改了A1、A2但没有9 W7 i! A/ \; l
    修改A3,这样,落到副本A3的读操作可能读到不正确的数据;相应地,如果有一个
    ' d! r1 L0 C+ ?/ E: r! T0 Y追加操作往A1、A2上追加了一个记录,但是追加A3失败,那么即使读操作落到副本
    % S" R- t: [- }8 `: ]9 H$ wA3也只是读到过期而不是错误的数据。
    : D, P- y2 C3 n我们只讨论追加的一致性。如果不发生异常,追加成功的记录在GFS的各个副本
    ! B. [# N! f# Z" l1 a) ]$ g5 K8 U中是确定并且严格一致的;但是如果出现了异常,可能出现某些副本追加成功而某
    ( a4 W  m2 v2 I  P/ }/ E些副本没有成功的情况,失败的副本可能会出现一些可识别的填充(padding)记
    # v0 ~2 T' y# r/ b" e0 @- W录。GFS客户端追加失败将重试,只要返回用户追加成功,说明在所有副本中都至少
    7 i$ D' L3 L3 d7 |3 |0 ~) B追加成功了一次。当然,可能出现记录在某些副本中被追加了多次,即重复记录;
    7 q: M& r( e1 t' A也可能出现一些可识别的填充记录,应用层需要能够处理这些问题。( ~+ a, u" v& w& Z
    另外,由于GFS支持多个客户端并发追加,多个客户端之间的顺序是无法保证  H) `5 k( o4 G5 u2 c
    的,同一个客户端连续追加成功的多个记录也可能被打断,比如客户端先后追加成
    1 ?" J2 l* V2 ^& Q7 g4 ~4 @功记录R1和R2,由于追加R1和R2这两条记录的过程不是原子的,中途可能被其他客1 q6 i/ b6 b" o
    户端打断,那么GFS的chunk中记录的R1和R2可能不连续,中间夹杂着其他客户端追; e1 p5 n5 {& i
    加的数据。5 S. t0 u+ w1 Y. _+ B8 X6 g( M
    GFS的这种一致性模型是追求性能导致的,这增加了应用程序开发的难度。对于# e' P, Q0 P8 N1 Q9 g
    MapReduce应用,由于其批处理特性,可以先将数据追加到一个临时文件,在临时文
    2 L, l7 w/ Y' I件中维护索引记录每个追加成功的记录的偏移,等到文件关闭时一次性将临时文件
      |/ I" x6 P8 n改名为最终文件。对于上层的Bigtable,有两种处理方式,后面将会介绍。: [! M7 B) o0 O8 B% c+ I- y
    3.追加流程# f( L  O+ t  @' Y
    追加流程是GFS系统中最为复杂的地方,而且,高效支持记录追加对基于GFS实
    ( Z/ Q, ~; S& N" N( y. S/ x; L现的分布式表格系统Bigtable是至关重要的。如图4-2所示,追加流程大致如下:
    ' Z$ g& a/ L5 ]- T图 4-2 GFS追加流程; @3 l/ m+ ]! `6 Y4 R6 z( k3 f
    1)客户端向Master请求chunk每个副本所在的ChunkServer,其中主ChunkServer持/ t8 F5 q1 o, t8 T
    有修改租约。如果没有ChunkServer持有租约,说明该chunk最近没有写操作,Master3 M( R; x8 h# u, e
    会发起一个任务,按照一定的策略将chunk的租约授权给其中一台ChunkServer。# ?6 u( _7 t; P/ K" c; y
    2)Master返回客户端主副本和备副本所在的ChunkServer的位置信息,客户端将
    - r/ }8 Y2 D: N9 f; S缓存这些信息供以后使用。如果不出现故障,客户端以后读写该chunk都不需要再次% `  F2 f# a0 F+ F
    请求Master。
    9 `3 q. f, s% w: a8 h6 ^6 n( G1 `3)客户端将要追加的记录发送到每一个副本,每一个ChunkServer会在内部的( U. v3 l# |% V) W, E3 {6 ~
    LRU结构中缓存这些数据。GFS中采用数据流和控制流分离的方法,从而能够基于网7 k" K7 I% l; H$ W
    络拓扑结构更好地调度数据流的传输。. t  N3 }) H6 C5 H
    4)当所有副本都确认收到了数据,客户端发起一个写请求控制命令给主副本。
    ; p! b5 l4 f- ^0 g" u* I, |( p由于主副本可能收到多个客户端对同一个chunk的并发追加操作,主副本将确定这些
    ) [* R5 }1 _" M操作的顺序并写入本地。
    6 e+ [& Z* x1 ^2 c! K$ s5)主副本把写请求提交给所有的备副本。每一个备副本会根据主副本确定的顺
    + z2 ?* M8 y6 e) ~. a# |3 h& R序执行写操作。
    ; g) b! X  o5 |0 {+ g2 ]6)备副本成功完成后应答主副本。
    ; F5 ^6 o, }8 |3 x. A# p7 f7)主副本应答客户端,如果有副本发生错误,将出现主副本写成功但是某些备
    : M7 E6 Y6 x, _: l' f副本不成功的情况,客户端将重试。
    ! J+ ]) a; [" t/ CGFS追加流程有两个特色:流水线及分离数据流与控制流。流水线操作用来减少  @  s$ N5 y8 y( s
    延时。当一个ChunkServer接收到一些数据,它就立即开始转发。由于采用全双工网( q, P& J6 i0 m- w% W7 r3 X
    络,立即发送数据并不会降低接收数据的速率。抛开网络阻塞,传输B个字节到R个
    ; r& }0 ?) M0 m! Z+ R副本的理想时间是B/T+RL,其中T是网络吞吐量,L是节点之间的延时。假设采用千
    - Y( ]$ a6 @6 w/ w8 @兆网络,L通常小于1ms,传输1MB数据到多个副本的时间小于80ms。分离数据流与
    3 a) @! n; }5 Z控制流主要是为了优化数据传输,每一台机器都是把数据发送给网络拓扑图上“最$ A9 I; r7 u3 w2 H+ J% y2 B2 y
    近”的尚未收到数据的数据。举个例子,假设有三台ChunkServer:S1、S2和S3,S1与
    / Q3 m: e$ G. s5 `% j% e! hS3在同一个机架上,S2在另外一个机架上,客户端部署在机器S1上。如果数据先从2 @6 K# A. ~5 u; p7 i+ X% t4 P
    S1转发到S2,再从S2转发到S3,需要经历两次跨机架数据传输;相对地,按照GFS
    & B. D7 n) _6 }& L  _( h1 {0 I中的策略,数据先发送到S1,接着从S1转发到S3,最后转发到S2,只需要一次跨机
    # h" h; u6 s6 U( t: f0 A0 ^' G' c! N架数据传输。
    & |9 N, s/ \; F7 K+ N" W: o7 @分离数据流与控制流的前提是每次追加的数据都比较大,比如MapReduce批处理; z! F& o% W; T5 W/ M
    系统,而且这种分离增加了追加流程的复杂度。如果采用传统的主备复制方法,追
    : G/ W& i* a3 \6 e加流程会在一定程度上得到简化,如图4-3所示:
    9 y, y0 {6 R/ O# @$ `图 4-3 GFS追加流程(数据流与控制流合并)" D$ _! A( ?4 A/ W( X! ?8 s( T
    1)同图4-2 GFS追加流程:客户端向Master请求chunk每个副本所在的
    8 ~' [$ k4 l/ k7 S  K8 {& DChunkServer。9 _  Q% V; Z/ y" {$ J
    2)同图4-2 GFS追加流程:Master返回客户端主副本和备副本所在ChunkServer的
    6 }/ X1 U. R1 B6 G% k5 P位置信息。5 I* N4 @  a6 O( ~5 a
    3)Client将待追加数据发送到主副本,主副本可能收到多个客户端的并发追加
    + d/ n, O+ [2 T* D6 Z1 A请求,需要确定操作顺序,并写入本地。1 o$ M4 e, T% J, ^: x7 m
    4)主副本将数据通过流水线的方式转发给所有的备副本。
    # ?1 w0 S9 b. ~1 \( z$ ]$ d9 [5)每个备副本收到待追加的记录数据后写入本地,所有副本都在本地写成功并, g$ x, u/ ~' z) i9 ~) [
    且收到后一个副本的应答消息时向前一个副本回应,比如图4-3中备副本A需要等待
    ' V! K8 ]% D, U+ c备副本B应答成功且本地写成功后才可以应答主副本。3 O5 F* f, W, ^' U' r! a
    6)主副本应答客户端。如果客户端在超时时间之内没有收到主副本的应答,说
    - F6 N- @; \' t9 j明发生了错误,需要重试。
    $ t; R5 M) W% k* Y1 O  K( z当然,实际的追加流程远远没有这么简单。追加的过程中可能出现主副本租约9 ~/ S( \$ j  {- e" l, u4 j
    过期而失去chunk修改操作的授权,以及主副本或者备副本所在的ChunkServer出现故
    / M1 v: W6 u& v障,等等。由于篇幅有限,追加流程的异常处理留作读者思考。
    ) u! R6 }8 ~! y% |3 N4.容错机制" j: [* r- N6 s* D; C. e2 S; [5 W
    (1)Master容错; V" P& a( L; ^4 {; `# l/ q
    Master容错与传统方法类似,通过操作日志加checkpoint的方式进行,并且有一5 G  C* f  Q- B" a! k
    台称为"Shadow Master"的实时热备。2 A6 S4 G  f* K8 R/ u
    Master上保存了三种元数据信息:
    2 O5 i  W6 B! A$ N3 A$ J●命名空间(Name Space),也就是整个文件系统的目录结构以及chunk基本信( w+ n2 ?+ u( S
    息;4 Y2 I& q; b/ M) S* o4 N6 i0 j( y
    ●文件到chunk之间的映射;
    " @/ v4 K& I; i●chunk副本的位置信息,每个chunk通常有三个副本。
    & Q- J: q. X8 N+ E1 P# W% EGFS Master的修改操作总是先记录操作日志,然后修改内存。当Master发生故障
    / V7 a5 Z" v) ^# p) G* B9 z6 r重启时,可以通过磁盘中的操作日志恢复内存数据结构。另外,为了减少Master宕机' O( M6 u' u/ q0 D0 d
    恢复时间,Master会定期将内存中的数据以checkpoint文件的形式转储到磁盘中,从- l& |% I  p3 I; a
    而减少回放的日志量。为了进一步提高Master的可靠性和可用性,GFS中还会执行实% E( h, o  T! y) o+ k
    时热备,所有的元数据修改操作都必须保证发送到实时热备才算成功。远程的实时
    # j2 z. ]! b* K! _* f' X& b- p% B热备将实时接收Master发送的操作日志并在内存中回放这些元数据操作。如果Master
    ' @+ a$ j( J" ~8 Q8 V宕机,还可以秒级切换到实时备机继续提供服务。为了保证同一时刻只有一台, {9 f+ `9 V) j  Z0 C
    Master,GFS依赖Google内部的Chubby服务进行选主操作。
    & ^6 ?# |8 p9 y* MMaster需要持久化前两种元数据,即命名空间及文件到chunk之间的映射;对于
    , d6 `, h* p; \$ ]第三种元数据,即chunk副本的位置信息,Master可以选择不进行持久化,这是因为
    % k# G! S/ m  F* j# oChunkServer维护了这些信息,即使Master发生故障,也可以在重启时通过: j, Z5 o8 l* q1 `8 G: R
    ChunkServer汇报来获取。
    : N/ I+ v+ U% j! g+ @& q(2)ChunkServer容错6 k: b" y* R) c* H( A6 K
    GFS采用复制多个副本的方式实现ChunkServer的容错,每个chunk有多个存储副
    ) B: |# }* \9 N4 p$ [! j# |  m本,分别存储在不同的ChunkServer上。对于每个chunk,必须将所有的副本全部写入
    8 x+ T; y/ K; X! l4 Z  x成功,才视为成功写入。如果相关的副本出现丢失或不可恢复的情况,Master自动将5 K6 j# t; l8 G; j* @& \
    副本复制到其他ChunkServer,从而确保副本保持一定的个数。1 j# s: ^1 T# i* r, @
    另外,ChunkServer会对存储的数据维持校验和。GFS以64MB为chunk大小来划分0 N* d. Q, c( N$ z- z3 x
    文件,每个chunk又以Block为单位进行划分,Block大小为64KB,每个Block对应一个
    * ~- E+ H9 S+ s32位的校验和。当读取一个chunk副本时,ChunkServer会将读取的数据和校验和进行; X9 G! Z1 U2 A/ Z/ k3 y- j0 ^
    比较,如果不匹配,就会返回错误,客户端将选择其他ChunkServer上的副本。
    5 E& H* [  R+ k& v- }, Y4.1.3 Master设计$ u. ^% y& r  H! v
    1.Master内存占用
    7 y/ C- h$ S$ G# D0 t4 G" cMaster维护了系统中的元数据,包括文件及chunk命名空间、文件到chunk之间的6 w* f+ ^; t3 B/ a
    映射、chunk副本的位置信息。其中前两种元数据需要持久化到磁盘,chunk副本的位
    - g& s& q, o  ^5 w, s, s; |置信息不需要持久化,可以通过ChunkServer汇报获取。9 S0 p+ b9 [3 {2 f  X# z
    内存是Master的稀有资源,接下来介绍如何估算Master的内存使用量。chunk的元+ S5 s' C5 @2 i) u; Y! K& i" J6 T
    信息包括全局唯一的ID、版本号、每个副本所在的ChunkServer编号、引用计数等。
    . f" X9 \* Z* i2 B6 C% o" ^GFS系统中每个chunk大小为64MB,默认存储3份,每个chunk的元数据小于64字节。
    + n7 i2 u0 G/ U0 I7 M/ D4 c% [那么1PB数据的chunk元信息大小不超过1PB×3/64MB×64=3GB。另外,Master对命名
    ! M7 T9 O$ Z, h6 N1 L空间进行了压缩存储,例如有两个文件foo1和foo2都存放在目
    & o. l) f( D0 U# E录/home/very_long_directory_name/中,那么目录名在内存中只需要存放一次。压缩存1 a& l& l" z$ F7 d. y: b
    储后,每个文件在文件命名空间的元数据也不超过64字节,由于GFS中的文件一般都7 W* C+ l9 M+ Q
    是大文件,因此,文件命名空间占用内存不多。这也就说明了Master内存容量不会成
    . |8 n3 |* p# `+ T2 k- J为GFS的系统瓶颈。7 y  z( P9 O$ z% v  B2 [
    2.负载均衡$ \9 |/ Z& d& ?' c9 P3 m: V- x
    GFS中副本的分布策略需要考虑多种因素,如网络拓扑、机架分布、磁盘利用率* d. C: l& `. J9 G% Q- U, \! B
    等。为了提高系统的可用性,GFS会避免将同一个chunk的所有副本都存放在同一个/ e4 q' w1 e- K$ R8 N& A
    机架的情况。9 N% L& \9 C. g; }% J1 x/ F
    系统中需要创建chunk副本的情况有三种:chunk创建、chunk复制(re-: o9 f. y, H& b9 N: Q9 s
    replication)以及负载均衡(rebalancing)。' T- ?/ u# }+ n! O- v/ ]0 u
    当Master创建了一个chunk,它会根据如下因素来选择chunk副本的初始位置:1)
    2 {( |5 q' R" f3 _& h新副本所在的ChunkServer的磁盘利用率低于平均水平;2)限制每个Chunk-Server“最
    , |- Q: _& g4 I: @近”创建的数量;3)每个chunk的所有副本不能在同一个机架。第二点容易忽略但却5 s" C/ q9 y- P2 n0 G, @: ?5 B( r1 h
    很重要,因为创建完chunk以后通常需要马上写入数据,如果不限制“最近”创建的数
    . l$ u1 X/ P( i5 }; j6 i3 q: s量,当一台空的ChunkServer上线时,由于磁盘利用率低,可能导致大量的chunk瞬间
    5 Z+ Y; |! C( D* M7 o迁移到这台机器从而将它压垮。, E& Y1 J+ T) h+ Z
    当chunk的副本数量小于一定的数量后,Master会尝试重新复制一个chunk副本。% f) u% ?7 L5 }$ R, b' b0 g( k
    可能的原因包括ChunkServer宕机或者ChunkServer报告自己的副本损坏,或者
    0 ?" K# ?# w1 v) Z! D5 U/ \9 ]2 jChunkServer的某个磁盘故障,或者用户动态增加了chunk的副本数,等等。每个chunk
    7 f. _" U" ]8 E' z& u3 p* _复制任务都有一个优先级,按照优先级从高到低在Master排队等待执行。例如,只有
    ! P2 b* D4 k* _5 b" u一个副本的chunk需要优先复制。另外,GFS会提高所有阻塞客户端操作的chunk复制6 c$ m, }3 q; L
    任务的优先级,例如客户端正在往一个只有一个副本的chunk追加数据,如果限制至
    , `2 h+ a0 m" o2 x& @; y: p" a: M少需要追加成功两个副本,那么这个chunk复制任务会阻塞客户端写操作,需要提高
    % t1 w5 M4 j4 f9 P) E' m优先级。
    + P7 A% x3 M8 @3 ]7 K. {最后,Master会定期扫描当前副本的分布情况,如果发现磁盘使用量或者机器负
    & T$ J' f  {7 w载不均衡,将执行重新负载均衡操作。
    / q2 l1 ^; O/ y* L7 E0 i' Y! V无论是chunk创建,chunk重新复制,还是重新负载均衡,这些操作选择chunk副本+ [) J+ {" R; w4 j; {. X3 [
    位置的策略都是相同的,并且需要限制重新复制和重新负载均衡任务的拷贝速度,
    , W8 q9 O5 A1 g; B2 F3 g" u8 y' x否则可能影响系统正常的读写服务。
    8 @. }2 E- w4 m$ S% `1 \. }3.垃圾回收+ \! \: N1 B" b: w- C
    GFS采用延迟删除的机制,也就是说,当删除文件后,GFS并不要求立即归还可: s' X5 J# t6 U
    用的物理存储,而是在元数据中将文件改名为一个隐藏的名字,并且包含一个删除+ v6 s& n. b3 j8 K/ q0 u
    时间戳。Master定时检查,如果发现文件删除超过一段时间(默认为3天,可配
    , `' t: [& J% L( x; W# Z置),那么它会把文件从内存元数据中删除,以后ChunkServer和Master的心跳消息4 S- A* @% v5 T) Z; y, U* J
    中,每一个ChunkServer都将报告自己的chunk集合,Master会回复在Master元数据中
    + c, Y' r: K* @; c  c7 }已经不存在的chunk信息,这时,ChunkServer会释放这些chunk副本。为了减轻系统的# u3 w$ b" D+ q( X1 C) e5 r
    负载,垃圾回收一般在服务低峰期执行,比如每天晚上凌晨1:00开始。
    - r6 ~2 [8 J" t5 A% v' m$ |另外,chunk副本可能会因为ChunkServer失效期间丢失了对chunk的修改操作而导
    $ q9 `+ e3 ?7 r) o2 G$ I致过期。系统对每个chunk都维护了版本号,过期的chunk可以通过版本号检测出来。1 G  w) ?# }* H. c
    Master仍然通过正常的垃圾回收机制来删除过期的副本。
    8 t+ e3 Z& m- Z4.快照
    8 }% @- l7 ?3 i) {/ e快照(Snapshot)操作是对源文件/目录进行一个“快照”操作,生成该时刻源文
    + v% ?' T, _3 V, @& a- {件/目录的一个瞬间状态存放于目标文件/目录中。GFS中使用标准的写时复制机制生" ?, V& u8 J0 L- p) _5 B
    成快照,也就是说,“快照”只是增加GFS中chunk的引用计数,表示这个chunk被快照4 o, _% Y: g- g# U3 H8 M
    文件引用了,等到客户端修改这个chunk时,才需要在ChunkServer中拷贝chunk的数据
    9 f# @  f2 Z& \1 R生成新的chunk,后续的修改操作落到新生成的chunk上。
    % z  }2 Q1 u9 O为了对某个文件做快照,首先需要停止这个文件的写服务,接着增加这个文件+ J" `3 z3 V# s
    的所有chunk的引用计数,以后修改这些chunk时会拷贝生成新的chunk。对某个文件执9 W0 f. f$ L3 n: X7 N+ V: v8 W
    行快照的大致步骤如下:7 b$ f4 i0 }) B/ [* d
    1)通过租约机制收回对文件的每个chunk写权限,停止对文件的写服务;
    ' T9 V1 K$ Q! `# ]+ G$ P2)Master拷贝文件名等元数据生成一个新的快照文件;8 Y5 |( S* m1 N0 ]+ G
    3)对执行快照的文件的所有chunk增加引用计数。7 y6 ^1 U' b8 ~# ?" L+ ^+ {% G6 V
    例如,对文件foo执行快照操作生成foo_backup,foo在GFS中有三个chunk:C1、C2+ u7 J" W- X/ e3 h
    和C3(简单起见,假设每个chunk只有一个副本)。Master首先需要收回C1、C2和C3$ v. [7 M. N* }5 ]- Z( ?$ B
    的写租约,从而保证文件foo处于一致的状态,接着Master复制foo文件的元数据用于
    * {  q* a2 S1 d; Y' W% z生成foo_backup,foo_backup同样指向C1、C2和C3。快照前,C1、C2和C3只被一个文
    . V* z7 L! Q! T- X  \( s* M件foo引用,因此引用计数为1;执行快照操作后,这些chunk的引用计数增加为2。以; c+ d# C3 e' G% A, [+ M" G
    后客户端再次向C3追加数据时,Master发现C3的引用计数大于1,通知C3所在的
    ' R# D$ E8 I  XChunkServer本次拷贝C3生成C3',客户端的追加操作也相应地转向C3'。7 k6 N$ D- l2 D  ?/ M! B; s
    4.1.4 ChunkServer设计7 S0 E* G: i3 M6 m: A( ?2 |
    ChunkServer管理大小约为64MB的chunk,存储的时候需要保证chunk尽可能均匀1 y/ r; @. f: {6 Q8 n
    地分布在不同的磁盘之中,需要考虑的可能因素包括磁盘空间、最近新建chunk数
    ( C) _0 a4 s& I: j/ |' w" j4 N! N等。另外,Linux文件系统删除64MB大文件消耗的时间太长且没有必要,因此,删除
      e  v% k1 R5 y0 Fchunk时可以只将对应的chunk文件移动到每个磁盘的回收站,以后新建chunk的时候可, H. f+ D9 p3 e( ?, W. ~  V
    以重用。
    ! I( y0 {$ k% z1 ]7 wChunkServer是一个磁盘和网络IO密集型应用,为了最大限度地发挥机器性能,
    % N5 O, }1 Y$ n* L% p8 c% `需要能够做到将磁盘和网络操作异步化,但这会增加代码实现的难度。! ?' m& h$ v& C
    4.1.5 讨论
    ; ~6 @+ B' w& s9 y7 P' q从GFS的架构设计可以看出,GFS是一个具有良好可扩展性并能够在软件层面自" g: j4 A" u) {! V1 V: L  a2 _
    动处理各种异常情况的系统。Google是一家很重视自动化的公司,从早期的GFS,再: O+ ~  `; o" i
    到Bigtable、Megastore,以及最近的Spanner,Google的分布式存储系统在这一点上一脉
    + i# y/ P" ^, E相承。由于Google的系统一开始能很好地解决可扩展性问题,所以后续的系统能够$ E3 X. N  G3 ?1 I
    构建在前一个系统之上并且一步一步引入新的功能,如Bigtable在GFS之上将海量数: A/ I- c% k( P! l& K
    据组织成表格形式,Megastore、Spanner又进一步在Bigtable之上融合一些关系型数据
    " o" ?; q1 ]/ M+ |8 L库的功能,整个解决方案完美华丽。
    8 S# p. o, y$ @5 ~0 }* y自动化对系统的容错能力提出了很高的要求,在设计GFS时认为节点失效是常# f$ B& h7 v+ S8 E3 C9 L/ }0 t
    态,通过在软件层面进行故障检测,并且通过chunk复制操作将原有故障节点的服务
    2 q. j- T; B! J) c% l% M. P迁移到新的节点。系统还会根据一定的策略,如磁盘使用情况、机器负载等执行负4 m  D8 U/ s3 t. A& j' S' R
    载均衡操作。Google在软件层面的努力获得了巨大的回报,由于软件层面能够做到) v/ u* L& k1 m5 r
    自动化容错,底层的硬件可以采用廉价的错误率较高的硬件,比如廉价的SATA盘,2 c6 O7 Q% E$ t1 y* Z
    这大大降低了云服务的成本,在和其他厂商的竞争中表现出价格优势。比较典型的2 v  d+ R! R! `* x- d: P: I
    例子就是Google的邮箱服务,由于基础设施成本低,Gmail服务能够免费给用户提供
    # V. `# {" P' ~9 M# R& o* i更大的容量,令其他厂商望尘莫及。
    % I6 C  ]( g) K$ z" e8 \1 v6 tGoogle的成功经验也表明了一点:单Master的设计是可行的。单Master的设计不# o+ z/ ~' [1 `* u8 _. r) ?( g
    仅简化了系统,而且能够较好地实现一致性,后面我们将要看到的绝大多数分布式7 ?5 S/ t; |2 E- q
    存储系统都和GFS一样依赖单总控节点。然而,单Master的设计并不意味着实现GFS5 `: D; ?) ?: q( B  t
    只是一些比较简单琐碎的工作。基于性能考虑,GFS提出了“记录至少原子性追加一
    $ B8 i. E3 r! K' u- m' P次”的一致性模型,通过租约的方式将每个chunk的修改授权下放到ChunkServer从而减4 S- i, e0 [: g# C9 q$ y
    少Master的负载,通过流水线的方式复制多个副本以减少延时,追加流程复杂繁琐。! z3 n9 c2 V+ X2 V0 A0 @
    另外,Master维护的元数据有很多,需要设计高效的数据结构,占用内存小,并且能
    1 K6 ^$ R/ p0 b) X够支持快照操作。支持写时复制的B树能够满足Master的元数据管理需求,然而,它& Q; _4 _( ~/ K* Z$ I( q
    的实现是相当复杂的。' f. o! ^: m9 M" H

    : Q* D% {' P! f4 ]
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-1-22 15:02 , Processed in 0.200736 second(s), 29 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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