java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2502|回复: 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 | 显示全部楼层 |阅读模式
    分布式文件系统的主要功能有两个:一个是存储文档、图像、视频之类的Blob3 V: W( i" s; ]1 F
    类型数据;另外一个是作为分布式表格系统的持久化层。
    % ~5 R% Z) u8 x$ d" T分布式文件系统中最为著名的莫过于Google File System(GFS),它构建在廉价) E& {& R  E# B; r4 i5 B' ]
    的普通PC服务器之上,支持自动容错。GFS内部将大文件划分为大小约为64MB的数
    # W$ \9 i9 }  R5 e) x# @据块(chunk),并通过主控服务器(Master)实现元数据管理、副本管理、自动负/ R" x4 C2 x: A1 O9 |
    载均衡等操作。其他文件系统,例如Taobao File System(TFS)、Facebook Haystack
    ( [2 j! L* Q2 I" e( ]" v或多或少借鉴了GFS的思路,架构上都比较相近。" N1 t  F: J3 g* o4 @$ |
    本章首先重点介绍GFS的内部实现机制,接着介绍TFS和Face book Haystack的内
    # w4 u, l8 l. V, r+ o部实现。最后,本章还会简单介绍内容分发网络(Content Delivery Network,CDN)技6 V* P: x8 y2 K4 U
    术,这种技术能够将图像、视频之类的数据缓存在离用户“最近”的网络节点上,从
    2 c* [9 M" d) Q) L* r# }而降低访问延时,节省带宽。) T4 Z, Z2 ~* f  C! h
    4.1 Google文件系统
    0 A# {% f" f9 W# k& YGoogle文件系统(GFS)是构建在廉价服务器之上的大型分布式系统。它将服务# y7 i6 [/ @% p' U3 z  G  }
    器故障视为正常现象,通过软件的方式自动容错,在保证系统可靠性和可用性的同
    ( n1 z# T5 n$ ^5 j3 ~- e时,大大降低系统的成本。/ V7 Q) p) d# b1 y
    GFS是Google分布式存储的基石,其他存储系统,如Google Bigtable、Google
    9 Z9 s$ _. q6 X3 ?1 ~Megastore、Google Percolator均直接或者间接地构建在GFS之上。另外,Google大规
    3 K- t+ P+ v- E+ ?# ?4 M: p模批处理系统MapReduce也需要利用GFS作为海量数据的输入输出。/ D! {1 |# I# l! D  S
    4.1.1 系统架构+ w0 ^- X4 N; W. o4 C- r; }" h8 w
    如图4-1所示,GFS系统的节点可分为三种角色:GFS Master(主控服务器)、4 A4 g  ]8 j- h- W& |) _
    GFS ChunkServer(CS,数据块服务器)以及GFS客户端。
    6 H3 j) S5 Q# U图 4-1 GFS整体架构
    6 z4 n$ n+ e. Z8 I* iGFS文件被划分为固定大小的数据块(chunk),由主服务器在创建时分配一个
    ) [8 E  ?+ E4 G0 c6 t2 X, F64位全局唯一的chunk句柄。CS以普通的Linux文件的形式将chunk存储在磁盘中。为1 S! Z9 O2 z7 }$ s- Q6 W7 [
    了保证可靠性,chunk在不同的机器中复制多份,默认为三份。
    / M- G1 M) \5 L) |! x" q/ ^) F, }主控服务器中维护了系统的元数据,包括文件及chunk命名空间、文件到chunk之1 I8 b8 F6 H+ O& F
    间的映射、chunk位置信息。它也负责整个系统的全局控制,如chunk租约管理、垃圾
    8 q* B* G0 r) R/ _+ M2 u0 X. v9 W回收无用chunk、chunk复制等。主控服务器会定期与CS通过心跳的方式交换信息。
    6 V' P# Q& @& d8 k9 `客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规
    ! S+ W! v0 C- a. K范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之: V" w+ }" t- ~$ X2 p
    进行交互的CS信息,然后直接访问这些CS,完成数据存取工作。0 B7 b0 t& ?4 G
    需要注意的是,GFS中的客户端不缓存文件数据,只缓存主控服务器中获取的元
    : G6 @- o. E: v& T* r数据,这是由GFS的应用特点决定的。GFS最主要的应用有两个:MapReduce与, @6 U3 W& o" |  U; F
    Bigtable。对于MapReduce,GFS客户端使用方式为顺序读写,没有缓存文件数据的必
    3 `6 L) X+ T  V' l$ A  p6 x要;而Bigtable作为分布式表格系统,内部实现了一套缓存机制。另外,如何维护客. m3 {" l& K5 f# S4 {! s2 X
    户端缓存与实际数据之间的一致性是一个极其复杂的问题。  E9 }; u6 Z5 a& d0 y
    4.1.2 关键问题* Y' c: P( g) U7 n; P: H
    1.租约机制+ N( [0 R3 O7 B0 H8 D1 [
    GFS数据追加以记录为单位,每个记录的大小为几十KB到几MB不等,如果每次7 N5 X6 P3 F' O' q) J- v
    记录追加都需要请求Master,那么Master显然会成为系统的性能瓶颈,因此,GFS系
    3 g2 A3 `) R. [( o! r# l统中通过租约(lease)机制将chunk写操作授权给ChunkServer。拥有租约授权的
    5 M' m3 W) x% g' jChunkServe称为主ChunkServer,其他副本所在的ChunkServer称为备ChunkServer。租) w2 o% C/ |. x+ X
    约授权针对单个chunk,在租约有效期内,对该chunk的写操作都由主ChunkServer负2 _7 w  z; D1 X4 m7 U' J
    责,从而减轻Master的负载。一般来说,租约的有效期比较长,比如60秒,只要没有
    ( Q" X( b& _% ^1 F; b9 o出现异常,主ChunkServer可以不断向Master请求延长租约的有效期直到整个chunk写
    - b* i. \" n( ~5 t1 Y/ e: j满。
    5 k9 d9 ?( Z$ L. x) f假设chunk A在GFS中保存了三个副本A1、A2、A3,其中,A1是主副本。如果副7 W! m# h& S' K/ K, m
    本A2所在ChunkServer下线后又重新上线,并且在A2下线的过程中,副本A1和A3有
    . x" r: U4 T- J$ S$ ?更新,那么A2需要被Master当成垃圾回收掉。GFS通过对每个chunk维护一个版本号
    , f# G9 V$ `! `1 I  c来解决,每次给chunk进行租约授权或者主ChunkServer重新延长租约有效期时,
    ' w) f3 b! h  J8 ~Master会将chunk的版本号加1。A2下线的过程中,副本A1和A3有更新,说明主, H! R& {! w1 S* w) ]* X
    ChunkServer向Master重新申请租约并增加了A1和A3的版本号,等到A2重新上线后,
    + x7 b* G6 Q2 H$ VMaster能够发现A2的版本号太低,从而将A2标记为可删除的chunk,Master的垃圾回收
    8 f! J$ ?0 T6 c任务会定时检查,并通知ChunkServer将A2回收掉。
      N- U8 R3 A8 I. r1 s0 e. f2.一致性模型
    ) p5 h' b4 L2 l; DGFS主要是为了追加(append)而不是改写(overwrite)而设计的。一方面是因" r3 U$ z# D4 N5 c5 Z8 L8 N
    为改写的需求比较少,或者可以通过追加来实现,比如可以只使用GFS的追加功能构
    6 }' u0 r% d" J6 Y# L" u0 k建分布式表格系统Bigtable;另一方面是因为追加的一致性模型相比改写要更加简单& t9 E( u- w* ?+ ]
    有效。考虑chunk A的三个副本A1、A2、A3,有一个改写操作修改了A1、A2但没有
    / e1 W* s. }# }修改A3,这样,落到副本A3的读操作可能读到不正确的数据;相应地,如果有一个
    2 a$ {9 B9 U2 r7 s6 H. \  w追加操作往A1、A2上追加了一个记录,但是追加A3失败,那么即使读操作落到副本0 ~* B: `1 W4 l  V
    A3也只是读到过期而不是错误的数据。. h! W) W  R( P2 \  p' J* k
    我们只讨论追加的一致性。如果不发生异常,追加成功的记录在GFS的各个副本
    . g" S4 C% F" G中是确定并且严格一致的;但是如果出现了异常,可能出现某些副本追加成功而某
    : |2 R- a( Y) f4 m. `/ J些副本没有成功的情况,失败的副本可能会出现一些可识别的填充(padding)记
    $ L1 W( P$ R% V3 b; m录。GFS客户端追加失败将重试,只要返回用户追加成功,说明在所有副本中都至少
    0 x( e! N4 y" l  L5 w4 u追加成功了一次。当然,可能出现记录在某些副本中被追加了多次,即重复记录;
      P$ [  y0 Y& }9 F也可能出现一些可识别的填充记录,应用层需要能够处理这些问题。
    % Y6 b3 h6 U& S! C; F& }+ {; B另外,由于GFS支持多个客户端并发追加,多个客户端之间的顺序是无法保证
    5 e3 X$ T' a3 _的,同一个客户端连续追加成功的多个记录也可能被打断,比如客户端先后追加成0 L" K/ A7 o" |/ d. H9 a9 k
    功记录R1和R2,由于追加R1和R2这两条记录的过程不是原子的,中途可能被其他客
    $ Q, G5 X& n0 ^# |2 ^户端打断,那么GFS的chunk中记录的R1和R2可能不连续,中间夹杂着其他客户端追
    ; w( |- L. P3 `加的数据。
    0 E- A  T! D' [GFS的这种一致性模型是追求性能导致的,这增加了应用程序开发的难度。对于
    3 D5 @* \; j! B6 KMapReduce应用,由于其批处理特性,可以先将数据追加到一个临时文件,在临时文- j, K3 S4 @  j; t( S
    件中维护索引记录每个追加成功的记录的偏移,等到文件关闭时一次性将临时文件
    - Z7 ~/ N8 f' `' {改名为最终文件。对于上层的Bigtable,有两种处理方式,后面将会介绍。
    2 K6 e# b$ F; Y& `0 m6 S3.追加流程1 B$ {- |$ _1 f/ K! ^
    追加流程是GFS系统中最为复杂的地方,而且,高效支持记录追加对基于GFS实9 I5 V/ c! M  F0 D( ?, n
    现的分布式表格系统Bigtable是至关重要的。如图4-2所示,追加流程大致如下:! b/ Z1 _" T# A4 b* e
    图 4-2 GFS追加流程1 w' s; G$ s' Z" J
    1)客户端向Master请求chunk每个副本所在的ChunkServer,其中主ChunkServer持9 B, O. }# t! E) ]+ R
    有修改租约。如果没有ChunkServer持有租约,说明该chunk最近没有写操作,Master3 Z- ?2 I& \; C1 l& b, H" @
    会发起一个任务,按照一定的策略将chunk的租约授权给其中一台ChunkServer。
    ; ]6 V+ j$ t2 j7 @0 ]# y2)Master返回客户端主副本和备副本所在的ChunkServer的位置信息,客户端将
    , H& N2 _8 C8 H* E& V缓存这些信息供以后使用。如果不出现故障,客户端以后读写该chunk都不需要再次
    : Y9 Q; v' c" }# U! g, d" Z0 |- {请求Master。
    ) V! I8 ?1 R* P( Y. H' ~3)客户端将要追加的记录发送到每一个副本,每一个ChunkServer会在内部的6 ?9 p+ H( ^& Y  J
    LRU结构中缓存这些数据。GFS中采用数据流和控制流分离的方法,从而能够基于网1 ?* r; b$ V1 x, q. z9 S/ x& q
    络拓扑结构更好地调度数据流的传输。
    " d* m2 q/ M  D2 h& k. }) D4)当所有副本都确认收到了数据,客户端发起一个写请求控制命令给主副本。5 ]* c, ^8 m8 h" i
    由于主副本可能收到多个客户端对同一个chunk的并发追加操作,主副本将确定这些+ }. E! f/ E- l3 |. y( `
    操作的顺序并写入本地。/ h* x5 m, `$ M/ n0 K
    5)主副本把写请求提交给所有的备副本。每一个备副本会根据主副本确定的顺6 a: p; Z* R4 F) m' Z
    序执行写操作。# T& u& G) ~. A& T2 n: n" Q
    6)备副本成功完成后应答主副本。
    5 j5 [* H  R4 f  r: ~( A5 d7)主副本应答客户端,如果有副本发生错误,将出现主副本写成功但是某些备3 E' k3 i8 w' O5 W
    副本不成功的情况,客户端将重试。" v* Z* ]+ ]1 h
    GFS追加流程有两个特色:流水线及分离数据流与控制流。流水线操作用来减少
    5 q- Z* `3 r+ a) Y# X) E4 p# N% a延时。当一个ChunkServer接收到一些数据,它就立即开始转发。由于采用全双工网1 c: |3 R$ R* I! E3 x/ I1 N" l
    络,立即发送数据并不会降低接收数据的速率。抛开网络阻塞,传输B个字节到R个/ U; S: Y" A. m7 w; v
    副本的理想时间是B/T+RL,其中T是网络吞吐量,L是节点之间的延时。假设采用千# h* \  }+ `$ u6 J2 ^
    兆网络,L通常小于1ms,传输1MB数据到多个副本的时间小于80ms。分离数据流与. S* i, Q! H, w5 Z) u4 ]! H" E
    控制流主要是为了优化数据传输,每一台机器都是把数据发送给网络拓扑图上“最
    1 f  G! M) j9 K! x6 ?0 s" d近”的尚未收到数据的数据。举个例子,假设有三台ChunkServer:S1、S2和S3,S1与
    / u/ g+ N8 p6 p2 h" Q% K+ US3在同一个机架上,S2在另外一个机架上,客户端部署在机器S1上。如果数据先从
    6 k* w5 v, |! K& uS1转发到S2,再从S2转发到S3,需要经历两次跨机架数据传输;相对地,按照GFS8 ^  ?. e8 K  f! d3 {$ Q' K
    中的策略,数据先发送到S1,接着从S1转发到S3,最后转发到S2,只需要一次跨机
    9 `$ x& q$ u' N7 `9 |架数据传输。" g* R- G7 c; M- u' z8 A
    分离数据流与控制流的前提是每次追加的数据都比较大,比如MapReduce批处理
    * M2 x" C: C3 D3 ~2 o系统,而且这种分离增加了追加流程的复杂度。如果采用传统的主备复制方法,追
    # ^, F# F0 g7 C) b/ C加流程会在一定程度上得到简化,如图4-3所示:; B6 X; X9 T! r7 \4 p2 l- C
    图 4-3 GFS追加流程(数据流与控制流合并)
    ) G3 h3 I; c, {, h* o; X( R1)同图4-2 GFS追加流程:客户端向Master请求chunk每个副本所在的. s' q! r. U" J% ]
    ChunkServer。! ~* F7 }9 L4 @
    2)同图4-2 GFS追加流程:Master返回客户端主副本和备副本所在ChunkServer的
    7 v/ j% Y7 U6 A. m6 C" d9 M5 X5 r位置信息。
    ' @6 [/ b( d5 F4 n# h6 d+ G6 _: n: S3)Client将待追加数据发送到主副本,主副本可能收到多个客户端的并发追加$ y; i: i. [6 [( [+ y6 Q5 f
    请求,需要确定操作顺序,并写入本地。
    5 P! G/ ~( x: K' G" W5 G; W) G  z4)主副本将数据通过流水线的方式转发给所有的备副本。9 A. w4 S" X9 C
    5)每个备副本收到待追加的记录数据后写入本地,所有副本都在本地写成功并0 @( f: F5 B% i
    且收到后一个副本的应答消息时向前一个副本回应,比如图4-3中备副本A需要等待
    5 Q' W! F% q  v: ?2 Q- ]备副本B应答成功且本地写成功后才可以应答主副本。
    ; T6 M# w6 q5 P5 P6)主副本应答客户端。如果客户端在超时时间之内没有收到主副本的应答,说. m! d+ u$ Q9 M. \/ _6 X
    明发生了错误,需要重试。
    % l/ C/ P' |2 Q+ c, p当然,实际的追加流程远远没有这么简单。追加的过程中可能出现主副本租约' u* c- B- ]0 J( p) O8 ]
    过期而失去chunk修改操作的授权,以及主副本或者备副本所在的ChunkServer出现故
    - i* t9 Y5 y- q& ?$ z障,等等。由于篇幅有限,追加流程的异常处理留作读者思考。4 g! d: ^( Q4 y. A4 F
    4.容错机制
    - C. e- D, `- s$ j! j9 `2 w1 N$ A(1)Master容错% R& P3 T! l- @9 {: l. F+ U4 S( V
    Master容错与传统方法类似,通过操作日志加checkpoint的方式进行,并且有一; o  ~9 [+ Z9 o6 X
    台称为"Shadow Master"的实时热备。
    6 Q: x/ L3 {( ~" M. HMaster上保存了三种元数据信息:
    ' R% ?7 t5 G0 T% k5 F; J5 x9 S●命名空间(Name Space),也就是整个文件系统的目录结构以及chunk基本信# H; i- W7 y$ ^" c( ?2 s4 g
    息;. p, e* U9 `: C5 J
    ●文件到chunk之间的映射;
    ( I: h3 E3 _: m. p●chunk副本的位置信息,每个chunk通常有三个副本。
    0 {/ L: |; J! b* O/ p2 p& }! pGFS Master的修改操作总是先记录操作日志,然后修改内存。当Master发生故障3 e5 U: }. W9 K
    重启时,可以通过磁盘中的操作日志恢复内存数据结构。另外,为了减少Master宕机5 K: I, L9 X/ m; R, M$ N+ H
    恢复时间,Master会定期将内存中的数据以checkpoint文件的形式转储到磁盘中,从
    4 F% s' U2 E4 P6 P而减少回放的日志量。为了进一步提高Master的可靠性和可用性,GFS中还会执行实0 Z- T2 X% w7 ~- E3 ~; I1 W: B6 J9 D' [
    时热备,所有的元数据修改操作都必须保证发送到实时热备才算成功。远程的实时
    3 \# ?4 ^. R; g8 n2 d热备将实时接收Master发送的操作日志并在内存中回放这些元数据操作。如果Master7 T+ p" [3 C1 v) b
    宕机,还可以秒级切换到实时备机继续提供服务。为了保证同一时刻只有一台1 [  O5 c  f/ Q, |7 U
    Master,GFS依赖Google内部的Chubby服务进行选主操作。
    % e  [$ |% w+ v: KMaster需要持久化前两种元数据,即命名空间及文件到chunk之间的映射;对于
    8 q# O* A4 y: |4 }第三种元数据,即chunk副本的位置信息,Master可以选择不进行持久化,这是因为
    9 _% U5 P9 d% fChunkServer维护了这些信息,即使Master发生故障,也可以在重启时通过
    / y. N! o5 w' {. WChunkServer汇报来获取。
    ! H' ?1 Z4 o" z6 v(2)ChunkServer容错
    2 \5 Z* A. X  F4 m* m( |3 J+ p% f. qGFS采用复制多个副本的方式实现ChunkServer的容错,每个chunk有多个存储副
    " C) Y  U* B; t本,分别存储在不同的ChunkServer上。对于每个chunk,必须将所有的副本全部写入
    : \% ?) ?7 x# W  C6 L2 ^8 v成功,才视为成功写入。如果相关的副本出现丢失或不可恢复的情况,Master自动将& z) J( ]# b. f6 C- v1 e
    副本复制到其他ChunkServer,从而确保副本保持一定的个数。
    8 |& n6 S; Y; }' {另外,ChunkServer会对存储的数据维持校验和。GFS以64MB为chunk大小来划分9 I8 }: h# i: M- ~: {$ t
    文件,每个chunk又以Block为单位进行划分,Block大小为64KB,每个Block对应一个, \+ r! N  Y% x; g
    32位的校验和。当读取一个chunk副本时,ChunkServer会将读取的数据和校验和进行5 P8 V1 ^. R7 Z) x# ]" o
    比较,如果不匹配,就会返回错误,客户端将选择其他ChunkServer上的副本。
    9 q  u$ |# Y# s, ^% |# A) O4.1.3 Master设计/ A; m: z* z* U# n6 g. Y; R  p4 G
    1.Master内存占用
    " u! a5 D( m1 q  x) wMaster维护了系统中的元数据,包括文件及chunk命名空间、文件到chunk之间的) U# u7 ?2 r, w: w' U1 }
    映射、chunk副本的位置信息。其中前两种元数据需要持久化到磁盘,chunk副本的位
    ; I, X8 v6 e" X, _- d/ B置信息不需要持久化,可以通过ChunkServer汇报获取。# U0 e4 ^% n$ U- S8 m
    内存是Master的稀有资源,接下来介绍如何估算Master的内存使用量。chunk的元$ o( ]/ j# L+ J) R: a
    信息包括全局唯一的ID、版本号、每个副本所在的ChunkServer编号、引用计数等。$ R; i2 J" O3 h( K
    GFS系统中每个chunk大小为64MB,默认存储3份,每个chunk的元数据小于64字节。
    1 F( |- ^4 M6 K' U) o/ T! U那么1PB数据的chunk元信息大小不超过1PB×3/64MB×64=3GB。另外,Master对命名  C& b! I% {% ]; S' U
    空间进行了压缩存储,例如有两个文件foo1和foo2都存放在目. {5 w1 d5 W; Z% [+ [7 z- Y" A
    录/home/very_long_directory_name/中,那么目录名在内存中只需要存放一次。压缩存
    5 p" ]" V; R  k3 Y: b% ]+ R储后,每个文件在文件命名空间的元数据也不超过64字节,由于GFS中的文件一般都
    ! r. N; d# p0 B" d是大文件,因此,文件命名空间占用内存不多。这也就说明了Master内存容量不会成( S' S0 u  `0 s) A( x
    为GFS的系统瓶颈。* B8 T% v; z4 r
    2.负载均衡2 }6 ]7 @; [5 A
    GFS中副本的分布策略需要考虑多种因素,如网络拓扑、机架分布、磁盘利用率
    1 e8 @$ c2 z6 L0 |等。为了提高系统的可用性,GFS会避免将同一个chunk的所有副本都存放在同一个
    0 y$ p' {; M. x! B9 v. }4 ^6 K6 \机架的情况。
    , c; |; G$ ~5 G( F/ U; i: g3 w! t系统中需要创建chunk副本的情况有三种:chunk创建、chunk复制(re-
    2 S& `2 z6 ~% x( e# O5 }replication)以及负载均衡(rebalancing)。: `# ~$ h2 A+ B4 w* x
    当Master创建了一个chunk,它会根据如下因素来选择chunk副本的初始位置:1)
      A' {' i. E4 I' e+ E) d新副本所在的ChunkServer的磁盘利用率低于平均水平;2)限制每个Chunk-Server“最8 I: H4 q$ R& P) f1 Q0 S$ f
    近”创建的数量;3)每个chunk的所有副本不能在同一个机架。第二点容易忽略但却
    9 V7 B/ y- p% z, H, R很重要,因为创建完chunk以后通常需要马上写入数据,如果不限制“最近”创建的数
    $ X! f/ o4 h4 q$ s量,当一台空的ChunkServer上线时,由于磁盘利用率低,可能导致大量的chunk瞬间+ r4 w& X4 c; D% a8 p+ \
    迁移到这台机器从而将它压垮。
    # `; C; C) ?/ d) s  x0 @. E% G0 c8 E当chunk的副本数量小于一定的数量后,Master会尝试重新复制一个chunk副本。
    * D, Y' v* O$ }) c* H, ?可能的原因包括ChunkServer宕机或者ChunkServer报告自己的副本损坏,或者
    8 ?. o+ O4 d+ b7 X7 F3 qChunkServer的某个磁盘故障,或者用户动态增加了chunk的副本数,等等。每个chunk
      S! Y, z& c3 Z4 e) {复制任务都有一个优先级,按照优先级从高到低在Master排队等待执行。例如,只有
    0 h: [4 ^8 n1 \一个副本的chunk需要优先复制。另外,GFS会提高所有阻塞客户端操作的chunk复制/ b* J" b. _% u# r9 g; f- d
    任务的优先级,例如客户端正在往一个只有一个副本的chunk追加数据,如果限制至6 b, T. P* t6 A* r  p5 P$ v
    少需要追加成功两个副本,那么这个chunk复制任务会阻塞客户端写操作,需要提高
    & S. ^5 S8 q/ K3 f# y/ r. X优先级。
    ( J, P. q( \7 g; R9 o, |: r最后,Master会定期扫描当前副本的分布情况,如果发现磁盘使用量或者机器负: L; ^2 _4 {0 ^2 ?/ K& N$ X  A
    载不均衡,将执行重新负载均衡操作。
    , ^% B8 N6 ^* m5 x, ]' a( ^无论是chunk创建,chunk重新复制,还是重新负载均衡,这些操作选择chunk副本
    3 W+ H- W" G1 B1 i$ ~2 k位置的策略都是相同的,并且需要限制重新复制和重新负载均衡任务的拷贝速度,
    # n7 P$ B& X: E" L! ?% n3 r否则可能影响系统正常的读写服务。- V; r3 O) Q5 f. A
    3.垃圾回收
    / u/ O# w% j0 V; y2 w# Z, yGFS采用延迟删除的机制,也就是说,当删除文件后,GFS并不要求立即归还可& m* o6 B! x0 w
    用的物理存储,而是在元数据中将文件改名为一个隐藏的名字,并且包含一个删除" y* [* l/ R9 C: E" d& }" T
    时间戳。Master定时检查,如果发现文件删除超过一段时间(默认为3天,可配# W0 a  B4 C  `
    置),那么它会把文件从内存元数据中删除,以后ChunkServer和Master的心跳消息
    0 Y+ }" D* m% ?1 n( G3 |中,每一个ChunkServer都将报告自己的chunk集合,Master会回复在Master元数据中
    ; y- w0 G: r  L! D$ j, N已经不存在的chunk信息,这时,ChunkServer会释放这些chunk副本。为了减轻系统的
    , C* I1 U9 _3 c负载,垃圾回收一般在服务低峰期执行,比如每天晚上凌晨1:00开始。# V+ M- C& f6 y2 P1 K2 F
    另外,chunk副本可能会因为ChunkServer失效期间丢失了对chunk的修改操作而导7 l7 ]: s2 h2 x( Q' S7 A
    致过期。系统对每个chunk都维护了版本号,过期的chunk可以通过版本号检测出来。) f) V5 r+ q! i' A5 g# l( }
    Master仍然通过正常的垃圾回收机制来删除过期的副本。
    0 N' v" H8 |! g# b+ S4.快照. h& }9 ~# _; l, M3 e2 q
    快照(Snapshot)操作是对源文件/目录进行一个“快照”操作,生成该时刻源文* f( H9 k, j" }; q
    件/目录的一个瞬间状态存放于目标文件/目录中。GFS中使用标准的写时复制机制生
    & J2 q, K4 v' Z4 r" v$ T2 c成快照,也就是说,“快照”只是增加GFS中chunk的引用计数,表示这个chunk被快照
    6 a2 b4 d& {, R. L- K+ f& _文件引用了,等到客户端修改这个chunk时,才需要在ChunkServer中拷贝chunk的数据
    : a) k( f2 W: I7 W, K5 X5 V生成新的chunk,后续的修改操作落到新生成的chunk上。
    3 L- ?7 d  Q+ m! M( Z% i9 P  M+ {为了对某个文件做快照,首先需要停止这个文件的写服务,接着增加这个文件$ a* e' f5 o6 u8 [, E# Y0 }- l
    的所有chunk的引用计数,以后修改这些chunk时会拷贝生成新的chunk。对某个文件执
    1 {" y5 v; |9 ~( D! M: }" p行快照的大致步骤如下:5 v; z! x0 f" R) ^5 D1 ^
    1)通过租约机制收回对文件的每个chunk写权限,停止对文件的写服务;
    + s5 c- _6 X; C+ l( o1 j2)Master拷贝文件名等元数据生成一个新的快照文件;% g! R" \% k9 E" Z( p( E
    3)对执行快照的文件的所有chunk增加引用计数。
    * x' p0 \; i+ u* t例如,对文件foo执行快照操作生成foo_backup,foo在GFS中有三个chunk:C1、C2
    7 |& O; c. ?8 s, q: _# r" Z' Y和C3(简单起见,假设每个chunk只有一个副本)。Master首先需要收回C1、C2和C3! w  G2 q1 F: U
    的写租约,从而保证文件foo处于一致的状态,接着Master复制foo文件的元数据用于& ^$ ]9 n, V( I" ]0 b
    生成foo_backup,foo_backup同样指向C1、C2和C3。快照前,C1、C2和C3只被一个文  M1 A$ n3 L; s/ U* }5 L  U
    件foo引用,因此引用计数为1;执行快照操作后,这些chunk的引用计数增加为2。以
    ' }1 M- N8 O" D8 I7 _2 B8 m后客户端再次向C3追加数据时,Master发现C3的引用计数大于1,通知C3所在的* Y2 v0 \4 l- Z( T# e# S* S  G
    ChunkServer本次拷贝C3生成C3',客户端的追加操作也相应地转向C3'。8 O" a! U7 l& ~& l
    4.1.4 ChunkServer设计
    1 i0 \/ |: M. W% K! x) ]7 w/ {ChunkServer管理大小约为64MB的chunk,存储的时候需要保证chunk尽可能均匀
    ( k. e5 q4 \3 v$ L& n地分布在不同的磁盘之中,需要考虑的可能因素包括磁盘空间、最近新建chunk数' P2 E( w. F7 m0 R6 L) o
    等。另外,Linux文件系统删除64MB大文件消耗的时间太长且没有必要,因此,删除7 i( m3 G7 i& }9 B0 [- `8 w
    chunk时可以只将对应的chunk文件移动到每个磁盘的回收站,以后新建chunk的时候可
    1 |7 _$ w/ T' A- \& z+ K以重用。( _5 f9 \/ E' ]3 g. G* d5 e
    ChunkServer是一个磁盘和网络IO密集型应用,为了最大限度地发挥机器性能,; `4 \! d$ H* _% D* Y) w  W
    需要能够做到将磁盘和网络操作异步化,但这会增加代码实现的难度。  }7 E2 k* T& l2 u- c+ S0 E1 x: W
    4.1.5 讨论- g9 s; P! W3 |3 P: L2 Y) i2 |6 P
    从GFS的架构设计可以看出,GFS是一个具有良好可扩展性并能够在软件层面自
    # a3 D" e& }% t( }, h; Q动处理各种异常情况的系统。Google是一家很重视自动化的公司,从早期的GFS,再( |5 K7 X! Z' m" U6 w! q0 Z
    到Bigtable、Megastore,以及最近的Spanner,Google的分布式存储系统在这一点上一脉
    ( D  q! W  [6 j" b! [相承。由于Google的系统一开始能很好地解决可扩展性问题,所以后续的系统能够
    % V5 g, s9 A9 P- J构建在前一个系统之上并且一步一步引入新的功能,如Bigtable在GFS之上将海量数% E% m" ~7 t* f. V. S) Y
    据组织成表格形式,Megastore、Spanner又进一步在Bigtable之上融合一些关系型数据( }8 k. o( O5 @. y, `
    库的功能,整个解决方案完美华丽。
    3 c6 `+ I$ P- F7 Q6 e自动化对系统的容错能力提出了很高的要求,在设计GFS时认为节点失效是常, H" Y, H* e- U% V1 G
    态,通过在软件层面进行故障检测,并且通过chunk复制操作将原有故障节点的服务3 n9 C- V0 B# L) d' ~/ u) z: d
    迁移到新的节点。系统还会根据一定的策略,如磁盘使用情况、机器负载等执行负: ]- e9 `, e' L! h' c
    载均衡操作。Google在软件层面的努力获得了巨大的回报,由于软件层面能够做到
    / x0 n+ V- L1 h4 d6 A/ }  ^. j自动化容错,底层的硬件可以采用廉价的错误率较高的硬件,比如廉价的SATA盘,
    6 |4 b. T+ ]# t) u' R; ~这大大降低了云服务的成本,在和其他厂商的竞争中表现出价格优势。比较典型的5 h1 D+ A6 R) o
    例子就是Google的邮箱服务,由于基础设施成本低,Gmail服务能够免费给用户提供4 R" O5 S3 @$ c2 ]6 e0 Q  L
    更大的容量,令其他厂商望尘莫及。" l# b6 J( I/ K) d1 Z$ l
    Google的成功经验也表明了一点:单Master的设计是可行的。单Master的设计不+ ?  v6 w5 N6 @  I, T" }
    仅简化了系统,而且能够较好地实现一致性,后面我们将要看到的绝大多数分布式
    8 W; l$ h- z9 [1 u3 N: X4 J  A存储系统都和GFS一样依赖单总控节点。然而,单Master的设计并不意味着实现GFS  C! t* d7 c! H" o2 J
    只是一些比较简单琐碎的工作。基于性能考虑,GFS提出了“记录至少原子性追加一
    # J- k5 ~) B( l次”的一致性模型,通过租约的方式将每个chunk的修改授权下放到ChunkServer从而减/ {6 E, S$ B0 e6 |) [. W) v4 C
    少Master的负载,通过流水线的方式复制多个副本以减少延时,追加流程复杂繁琐。5 b, l# d" q, n8 w: ?: ?. e, M
    另外,Master维护的元数据有很多,需要设计高效的数据结构,占用内存小,并且能7 J! @8 Q6 q- x
    够支持快照操作。支持写时复制的B树能够满足Master的元数据管理需求,然而,它9 j& u" A6 V- n4 P0 f9 Y; L3 p5 @
    的实现是相当复杂的。1 u/ R* F* z0 a% _1 H& r

    / o  M' i0 R8 H/ q! `/ |/ a) o( U
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-1 14:02 , Processed in 0.299755 second(s), 32 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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