java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2464|回复: 0

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

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

    [LV.Master]出神入化

    2062

    主题

    3720

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66592

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

    发表于 2017-3-3 20:20:23 | 显示全部楼层 |阅读模式
    分布式文件系统的主要功能有两个:一个是存储文档、图像、视频之类的Blob4 H3 H% f! g; M( _
    类型数据;另外一个是作为分布式表格系统的持久化层。
    % J0 ~% Q2 L7 i* l" J分布式文件系统中最为著名的莫过于Google File System(GFS),它构建在廉价
    ( V- d3 u! U! C6 p" A的普通PC服务器之上,支持自动容错。GFS内部将大文件划分为大小约为64MB的数6 X. |: Y! R6 `
    据块(chunk),并通过主控服务器(Master)实现元数据管理、副本管理、自动负
    8 k. C- O% b; H载均衡等操作。其他文件系统,例如Taobao File System(TFS)、Facebook Haystack7 V( G9 B$ ~, X+ R; k0 t
    或多或少借鉴了GFS的思路,架构上都比较相近。( w' w( J0 ]% C: J& j
    本章首先重点介绍GFS的内部实现机制,接着介绍TFS和Face book Haystack的内) X9 F" x5 a5 r: ]  k) z
    部实现。最后,本章还会简单介绍内容分发网络(Content Delivery Network,CDN)技
    ! Q! T7 j. g3 h2 p  W' V- ]术,这种技术能够将图像、视频之类的数据缓存在离用户“最近”的网络节点上,从
    . ~6 I4 R, j8 G1 v  _; r而降低访问延时,节省带宽。& J( [/ B. [0 f$ G, H# a4 \
    4.1 Google文件系统) i; R! R2 H% t$ |8 K+ C
    Google文件系统(GFS)是构建在廉价服务器之上的大型分布式系统。它将服务: _2 d( S5 X  W7 L* W, r2 u; H! S& J
    器故障视为正常现象,通过软件的方式自动容错,在保证系统可靠性和可用性的同6 _( q! ^* J3 f' m" `4 H. O6 D  r
    时,大大降低系统的成本。1 i9 p! m. {' H: V0 [7 y% C
    GFS是Google分布式存储的基石,其他存储系统,如Google Bigtable、Google& T7 G' E" q2 \" y) T  `
    Megastore、Google Percolator均直接或者间接地构建在GFS之上。另外,Google大规
    5 s; d8 _3 B' k  a1 _: D模批处理系统MapReduce也需要利用GFS作为海量数据的输入输出。
    1 _; R, s6 N8 k9 a8 K4.1.1 系统架构. k" e. p- V% ]5 P& ~* k, M. z
    如图4-1所示,GFS系统的节点可分为三种角色:GFS Master(主控服务器)、
    / T; U) J5 f7 [" x" F1 uGFS ChunkServer(CS,数据块服务器)以及GFS客户端。
    6 R- k1 N5 o4 [7 H图 4-1 GFS整体架构
      V( U6 W+ q* XGFS文件被划分为固定大小的数据块(chunk),由主服务器在创建时分配一个# H5 F* ?1 ]1 d
    64位全局唯一的chunk句柄。CS以普通的Linux文件的形式将chunk存储在磁盘中。为+ v  q/ Y; ~6 h  m
    了保证可靠性,chunk在不同的机器中复制多份,默认为三份。
    $ O. \3 o* g9 K& c  D主控服务器中维护了系统的元数据,包括文件及chunk命名空间、文件到chunk之
    8 O; h% t  D1 k1 [. X$ {) @间的映射、chunk位置信息。它也负责整个系统的全局控制,如chunk租约管理、垃圾
    1 ^0 h+ `$ s' c+ d2 A$ u: J回收无用chunk、chunk复制等。主控服务器会定期与CS通过心跳的方式交换信息。
    ' G5 }) Z5 x; s( c客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规$ ]5 D; C. \% K
    范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之( R* U7 D% D/ G5 e% v& u' V- B2 c
    进行交互的CS信息,然后直接访问这些CS,完成数据存取工作。8 d7 v1 U; }* i! c
    需要注意的是,GFS中的客户端不缓存文件数据,只缓存主控服务器中获取的元
    6 f" G0 d8 m* p% U7 y+ F/ s数据,这是由GFS的应用特点决定的。GFS最主要的应用有两个:MapReduce与9 w3 x5 U5 d" V. n  w
    Bigtable。对于MapReduce,GFS客户端使用方式为顺序读写,没有缓存文件数据的必
    4 T8 A, y- |5 O要;而Bigtable作为分布式表格系统,内部实现了一套缓存机制。另外,如何维护客
    2 o) _: |! ^8 z) @6 `* t: s' n% h户端缓存与实际数据之间的一致性是一个极其复杂的问题。
    0 t  r- e( }, o! y6 t4.1.2 关键问题
    ) l8 |" S; G* {- P7 W1.租约机制4 o) \. o, F* w. G% c% q) F
    GFS数据追加以记录为单位,每个记录的大小为几十KB到几MB不等,如果每次
    7 X+ x/ a- D; q  ?1 b记录追加都需要请求Master,那么Master显然会成为系统的性能瓶颈,因此,GFS系
    5 h. b; m1 x  h6 G' F% J统中通过租约(lease)机制将chunk写操作授权给ChunkServer。拥有租约授权的
      F" P: O) q7 e. [& ^" l8 PChunkServe称为主ChunkServer,其他副本所在的ChunkServer称为备ChunkServer。租; s" ^: o/ D2 m4 D2 q6 H, O
    约授权针对单个chunk,在租约有效期内,对该chunk的写操作都由主ChunkServer负
    ( M0 Q  G% s& L/ L: _责,从而减轻Master的负载。一般来说,租约的有效期比较长,比如60秒,只要没有! ~- `+ o8 h4 L+ _, a
    出现异常,主ChunkServer可以不断向Master请求延长租约的有效期直到整个chunk写" B$ I. m5 ?" }1 r! p
    满。* ~& l% ^. o4 ]0 Y5 K  s
    假设chunk A在GFS中保存了三个副本A1、A2、A3,其中,A1是主副本。如果副7 I9 m( ?$ Z$ R0 Y9 a
    本A2所在ChunkServer下线后又重新上线,并且在A2下线的过程中,副本A1和A3有
    4 a( g; S$ E4 B) @7 f* [% k9 j5 q更新,那么A2需要被Master当成垃圾回收掉。GFS通过对每个chunk维护一个版本号0 K( N' J5 q# y" V0 A
    来解决,每次给chunk进行租约授权或者主ChunkServer重新延长租约有效期时,
    ) k$ f! `$ H/ a8 T4 B, m3 _Master会将chunk的版本号加1。A2下线的过程中,副本A1和A3有更新,说明主7 p2 ~8 D, ^8 M3 X
    ChunkServer向Master重新申请租约并增加了A1和A3的版本号,等到A2重新上线后,
    ; U& r$ v: X& q8 |Master能够发现A2的版本号太低,从而将A2标记为可删除的chunk,Master的垃圾回收
    9 x, d. I) S* G6 @8 J任务会定时检查,并通知ChunkServer将A2回收掉。7 C3 f& b5 t" l( A
    2.一致性模型
    * j5 v$ W' L1 W! N$ WGFS主要是为了追加(append)而不是改写(overwrite)而设计的。一方面是因
    4 {/ U8 O- E% I( d: e. E7 I为改写的需求比较少,或者可以通过追加来实现,比如可以只使用GFS的追加功能构3 U9 s3 T4 O- b  h% |* j
    建分布式表格系统Bigtable;另一方面是因为追加的一致性模型相比改写要更加简单4 ?$ Z' q: f# E
    有效。考虑chunk A的三个副本A1、A2、A3,有一个改写操作修改了A1、A2但没有
      [$ ]7 Y; Q. C% D9 \, K修改A3,这样,落到副本A3的读操作可能读到不正确的数据;相应地,如果有一个- Y, ^( _" H$ E
    追加操作往A1、A2上追加了一个记录,但是追加A3失败,那么即使读操作落到副本* i+ \+ o; Z  ]) ~1 x
    A3也只是读到过期而不是错误的数据。  n0 M" b7 N) b/ `6 C* ], q
    我们只讨论追加的一致性。如果不发生异常,追加成功的记录在GFS的各个副本7 N, o+ a/ z2 e  _
    中是确定并且严格一致的;但是如果出现了异常,可能出现某些副本追加成功而某7 v) J0 K/ [) b$ ~
    些副本没有成功的情况,失败的副本可能会出现一些可识别的填充(padding)记
    2 N* U+ v3 S9 C% z. z- Z录。GFS客户端追加失败将重试,只要返回用户追加成功,说明在所有副本中都至少
    , G0 e, o: o/ W- q9 c2 k追加成功了一次。当然,可能出现记录在某些副本中被追加了多次,即重复记录;# B9 u5 [3 o" p, S$ q% q# h
    也可能出现一些可识别的填充记录,应用层需要能够处理这些问题。0 L3 g% T0 B" X! ^0 g/ q: Y
    另外,由于GFS支持多个客户端并发追加,多个客户端之间的顺序是无法保证
    ) _1 O. @: g. E4 r$ ?的,同一个客户端连续追加成功的多个记录也可能被打断,比如客户端先后追加成
    9 Y+ x$ U- E  l功记录R1和R2,由于追加R1和R2这两条记录的过程不是原子的,中途可能被其他客) p3 W5 T. ?4 k* S) ?
    户端打断,那么GFS的chunk中记录的R1和R2可能不连续,中间夹杂着其他客户端追4 P) r$ ?+ b0 X5 ^. z
    加的数据。
    9 _+ g0 D3 q2 R* {  b4 u+ S! |- |GFS的这种一致性模型是追求性能导致的,这增加了应用程序开发的难度。对于3 G" n' t& U# u' @# m' _3 x
    MapReduce应用,由于其批处理特性,可以先将数据追加到一个临时文件,在临时文
    % B. w' P% S. F, D$ q9 o0 U7 y9 j( ?件中维护索引记录每个追加成功的记录的偏移,等到文件关闭时一次性将临时文件
    & P( u2 o( i3 o. S1 ]2 u# g) B1 B改名为最终文件。对于上层的Bigtable,有两种处理方式,后面将会介绍。# Q  a" S! D9 V
    3.追加流程
    , d9 M! p( P0 Q, o- N- `追加流程是GFS系统中最为复杂的地方,而且,高效支持记录追加对基于GFS实
    1 q/ q0 U+ ?3 I5 d4 _现的分布式表格系统Bigtable是至关重要的。如图4-2所示,追加流程大致如下:( n% [! O4 T+ ~! _( P& {$ W3 C
    图 4-2 GFS追加流程7 p9 K- P& D; g
    1)客户端向Master请求chunk每个副本所在的ChunkServer,其中主ChunkServer持
    % b8 n0 q, _% y8 q# F0 B有修改租约。如果没有ChunkServer持有租约,说明该chunk最近没有写操作,Master
    * p. H3 Z% t( S( `会发起一个任务,按照一定的策略将chunk的租约授权给其中一台ChunkServer。% `) Y# I9 i5 K2 o0 Q. e$ x
    2)Master返回客户端主副本和备副本所在的ChunkServer的位置信息,客户端将
    , A5 h( v4 Q* n" g. F8 w缓存这些信息供以后使用。如果不出现故障,客户端以后读写该chunk都不需要再次
    ; F( o5 t  p6 F+ q# I请求Master。
    0 X' o5 t  A, {( p3)客户端将要追加的记录发送到每一个副本,每一个ChunkServer会在内部的
    2 b) X7 \- U, d$ VLRU结构中缓存这些数据。GFS中采用数据流和控制流分离的方法,从而能够基于网& @* h/ [3 b% \) m0 L7 \
    络拓扑结构更好地调度数据流的传输。
    ( |  }# L8 w7 q8 H, f5 \: L4)当所有副本都确认收到了数据,客户端发起一个写请求控制命令给主副本。4 P; ^9 a$ Z0 n( q3 U8 j
    由于主副本可能收到多个客户端对同一个chunk的并发追加操作,主副本将确定这些) D& m5 l9 G0 ~- v
    操作的顺序并写入本地。
    ) i+ Y) Q7 p- d1 i7 K5)主副本把写请求提交给所有的备副本。每一个备副本会根据主副本确定的顺, Y( u8 ?2 I% Q3 b1 B! n; r$ p
    序执行写操作。
    1 }& W& f2 y1 E6)备副本成功完成后应答主副本。  w, L5 b- s1 a0 }# i
    7)主副本应答客户端,如果有副本发生错误,将出现主副本写成功但是某些备
    $ s, I9 v' X/ z. x3 H副本不成功的情况,客户端将重试。  P7 ^/ Z/ s0 u" ^- ]& F
    GFS追加流程有两个特色:流水线及分离数据流与控制流。流水线操作用来减少+ Z* L+ c9 D- ~- s! g8 W
    延时。当一个ChunkServer接收到一些数据,它就立即开始转发。由于采用全双工网8 a# l# q: ~/ k
    络,立即发送数据并不会降低接收数据的速率。抛开网络阻塞,传输B个字节到R个
    / Q3 \  \, ?, z8 y0 a3 Z副本的理想时间是B/T+RL,其中T是网络吞吐量,L是节点之间的延时。假设采用千
    * t' _3 P: d  ^兆网络,L通常小于1ms,传输1MB数据到多个副本的时间小于80ms。分离数据流与
    " h5 v! T8 ~# m, R控制流主要是为了优化数据传输,每一台机器都是把数据发送给网络拓扑图上“最
    8 d$ D* P6 L  b) m6 X+ o近”的尚未收到数据的数据。举个例子,假设有三台ChunkServer:S1、S2和S3,S1与3 h( I0 t# ?$ L
    S3在同一个机架上,S2在另外一个机架上,客户端部署在机器S1上。如果数据先从
    8 C4 t4 c! T, U3 y  DS1转发到S2,再从S2转发到S3,需要经历两次跨机架数据传输;相对地,按照GFS3 c" [! T- s0 i6 `2 ?" z) w
    中的策略,数据先发送到S1,接着从S1转发到S3,最后转发到S2,只需要一次跨机
    7 k$ n; l( u$ L  c4 V; O2 W, ?架数据传输。3 f- j5 e* h- m: a
    分离数据流与控制流的前提是每次追加的数据都比较大,比如MapReduce批处理$ E9 u! _+ f" ^6 y; v& p: _
    系统,而且这种分离增加了追加流程的复杂度。如果采用传统的主备复制方法,追& \) M7 k) x& K* w8 J6 w
    加流程会在一定程度上得到简化,如图4-3所示:
    / S; B- s: f+ @图 4-3 GFS追加流程(数据流与控制流合并)
    ; H& n0 y/ B$ e3 f( |9 ~1 y% K1)同图4-2 GFS追加流程:客户端向Master请求chunk每个副本所在的9 \5 {5 N0 M5 }
    ChunkServer。& C7 d0 e( \5 K8 x9 r/ T
    2)同图4-2 GFS追加流程:Master返回客户端主副本和备副本所在ChunkServer的
    + g$ J0 j: B8 f" I4 k' Z2 w1 E* ?位置信息。
    0 w" M! ]& a; B% P3 B2 W3)Client将待追加数据发送到主副本,主副本可能收到多个客户端的并发追加( B8 x. x0 M: t. {
    请求,需要确定操作顺序,并写入本地。! x. ?7 ^  {9 `' x" k% l# x
    4)主副本将数据通过流水线的方式转发给所有的备副本。
    6 W4 B: G' k6 G+ i& P" ^7 R5)每个备副本收到待追加的记录数据后写入本地,所有副本都在本地写成功并
    5 p3 R' b5 b3 \% a0 ]且收到后一个副本的应答消息时向前一个副本回应,比如图4-3中备副本A需要等待- {( i' q" a0 ?/ A7 W, @8 b
    备副本B应答成功且本地写成功后才可以应答主副本。
    9 ?6 T* G- ^2 }. |9 [  o: q6)主副本应答客户端。如果客户端在超时时间之内没有收到主副本的应答,说
    / h3 A& G+ u/ [- B( o# \9 t8 W! J明发生了错误,需要重试。
    % ^& H# V5 e6 N; J5 i7 n0 M当然,实际的追加流程远远没有这么简单。追加的过程中可能出现主副本租约
    8 a, n* c! K8 ]. i2 }过期而失去chunk修改操作的授权,以及主副本或者备副本所在的ChunkServer出现故
    0 d. x5 y0 w. r+ H) t# |7 l: d; G障,等等。由于篇幅有限,追加流程的异常处理留作读者思考。/ B& o# f% W4 @5 v3 O5 z
    4.容错机制0 S7 r" {4 v- v7 O
    (1)Master容错, T. F& H! j( `% E$ E  P
    Master容错与传统方法类似,通过操作日志加checkpoint的方式进行,并且有一
      E. K7 \/ E  a, Y; ^. j7 x台称为"Shadow Master"的实时热备。7 N% \, m$ m0 y  T3 w. ?
    Master上保存了三种元数据信息:
    , w2 o0 [# W1 `3 D$ n, D●命名空间(Name Space),也就是整个文件系统的目录结构以及chunk基本信; Z. h7 b/ r( W& {. c
    息;/ y5 ?' o7 G9 B: M4 y5 r, D
    ●文件到chunk之间的映射;: x. Q/ v$ [3 E; ]: f
    ●chunk副本的位置信息,每个chunk通常有三个副本。# M% P% s9 g% I. _8 ~
    GFS Master的修改操作总是先记录操作日志,然后修改内存。当Master发生故障
    6 B+ H$ o) F. o$ R" K0 n+ [重启时,可以通过磁盘中的操作日志恢复内存数据结构。另外,为了减少Master宕机7 |) N2 l8 \% e9 j) D
    恢复时间,Master会定期将内存中的数据以checkpoint文件的形式转储到磁盘中,从: ~8 [# n4 K# a% ~: l" l4 ~
    而减少回放的日志量。为了进一步提高Master的可靠性和可用性,GFS中还会执行实
    9 c) b/ }/ n. P; |; a0 h' d4 T2 a时热备,所有的元数据修改操作都必须保证发送到实时热备才算成功。远程的实时
    5 b8 H5 x& R0 J0 F$ C热备将实时接收Master发送的操作日志并在内存中回放这些元数据操作。如果Master
    * f; ]" ]3 w/ F5 y9 l! ^宕机,还可以秒级切换到实时备机继续提供服务。为了保证同一时刻只有一台
    , x: m% W- l& o+ u$ r8 B7 n% rMaster,GFS依赖Google内部的Chubby服务进行选主操作。" W, V" ~; K# @8 @+ X" D
    Master需要持久化前两种元数据,即命名空间及文件到chunk之间的映射;对于2 Y: l+ `& [- M# q
    第三种元数据,即chunk副本的位置信息,Master可以选择不进行持久化,这是因为
    0 |2 y& a/ {6 l8 i% ^% AChunkServer维护了这些信息,即使Master发生故障,也可以在重启时通过
    4 k# I# l0 l. E& RChunkServer汇报来获取。2 z4 a, k9 i5 ]  R3 u0 ?
    (2)ChunkServer容错
    5 @8 D, n+ X, G; f- U) QGFS采用复制多个副本的方式实现ChunkServer的容错,每个chunk有多个存储副0 M$ g) g0 N( S% s
    本,分别存储在不同的ChunkServer上。对于每个chunk,必须将所有的副本全部写入
    % Y- ~* v, m$ C9 o" X! ^成功,才视为成功写入。如果相关的副本出现丢失或不可恢复的情况,Master自动将
    + {1 Y! b& E6 d" m5 d! t副本复制到其他ChunkServer,从而确保副本保持一定的个数。$ `2 {) }$ o; W% `) A+ \3 {7 @+ l
    另外,ChunkServer会对存储的数据维持校验和。GFS以64MB为chunk大小来划分3 i9 V& E, |1 a$ i* Q6 Z4 Z7 a8 R* @
    文件,每个chunk又以Block为单位进行划分,Block大小为64KB,每个Block对应一个
    1 y7 \4 T3 p* X3 n8 V32位的校验和。当读取一个chunk副本时,ChunkServer会将读取的数据和校验和进行
      I/ c" q1 B! X& [; r! L比较,如果不匹配,就会返回错误,客户端将选择其他ChunkServer上的副本。" i0 J" u4 h3 D% }
    4.1.3 Master设计
    % z% J0 o7 z! n5 R) ^1.Master内存占用
      l3 U* L( q7 Y7 MMaster维护了系统中的元数据,包括文件及chunk命名空间、文件到chunk之间的
    7 [: F* x' e0 Z/ C! G映射、chunk副本的位置信息。其中前两种元数据需要持久化到磁盘,chunk副本的位, Z$ c) Y  \" p3 ?
    置信息不需要持久化,可以通过ChunkServer汇报获取。
    5 A" P% r% v+ N0 ~内存是Master的稀有资源,接下来介绍如何估算Master的内存使用量。chunk的元6 O7 M( c% ^( B, Y- g. m3 n- t' M
    信息包括全局唯一的ID、版本号、每个副本所在的ChunkServer编号、引用计数等。# k! p$ j( K" ]6 E
    GFS系统中每个chunk大小为64MB,默认存储3份,每个chunk的元数据小于64字节。% U2 j3 x) I- h' K8 J0 c" A& m9 Q
    那么1PB数据的chunk元信息大小不超过1PB×3/64MB×64=3GB。另外,Master对命名* {8 z( ^! j5 M  @. R
    空间进行了压缩存储,例如有两个文件foo1和foo2都存放在目
    5 @3 `' V4 c# y  r8 L% Q3 D) Y录/home/very_long_directory_name/中,那么目录名在内存中只需要存放一次。压缩存" d3 R& Y, u5 s7 W# W% `9 u
    储后,每个文件在文件命名空间的元数据也不超过64字节,由于GFS中的文件一般都" l, m) I, x$ a4 ~7 v4 x, K, N
    是大文件,因此,文件命名空间占用内存不多。这也就说明了Master内存容量不会成
    6 R7 g! ^( Z0 v: H7 N& k为GFS的系统瓶颈。
    6 d# f3 j6 ~- i% t$ g8 K* n2.负载均衡
    ) \% ?9 s- B( p  BGFS中副本的分布策略需要考虑多种因素,如网络拓扑、机架分布、磁盘利用率! U$ U& t+ l2 P# H2 B* b# n
    等。为了提高系统的可用性,GFS会避免将同一个chunk的所有副本都存放在同一个) \+ E+ U' `+ }; d
    机架的情况。! b4 w) E. N! f4 U8 D: B; E4 e
    系统中需要创建chunk副本的情况有三种:chunk创建、chunk复制(re-
    2 W$ f. z# Y3 X4 |+ T  ~+ ]replication)以及负载均衡(rebalancing)。
    : x* E+ m5 J; _" f当Master创建了一个chunk,它会根据如下因素来选择chunk副本的初始位置:1)
    , _' h* F6 T9 ?" h1 A# a+ x8 o& k新副本所在的ChunkServer的磁盘利用率低于平均水平;2)限制每个Chunk-Server“最, m* }$ @9 i  A2 v' w! Q5 |, j
    近”创建的数量;3)每个chunk的所有副本不能在同一个机架。第二点容易忽略但却
    5 ^* p5 T+ F# `. v% K$ \8 s很重要,因为创建完chunk以后通常需要马上写入数据,如果不限制“最近”创建的数6 w" S7 x6 G/ L- n
    量,当一台空的ChunkServer上线时,由于磁盘利用率低,可能导致大量的chunk瞬间
    & k" T  Y! @: M+ ^; o" S! }迁移到这台机器从而将它压垮。/ o& x% x. z! c( S2 H- {5 N% ~* H
    当chunk的副本数量小于一定的数量后,Master会尝试重新复制一个chunk副本。& w. q  }3 Q0 }  l& U
    可能的原因包括ChunkServer宕机或者ChunkServer报告自己的副本损坏,或者
    , e) J5 I0 g" y/ o3 Q) n, n* |ChunkServer的某个磁盘故障,或者用户动态增加了chunk的副本数,等等。每个chunk8 V# Z1 f% h$ V) T( ]* J
    复制任务都有一个优先级,按照优先级从高到低在Master排队等待执行。例如,只有
    : o7 j5 ]* n- z一个副本的chunk需要优先复制。另外,GFS会提高所有阻塞客户端操作的chunk复制
    4 t$ B. g8 z+ u' s( T任务的优先级,例如客户端正在往一个只有一个副本的chunk追加数据,如果限制至* f, Z2 O# ~% v
    少需要追加成功两个副本,那么这个chunk复制任务会阻塞客户端写操作,需要提高
    3 t1 t3 x/ h) v2 [2 k0 ^& z7 i优先级。  o, z8 q. w* D, E* r: Q* i! z
    最后,Master会定期扫描当前副本的分布情况,如果发现磁盘使用量或者机器负1 {! z7 M. E2 Z9 K
    载不均衡,将执行重新负载均衡操作。
    ; l7 I1 E  Q2 e无论是chunk创建,chunk重新复制,还是重新负载均衡,这些操作选择chunk副本
    ; P2 o0 f/ V+ q% V8 j位置的策略都是相同的,并且需要限制重新复制和重新负载均衡任务的拷贝速度,% R; O# v5 O. ^" d+ \8 g
    否则可能影响系统正常的读写服务。. d6 Z$ z# u0 C
    3.垃圾回收6 ^4 m. P! z/ c4 Q3 K( [/ Q
    GFS采用延迟删除的机制,也就是说,当删除文件后,GFS并不要求立即归还可
    & o5 Z* p9 f  h  }( D: g) F用的物理存储,而是在元数据中将文件改名为一个隐藏的名字,并且包含一个删除
    6 e# G2 a* U3 [4 \1 f时间戳。Master定时检查,如果发现文件删除超过一段时间(默认为3天,可配
    3 d4 c  J" n1 B% p- u置),那么它会把文件从内存元数据中删除,以后ChunkServer和Master的心跳消息
    6 A, h! y* c; p9 p+ I中,每一个ChunkServer都将报告自己的chunk集合,Master会回复在Master元数据中
    - W. h! S& J8 g2 X已经不存在的chunk信息,这时,ChunkServer会释放这些chunk副本。为了减轻系统的) A! G' w8 q3 p% ]
    负载,垃圾回收一般在服务低峰期执行,比如每天晚上凌晨1:00开始。% s7 u9 M1 ]: i0 M" L! O2 }  i0 c
    另外,chunk副本可能会因为ChunkServer失效期间丢失了对chunk的修改操作而导# ]# h; Y( D. X0 n
    致过期。系统对每个chunk都维护了版本号,过期的chunk可以通过版本号检测出来。6 f6 G$ k$ i+ j+ S/ P2 e- l
    Master仍然通过正常的垃圾回收机制来删除过期的副本。! b5 R5 S4 Y  H: K6 v
    4.快照" d, z: b, R  P* g
    快照(Snapshot)操作是对源文件/目录进行一个“快照”操作,生成该时刻源文' J2 A) t$ O9 U) |$ C$ i  V
    件/目录的一个瞬间状态存放于目标文件/目录中。GFS中使用标准的写时复制机制生2 ^5 f; g/ a/ Y2 p4 F$ T8 [
    成快照,也就是说,“快照”只是增加GFS中chunk的引用计数,表示这个chunk被快照
    " j# U" }$ @. {1 `5 K! \5 ~2 q" W文件引用了,等到客户端修改这个chunk时,才需要在ChunkServer中拷贝chunk的数据
    8 T7 w3 o2 p- d* c" f2 i生成新的chunk,后续的修改操作落到新生成的chunk上。, M; I0 G3 ^% m! L! N" |
    为了对某个文件做快照,首先需要停止这个文件的写服务,接着增加这个文件6 ~$ u2 w4 ^. Q% F* S
    的所有chunk的引用计数,以后修改这些chunk时会拷贝生成新的chunk。对某个文件执% ]5 ?" ?( [& R' r: ^( v* I7 O7 `9 Z
    行快照的大致步骤如下:9 U% O7 I! B0 q0 J% p; {0 d: G; W
    1)通过租约机制收回对文件的每个chunk写权限,停止对文件的写服务;% N/ k% o! \4 z; ~- U9 u
    2)Master拷贝文件名等元数据生成一个新的快照文件;
    + c8 h. g: w* |6 x3)对执行快照的文件的所有chunk增加引用计数。1 ~0 I- `  z3 U5 t% y
    例如,对文件foo执行快照操作生成foo_backup,foo在GFS中有三个chunk:C1、C2
    " U, n. M# P; l) U5 o/ \1 s5 t和C3(简单起见,假设每个chunk只有一个副本)。Master首先需要收回C1、C2和C3
    # z( F, x$ y! @& b+ n9 k% T的写租约,从而保证文件foo处于一致的状态,接着Master复制foo文件的元数据用于
    ! B* ^- f) G9 [! N! j生成foo_backup,foo_backup同样指向C1、C2和C3。快照前,C1、C2和C3只被一个文
    + h* \' F0 N) S+ P件foo引用,因此引用计数为1;执行快照操作后,这些chunk的引用计数增加为2。以! s  M5 v9 u& V- [4 [: h1 M
    后客户端再次向C3追加数据时,Master发现C3的引用计数大于1,通知C3所在的6 g0 c, T9 w# s- c8 X% a& E
    ChunkServer本次拷贝C3生成C3',客户端的追加操作也相应地转向C3'。
    ; x+ ^  U7 i2 H8 {* |2 T. {" V4.1.4 ChunkServer设计
    + H: A8 Y/ r" y* p5 AChunkServer管理大小约为64MB的chunk,存储的时候需要保证chunk尽可能均匀4 L5 ~  y/ z2 u4 P6 t, @! p
    地分布在不同的磁盘之中,需要考虑的可能因素包括磁盘空间、最近新建chunk数
    - _! w" `: r# g* ]7 u7 p  M" m等。另外,Linux文件系统删除64MB大文件消耗的时间太长且没有必要,因此,删除& ?. c, f7 T  s2 g
    chunk时可以只将对应的chunk文件移动到每个磁盘的回收站,以后新建chunk的时候可/ x# ^! @& R1 h' y2 B$ |
    以重用。. A7 I  T& B* h. G" D
    ChunkServer是一个磁盘和网络IO密集型应用,为了最大限度地发挥机器性能,
    # p5 o/ U: {3 _" p& s9 S需要能够做到将磁盘和网络操作异步化,但这会增加代码实现的难度。( E2 \$ o( b5 k
    4.1.5 讨论  X7 a, s: J: k3 w6 a- c0 i9 B1 J1 l
    从GFS的架构设计可以看出,GFS是一个具有良好可扩展性并能够在软件层面自
    + V* d* B$ ^5 e动处理各种异常情况的系统。Google是一家很重视自动化的公司,从早期的GFS,再9 Q1 q4 {9 e* {" F7 f( Q
    到Bigtable、Megastore,以及最近的Spanner,Google的分布式存储系统在这一点上一脉
    * t2 @, Q9 R. j' U( v" I相承。由于Google的系统一开始能很好地解决可扩展性问题,所以后续的系统能够7 N* z7 C( f& E5 }& ~
    构建在前一个系统之上并且一步一步引入新的功能,如Bigtable在GFS之上将海量数" q& {; u- Q) @$ P9 u
    据组织成表格形式,Megastore、Spanner又进一步在Bigtable之上融合一些关系型数据
    4 b! C# z+ M  O3 N6 j库的功能,整个解决方案完美华丽。
    9 q( e/ ^1 Z$ A% _自动化对系统的容错能力提出了很高的要求,在设计GFS时认为节点失效是常- K$ t* z9 Q% c; s' F
    态,通过在软件层面进行故障检测,并且通过chunk复制操作将原有故障节点的服务
    / ?' {: q5 J) |( C7 y. U迁移到新的节点。系统还会根据一定的策略,如磁盘使用情况、机器负载等执行负  C. i3 {: x- m
    载均衡操作。Google在软件层面的努力获得了巨大的回报,由于软件层面能够做到. v/ i  R; `1 \0 }! }, W: r- Q3 c
    自动化容错,底层的硬件可以采用廉价的错误率较高的硬件,比如廉价的SATA盘,
    ) j( ]. w& ~5 O) J  _4 w5 `0 X这大大降低了云服务的成本,在和其他厂商的竞争中表现出价格优势。比较典型的/ M. ?( f8 f- v  ?. ^5 v# r
    例子就是Google的邮箱服务,由于基础设施成本低,Gmail服务能够免费给用户提供% T6 G# A* [: a4 l+ b' f, H
    更大的容量,令其他厂商望尘莫及。; j- H( f) T- S$ k
    Google的成功经验也表明了一点:单Master的设计是可行的。单Master的设计不' _1 q- S$ R8 H6 [
    仅简化了系统,而且能够较好地实现一致性,后面我们将要看到的绝大多数分布式; [8 w7 N+ V' Z# o8 h
    存储系统都和GFS一样依赖单总控节点。然而,单Master的设计并不意味着实现GFS
    1 K2 |% f  W! o只是一些比较简单琐碎的工作。基于性能考虑,GFS提出了“记录至少原子性追加一
      k) T; u5 c1 b! g' \) i4 G/ x次”的一致性模型,通过租约的方式将每个chunk的修改授权下放到ChunkServer从而减
      T7 A6 A8 S6 ?& c4 c少Master的负载,通过流水线的方式复制多个副本以减少延时,追加流程复杂繁琐。3 E! L% |* _7 a( h, i# j- i: Y" V
    另外,Master维护的元数据有很多,需要设计高效的数据结构,占用内存小,并且能
    7 ~' _& U8 i' I$ N' J  ?( X够支持快照操作。支持写时复制的B树能够满足Master的元数据管理需求,然而,它% [) y  J2 V0 h6 ]$ M
    的实现是相当复杂的。
    * E8 G* L; [- o4 K; h3 F1 O
    ' h6 |+ |3 B# _/ U& c
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-2-23 11:48 , Processed in 0.108051 second(s), 29 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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