java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2498|回复: 0

《大规模分布式存储系统》第6章 分布式表格系统【6.1】

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

    [LV.Master]出神入化

    2025

    主题

    3683

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66345

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

    发表于 2017-3-4 12:02:10 | 显示全部楼层 |阅读模式
    第6章 分布式表格系统
    ! V! m' p9 p* D. ~分布式表格系统对外提供表格模型,每个表格由很多行组成,通过主键唯一标. n- a) U8 ?" z% n/ \) B
    识,每一行包含很多列。整个表格在系统中全局有序,适用3.3.2节中讲的顺序分! ^) B) V" X! b! R9 ]) i
    布。! Z% h/ V# ^, I
    Google Bigtable是分布式表格系统的始祖,它采用双层结构,底层采用GFS作为
    8 z! m% m* w( K, N/ o0 W' o持久化存储层。GFS+Bigtable双层架构是一种里程碑式的架构,其他系统,包括- D0 S; e0 t; z
    Microsoft分布式存储系统Windows Azure Storage以及开源的Hadoop系统,均为其模仿/ G  ~' c* n+ }7 |$ x3 |
    者。Bigtable的问题在于对外接口不够丰富,因此,Google后续开发了两套系统,一
    ; O( w4 h: _: v& }+ c+ P) x套是Megastore,构建在Bigtable之上,提供更加丰富的使用接口;另外一套是9 Y0 S0 u  S3 Y: z
    Spanner,支持跨多个数据中心的数据库事务,下一章会专门介绍。
    % z6 c; Z* ?. V) u7 A' a8 _本章首先详细介绍Bigtable的架构及实现,接着分析Megastore的架构,最后介绍
    : ^. t; t# {! n3 c, kMicrosoft Azure Storage的架构。
    $ ^5 |1 m0 C3 @3 r7 }6.1 Google Bigtable' |; L" a& k  V5 k7 R
    Bigtable是Google开发的基于GFS和Chubby的分布式表格系统。Google的很多数, O5 S0 C1 h% V6 ]% j1 V
    据,包括Web索引、卫星图像数据等在内的海量结构化和半结构化数据,都存储在( L" R0 j4 X2 q% V( o/ t9 P  {
    Bigtable中。与Google的其他系统一样,Bigtable的设计理念是构建在廉价的硬件之6 \; i7 B$ `2 l
    上,通过软件层面提供自动化容错和线性可扩展性能力。- B& k; f6 I" Q' V" @2 ]( q1 B
    Bigtable系统由很多表格组成,每个表格包含很多行,每行通过一个主键(Row; H! [8 E2 |7 a2 g9 N
    Key)唯一标识,每行又包含很多列(Column)。某一行的某一列构成一个单元7 V$ a$ F1 R+ P7 D
    (Cell),每个单元包含多个版本的数据。整体上看,Bigtable是一个分布式多维映' s& i3 T% B6 G. O( T1 G& _4 L; V
    射表,如下所示:( a- D/ f, w/ }- L+ d% q& [+ u
    (row:string,column:string,timestamp:int64)->string* E. ^3 i6 V% {3 B
    另外,Bigtable将多个列组织成列族(column family),这样,列名由两个部分
    4 a; a/ f7 y/ c& y0 r+ {1 M# V% Z  ~组成:(column family,qualifier)。列族是Bigtable中访问控制的基本单元,也就是. S6 `4 n$ @' j0 o9 x1 I
    说,访问权限的设置是在列族这一级别上进行的。Bigtable中的列族在创建表格的时
    6 i  a3 l+ V- V. t" i9 \: @' \候需要预先定义好,个数也不允许过多;然而,每个列族包含哪些qualifier是不需要
    4 j1 g! A! a. k" F预先定义的,qualifier可以任意多个,适合表示半结构化数据。
    # W  z* L' h: c+ Y  B: BBigtable数据的存储格式如图6-1所示。
    3 X/ y( s7 S3 b$ @图 6-1 Bigtable数据存储格式* W# f! N9 D& u) ^$ _( `
    Bigtable中的行主键可以是任意的字符串,最大不超过64KB。Bigtable表中的数
    & M" j9 F' _4 r. @8 s6 Z3 |1 U据按照行主键进行排序,排序使用的是字典序。图6-1中行主键com.cnn.www是域名
    # y' C7 [# Q7 K1 mwww.cnn.com变换后的结果,这样做的好处是使得所有www.cnn.com下的子域名在系
    " Q; E$ Y7 i/ o统中连续存放。这一行数据包含两个列族:"contents"和"anchor"。其中,列8 P1 Y$ W7 s# P; a
    族"anchor"又包含两个列,qualifier分别为"cnnsi.com"和"my:look.ca"。+ g, \7 ?! D3 _7 r8 _6 M) ]
    Google的很多服务,比如Web检索和用户的个性化设置,都需要保存不同时间的
    9 X8 b7 T! x+ w1 t' S数据,这些不同的数据版本必须通过时间戳来区分。图6-1中的t 4 、t 5 和t 6 表示保存了
    4 R9 d. o9 @& t0 e) `! e三个时间点获取的网页。为了简化不同版本的数据管理,Bigtable提供了两种设置:
    ) R" Q, [( \5 W; `  w+ O一种是保留最近的N个不同版本,另一种是保留限定时间内的所有不同版本,比如可
    $ w& t2 z: J! K+ s6 n以保存最近10天的所有不同版本的数据。失效的版本将会由Bigtable的垃圾回收机制: x" `' M/ H5 W" V9 o# V# H; B! m
    自动删除。3 c2 l% l/ z- x# @
    6.1.1 架构
    6 {: v( F5 O7 X3 |: B8 L7 j0 tBigtable构建在GFS之上,为文件系统增加一层分布式索引层。另外,Bigtable依
    - r) c; R8 L. O2 f6 n& E赖Google的Chubby(即分布式锁服务)进行服务器选举及全局信息维护。. W* q& E2 D% J* g9 s+ W0 [& A
    如图6-2所示,Bigtable将大表划分为大小在100~200MB的子表(tablet),每个7 M0 [, i; P3 I+ F
    子表对应一个连续的数据范围。Bigtable主要由三个部分组成:客户端程序库
    1 n5 y/ |* h6 W: q" o7 z' ?! B(Client)、一个主控服务器(Master)和多个子表服务器(Tablet Server)。
    * N" O; ?9 C- p( u' v8 G  E& G图 6-2 Bigtable的整体架构7 G3 s& \" `5 Q  Y4 i0 P( ?: m
    ●客户端程序库(Client):提供Bigtable到应用程序的接口,应用程序通过客户
    ( i2 e! |  ?* b2 {. X4 y端程序库对表格的数据单元进行增、删、查、改等操作。客户端通过Chubby锁服务
    % l  a0 l5 L* ^: N, L获取一些控制信息,但所有表格的数据内容都在客户端与子表服务器之间直接传
    - K# M" Z3 N' G/ z/ l3 t送;
    8 j( I6 A  f- p6 Y4 Q●主控服务器(Master):管理所有的子表服务器,包括分配子表给子表服务# T  r7 R5 h8 D( Q; E4 j9 t
    器,指导子表服务器实现子表的合并,接受来自子表服务器的子表分裂消息,监控( U- ?" P: K4 S/ i" l, |* t. N' [, _
    子表服务器,在子表服务器之间进行负载均衡并实现子表服务器的故障恢复等。
    2 C/ z; r: w' L& Q& D/ q* }$ H. L. t●子表服务器(Tablet Server):实现子表的装载/卸出、表格内容的读和写,子
    * c( B6 O* H# K. |0 D  T7 R  r表的合并和分裂。Tablet Server服务的数据包括操作日志以及每个子表上的sstable数6 v! z5 C+ n; t
    据,这些数据存储在底层的GFS中。, x/ J! U& z- ^) y8 [( b+ X
    Bigtable依赖于Chubby锁服务完成如下功能:& i1 q$ c) S8 b. |" e3 U
    1)选取并保证同一时间内只有一个主控服务器;* T2 a( R! F7 W* e9 e& P
    2)存储Bigtable系统引导信息;
    " t$ Z" f0 O% {4 L2 d" u3)用于配合主控服务器发现子表服务器加入和下线;
    ( K- j; l+ @/ B- O  c$ i8 R' ]7 A# V8 E4)获取Bigtable表格的schema信息及访问控制信息。2 a2 |* H% g% d3 V8 K
    Chubby是一个分布式锁服务,底层的核心算法为Paxos。Paxos算法的实现过程需
    ; ?/ T# @% \0 x要一个“多数派”就某个值达成一致,进而才能得到一个分布式一致性状态。也就是+ d# }3 T- R9 ?
    说,只要一半以上的节点不发生故障,Chubby就能够正常提供服务。Chubby服务部. o3 q  ?! G9 `" n- W2 T! E
    署在多个数据中心,典型的部署为两地三数据中心五副本,同城的两个数据中心分
    - P+ z' e" C4 V/ g9 o别部署两个副本,异地的数据中心部署一个副本,任何一个数据中心整体发生故障
    0 E, _+ k0 v$ L, i( k( w8 f都不影响正常服务。
    ) Y4 r7 @  c# X6 dBigtable包含三种类型的表格:用户表(User Table)、元数据表(Meta Table)
    7 v  g  o/ c* g$ T& B3 c和根表(Root Table)。其中,用户表存储用户实际数据;元数据表存储用户表的元# x# N; O7 @9 |, A6 E
    数据;如子表位置信息、SSTable及操作日志文件编号、日志回放点等,根表用来存
    6 q# K1 \% M8 z) m储元数据表的元数据;根表的元数据,也就是根表的位置信息,又称为Bigtable引导
    & g. j, C; i/ n# g( i信息,存放在Chubby系统中。客户端、主控服务器以及子表服务器执行过程中都需
    " t9 u: K) b* L: h8 ?要依赖Chubby服务,如果Chubby发生故障,Bigtable系统整体不可用。
    % _* X* J' x5 j. ]. [3 |9 w6.1.2 数据分布4 I( D. e) I3 ^& \! `) u; N5 J
    Bigtable中的数据在系统中切分为大小100~200MB的子表,所有的数据按照行" J* ?5 R) @& O  W4 _7 B# q
    主键全局排序。Bigtable中包含两级元数据,元数据表及根表。用户表在进行某些操
    : Z+ G% b$ O) X3 `作,比如子表分裂的时候需要修改元数据表,元数据表的某些操作又需要修改根
    % m9 n( S, ^$ s9 U表。通过使用两级元数据,提高了系统能够支持的数据量。假设平均一个子表大小8 R( q9 w+ W7 J! G
    为128MB,每个子表的元信息为1KB,那么一级元数据能够支持的数据量为
    0 t- J4 a1 z& l; l& Z0 Z: X% [128MB×(128MB/1KB)=16TB,两级元数据能够支持的数据量为& C) f! J6 W1 w- E) ^
    16TB×(128MB/1KB)=2048 PB,满足几乎所有业务的数据量需求。如图6-3所示。$ D% m; X- q1 L4 c
    图 6-3 Bigtable数据结构5 f7 I5 K5 M% ?
    客户端查询时,首先从Chubby中读取根表的位置,接着从根表读取所需的元数
    4 C; c6 |; R7 e据子表的位置,最后就可以从元数据子表中找到待查询的用户子表的位置。为了减
    5 @1 E, b6 }- H5 b% z4 q少访问开销,客户端使用了缓存(cache)和预取(prefetch)技术。子表的位置信息
    5 S- \0 Y. C5 Z/ m: M  ?3 b0 l被缓存在客户端,客户端在寻址时首先查找缓存,一旦缓存为空或者缓存信息过6 E/ \2 y5 B4 H) g9 z: _
    期,客户端就需要请求子表服务器的上一级元数据表获取位置信息,比如用户子表4 W& m2 {# g0 E4 U! B. l
    缓存过期需要请求元数据表,元数据子表缓存过期需要请求根表,根表缓存过期需, O' D4 l% @. n. ~
    要读取Chubby中的引导信息。如果缓存为空,最多需要三次请求;如果缓存信息过
    6 {( v( p6 i/ b  R期,最多需要六次请求,其中三次用来确定信息是过期的,另外三次获取新的地" p" S1 l4 m6 D0 H$ ^4 b0 I
    址。预取则是在每次访问元数据表时不仅仅读取所需的子表元数据,而是读取连续
    $ K% U' ~4 I- U* f) k, ?的多个子表元数据,这样查找下一个子表时不需要再次访问元数据表。! g/ {, i  q- m; h- `2 I
    6.1.3 复制与一致性
      l0 _6 P' c. v/ h3 yBigtable系统保证强一致性,同一个时刻同一个子表只能被一台Tablet Server服; k( F" L/ B# P0 ~" z8 s$ ~: l
    务,也就是说,Master将子表分配给某个Tablet Server服务时需要确保没有其他的8 `/ R: N; U; Z) H; C
    Tablet Server正在服务这个子表。这是通过Chubby的互斥锁机制保证的,Tablet Server$ a: t6 O0 Q% I
    启动时需要获取Chubby互斥锁,当Tablet Server出现故障,Master需要等到Tablet/ y* \9 V1 l( e6 {' @9 i
    Server的互斥锁失效,才能把它上面的子表迁移到其他Tablet Server。) B; E1 @9 Z3 ]# ~
    Bigtable的底层存储系统为GFS(参见前面4.1节)。GFS本质上是一个弱一致性
    % @" [3 V. P; O4 f: {: G系统,其一致性模型只保证“同一个记录至少成功写入一次”,但是可能存在重复记
    + i1 |5 W7 L# T% v) B7 {* }; t录,而且可能存在一些补零(padding)记录。
    2 F8 |2 s& e/ \4 @6 `/ U& ABigtable写入GFS的数据分为两种:5 L5 e/ a0 w3 p. q
    ●操作日志。当Tablet Server发生故障时,它上面服务的子表会被集群中的其他
    0 ~9 A: J3 P$ d; G4 g# X5 F) I  yTablet Server加载继续提供服务。加载子表可能需要回放操作日志,每条操作日志都
    , J  A! y6 H0 @有唯一的序号,通过它可以去除重复的操作日志。3 @9 _' b$ r7 [. t  S, W6 e. p9 D
    ●每个子表包含的SSTable数据。如果写入GFS失败可以重试并产生多条重复记
    2 J" e% h, i9 _6 E5 m录,但是Bigtable只会索引最后一条写入成功的记录。* A3 N  w+ G4 |! L
    Bigtable本质上是构建在GFS之上的一层分布式索引,通过它解决了GFS遗留的
    6 y7 x3 ~4 |8 U% T4 [8 M一致性问题,大大简化了用户使用。1 w$ @* g( r9 B- T
    6.1.4 容错. @: ]. v0 X3 H; Y
    Bigtable中Master对Tablet Server的监控是通过Chubby完成的,Tablet Server在初始
    " Z) n1 ~$ C5 o5 U化时都会从Chubby中获取一个独占锁。通过这种方式所有的Tablet Server基本信息被4 x, v1 i* ]. b7 W! K6 E4 f
    保存在Chubby中一个称为服务器目录(Server Directory)的特殊目录之中。Master通& T) l- l" s" n' m, Z) u4 q7 W
    过检测这个目录以随时获取最新的Tablet Server信息,包括目前活跃的Tablet Server,
    - W6 ]8 [* ?' b# t/ L3 V. s以及每个Tablet Server上现已分配的子表。对于每个Tablet Server,Master会定期询问其  m; R$ M4 r: k( @( R. q  E- w( _" S
    独占锁的状态。如果Tablet Server的锁丢失或者没有回应,则此时可能有两种情况,( g, M2 Y8 X8 D% ]0 [, e
    要么是Chubby出现了问题,要么是Tablet Server出现了问题。对此Master首先自己尝
    + F& o/ t. D9 j3 h+ I; S试获取这个独占锁,如果失败说明是Chubby服务出现问题,否则说明是Tablet Server
    8 z1 [$ R3 b! a7 s2 _+ u4 N出现了问题。Master将中止这个Tablet Server并将其上的子表全部迁移到其他Tablet
    ) U: f; k- V) [! X; D# l. oServer。
    2 u$ n1 w/ b% m- S每个子表持久化的数据包含两个部分:操作日志以及SSTable。Tablet Server发生
    3 n# p2 y0 e+ g3 _5 ~2 z, _: Z故障时某些子表的一些更新操作还在内存中,需要通过回放操作日志来恢复。为了8 @6 l, i# k! t+ [' j0 p& {- c/ J
    提高性能,Tablet Server没有为它服务的每个子表写一个操作日志文件,而是把所有. Y% E+ e# Y$ @9 f
    它服务的子表的操作日志混在一起写入GFS,每条日志通过<表格编号,行主键,日, y8 }  k: \5 U/ F
    志序列号>来唯一标识。当某个Tablet Server宕机后,Master将该Tablet Server服务的4 I9 @, u3 s; h/ W1 k
    子表分配给其他Tablet Server。为了减少Tablet Server从GFS读取的日志数据量,9 I- m* }4 c" j* s
    Master将选择一些Tablet Server对日志进行分段排序。排好序后,同一个子表的操作
    & n* o' \$ q1 `5 J) I2 z日志连续存放,Tablet Server恢复某个子表时只需要读取该子表对应的操作日志即! S8 r, m' e$ o  q$ S
    可。Master需要尽可能选择负载低的Tablet Server执行排序,并且需要处理排序任务" t# U. U- R5 c) v8 F
    失败的情况。% P& `+ k. ^% _
    Bigtable Master启动时需要从Chubby中获取一个独占锁,如果Master发生故障,/ l4 K" V& p+ @* \9 u/ _
    Master的独占锁将过期,管理程序会自动指定一个新的Master服务器,它从Chubby成  W  e5 J6 v" o0 r& s. G8 z- p; @
    功获取独占锁后可以继续提供服务。# r/ D2 j8 C0 a
    6.1.5 负载均衡
    * v4 j) f5 K8 M* t7 n& |8 q- w  G子表是Bigtable负载均衡的基本单位。Tablet Server定期向Master汇报状态,当状9 v4 i+ Z4 u! M) x
    态检测时发现某个Tablet Server上的负载过重时,Master会自动对其进行负载均衡,
    ' c6 G$ O  y  y0 E& w即执行子表迁移操作。子表迁移分为两步:第一步请求原有的Tablet Server卸载子
    * h  i( x5 Q: W% k' r6 Q表;第二步选择一台负载较低的Tablet Server加载子表。Master发送命令请求原有的
    8 U7 x6 {( y0 O, Z, k" L# qTablet Server卸载子表,原有Tablet Server解除加在子表上的互斥锁,而新的Tablet
    0 ]4 r" ]$ q4 E/ _) zServer加载子表时需要首先获取互斥锁。如果原有Tablet Server发生故障,新的Tablet& S' L( U( f, q" I( {8 [
    Server需要等待原有Tablet Server加在子表上的互斥锁过期。子表迁移前原有的Tablet
    8 `5 ^3 g4 I2 ^Server会对其执行Minor Compaction操作,将内存中的更新操作以SSTable文件的形式) U1 ]4 e3 J/ \+ H
    转储到GFS中,因此,负载均衡带来的子表迁移在新的Tablet Server上不需要回放操/ n; M  N3 o& h
    作日志。5 [1 ]) n4 Q0 E, b! Z
    子表迁移的过程中有短暂的时间需要停服务,为了尽可能减少停服务的时间,
    * J+ b  q0 @  q0 B) TBigtable内部采用两次Minor Compaction的策略。具体操作如下:7 [' R! z5 n& Q1 X! O. k' j4 b
    1)原有Tablet Server对子表执行一次Minor Compaction操作,操作过程中仍然允
    : ~. t) ]4 r3 f; b许写操作。. Y% J  x& P( |0 Q
    2)停止子表的写服务,对子表再次执行一次Minor Compaction操作。由于第一
    ) ~8 Y% A- T5 ~/ [- ~- T次Minor Compaction过程中写入的数据一般比较少,第二次Minor Compaction的时间
    + R$ E9 t* E/ l  T6 w1 @: r4 `3 D会比较短。
    $ f) P, j  }8 [由于Bigtable负载均衡的过程中会停一会读写服务,负载均衡策略不应当过于激
    , q3 l3 c( w6 x2 j进。负载均衡涉及的因素很多,Tablet Server通过心跳定时将读、写个数、磁盘、内: s" E( j* C% @7 n9 b. D. p6 E
    存负载等信息发送给Master,Master根据负载计算公式计算出需要迁移的子表,然后放
    8 T/ v7 R5 A2 n; m1 c3 f5 T6 \入迁移队列中等待执行。
    4 W: k/ ]8 ]5 z+ r+ v; X* I- j# o6.1.6 分裂与合并9 N+ Z! F( |( `- w: j" _( G* ]
    随着数据不断写入和删除,某些子表可能太大,某些子表可能太小,需要执行7 h5 `1 Q: {5 H) c% k
    子表分裂与合并操作。顺序分布与哈希分布的区别在于哈希分布往往是静态的,而
    $ s& z& _5 l" S) {5 n7 C5 p) h顺序分布是动态的,需要通过分裂与合并操作动态调整。" N# B, z5 x( Y. Z
    Bigtable每个子表的数据分为内存中的MemTable和GFS中的多个SSTable,由于
    6 Q8 \( q# ?" i& z4 C% s+ [Bigtable中同一个子表只被一台Tablet Server服务,进行分裂时比较简单。Bigtable上, {: Z2 @. f/ g; c+ O2 m5 F* i. {
    执行分裂操作不需要进行实际的数据拷贝工作,只需要将内存中的索引信息分成两
    ( c7 \7 O$ I1 ^+ T7 R+ Y份,比如分裂前子表的范围为(起始主键,结束主键],在内存中将索引分成(起始  t3 o' p/ Z- A, S# h- F
    主键,分裂主键]和(分裂主键,结束主键]两个范围。例如,某个子表(1,10]的分
    ; b# ^1 Y" E9 ]( [& V4 o7 Y裂主键为5,那么,分裂后生成的两个子表的数据范围为:(1,5]和(5,10]。分裂4 z/ J7 F% j( E3 o6 M
    以后两个子表各自写不同的MemTable,等到执行Compaction操作时再根据分裂后的; l1 V) K: C0 q* [) @$ W. f
    子表范围生成不同的SSTable,无用的数据自然成为垃圾被回收。
    - K' K+ e+ k, Z2 y分裂操作由Tablet Server发起,需要修改元数据,即用户表的分裂需要修改元数* b' Z7 |3 e& e+ ^: Z
    据表,元数据表的分裂需要修改根表。分裂操作需要增加一个子表,相当于在元数
    & q% J: S9 k5 X0 X据表中增加一行,通过Bigtable的行事务保证原子性。只要修改元数据表成功,分裂% v9 M7 M6 _8 A' b! B
    操作就算成功。分裂成功后Tablet Server将向Master汇报,如果出现Tablet Server故* X0 w; E- q+ [  O) C% r
    障,Master可能丢失汇报分裂消息。新的Tablet Server加载这个子表时将发现它已经
    $ d: Z& V; ?4 j! D分裂,并通知Master。
    # q( K/ |' [7 ~! Y合并操作由Master发起,相比分裂操作要更加复杂。由于待合并的两个子表可能, a/ `0 ], x# q# R( q
    被不同的Tablet Server加载,合并的第一步需要迁移其中一个子表,以使它们在同一
    # K' S6 o% X4 E& c5 ~0 X5 c' [个Tablet Server上,接着通知Tablet Server执行子表合并。子表合并操作具体实现时非& Y9 @" t/ @) @. _
    常麻烦,有兴趣的读者可以自行思考。
    7 |5 L7 u& H, x2 F0 w$ d) T: U6.1.7 单机存储2 S6 X! N  h) F. s  p
    如图6-4所示,Bigtable采用Merge-dump存储引擎。数据写入时需要先写操作日* o* d" X. i) c% D! e6 V5 w; A
    志,成功后应用到内存中的MemTable中,写操作日志是往磁盘中的日志文件追加数
    " w$ I  o0 {0 s8 Z据,很好地利用了磁盘设备的特性。当内存中的MemTable达到一定大小,需要将
    9 k: n  D; K( U, g) {4 b! q* A/ R% P( GMemTable转储(Dump)到磁盘中生成SSTable文件。由于数据同时存在MemTable和
    6 a! V* b' s: n2 p% K  i( D# u可能多个SSTable中,读取操作需要按从旧到新的时间顺序合并SSTable和内存中的4 T  I; g- H$ w' j: k" @6 F6 u
    MemTable数据。数据在SSTable中连续存放,因此可以同时满足随机读取和顺序读取0 A( W9 a& Y5 p7 l+ E! \0 K
    两种需求。为了防止磁盘中的SSTable文件过多,需要定时将多个SSTable通过
    4 U; r) v* e' v; a4 q: _5 ?6 Z- @compaction过程合并为一个SSTable,从而减少后续读操作需要读取的文件个数。一
    3 p7 F. ^! J* L4 [5 u' k般情况下,如果写操作比较少,我们总是能够使得对每一份数据同时只存在一个6 ?5 t0 C5 X& G1 c
    SSTable和一个MemTable,也就是说,随机读取和顺序读取都只需要访问一次磁盘,
    / ]/ t& X) l/ Y$ ^这对于线上服务基本上都是成立的。6 g0 [9 ~# R. H5 g( N/ h
    图 6-4 Bigtable单机存储引擎0 z" b* O7 {( l! m- i" d' u
    插入、删除、更新、增加(Add)等操作在Merge-dump引擎中都看成一回事,除
    / t$ w% F0 @! E% G, v* }了最早生成的SSTable外,SSTable中记录的只是操作,而不是最终的结果,需要等到* a0 |. [0 S9 ^  t" R+ ]5 u
    读取(随机或者顺序)时才合并得到最终结果。3 Q. Z  E- I$ d7 ^+ D: X2 c
    Bigtable中包含三种Compaction策略:Minor Compaction、Merging Compaction和3 A+ `4 i/ P; N3 H6 D
    Major Compaction。其中,Minor Compaction把内存中的MemTable转储到GFS中,
    * Y3 G5 |! r. d* Q  fMerging Compaction和Major Compaction合并GFS中的多个SSTable文件生成一个更大, Q. W1 C4 Y  ]9 N  l9 u
    的SSTable。Minor Compaction主要是为了防止内存占用过多,Merging和Major
    2 h1 ~# p, ^0 l+ f& NCompaction则是为了防止读取文件个数过多。Major Compaction与Merging Compaction3 e* F. n7 O% f6 t- _; ?
    的区别在于Major Compaction会合并所有的SSTable文件和内存中的MemTable,生成! B7 M( X% T2 n& o
    最终结果;而Merging Compaction生成的SSTable文件可能包含一些操作,比如删除、$ \& A6 X$ s- R+ Q$ H
    增加等。# ^. {: D/ V- E9 x5 X* U: k
    数据在SSTable中按照主键有序存储,每个SSTable由若干个大小相近的数据块
    ( L+ F& V# ?8 Q# T( c(Block)组成,每个数据块包含若干行。数据块的大小一般在8~64KB之间,允许0 b0 a' K$ D; K* y/ k) |
    用户配置。Tablet Server的缓存包括两种:块缓存(Block Cache)和行缓存(Row
    : w+ E; a- ~, I# b; h6 l0 v/ |Cache)。其中,块缓存的单位为SSTable中的数据块,行缓存的单位为一行记录。随! R( y# Y# ]0 w1 _
    机读取时,首先查找行缓存;如果行缓存不命中,接着再查找块缓存。另外,: \9 t) j# p+ [1 y
    Bigtable还支持布隆过滤器(Bloom Filter),如果读取的数据行在SSTable中不存在,* `3 M, H, h6 P) R
    可以通过布隆过滤器发现,从而避免一次读取GFS文件操作。
    / Z: Z  j5 O" [/ ]% p6.1.8 垃圾回收. R& @& O; g( N( J
    Compaction后生成新的SSTable,原有的SSTable成为垃圾需要被回收掉。每个子' v/ y1 Z) v8 Z6 p
    表正在引用的SSTable文件保存在元数据中。Master定期执行垃圾回收任务,这是一" y( \5 A6 n1 W% M3 i3 C- l+ M) c
    个标记删除(mark-and-sweep)过程。首先扫描GFS获取所有的SSTable文件,接着扫0 [, J) c" m0 U! u2 d
    描根表和元数据表获取所有正在使用的SSTable文件,如果GFS中的SSTable没被任何2 g8 Z( O! D2 \: v' ?( G' M0 A
    一个子表使用,说明可以被回收掉。这里需要注意,由于Tablet Server执行
    ; _& ^! t- ~1 P: U& }" U+ @3 C. G" E, aCompaction操作生成一个全新的SSTable与修改元数据这两个操作不是原子的,垃圾) H4 l) X+ g7 O# l% L
    回收需要避免删除刚刚生成但还没有记录到元数据中的SSTable文件。一种比较简单2 h2 f+ Z- P8 `0 ~- B4 t  q) e! r- M
    的做法是垃圾回收只删除至少一段时间,比如1小时没有被使用的SSTable文件。
    * k0 P  t8 f& T9 C6.1.9 讨论
    6 ]5 t6 \  y" l" h: P8 F) gGFS+Bigtable两层架构以一种很优雅的方式兼顾系统的强一致性和可用性。底层
    , b8 F) u, d" h3 T( o  Z文件系统GFS是弱一致性系统,可用性和性能很好,但是多客户端追加可能出现重复
    . o% e) [# W0 q5 ~. U记录等数据不一致问题;上层的表格系统Bigtable通过多级分布式索引的方式使得系
      D6 b/ m2 G. S6 P, @6 Q统对外整体表现为强一致性。Bigtable最大的优势在于线性可扩展,单台机器出现故9 T0 }' ^$ Z. W6 J  z
    障可将服务迅速(一分钟以内)迁移到整个集群。Bigtable架构最多可支持几千台的4 g. z+ }% a; b) ?
    集群规模,通过自动化容错技术大大降低了存储成本。
    8 h1 \' w" l- a4 iBigtable架构也面临一些问题,如下所示:) ]% V" G5 W" j4 }) {* ~/ K
    ●单副本服务。Bigtable架构非常适合离线或者半线上应用,然而,Tablet Server
    - V' c* [/ F3 U4 j/ Z7 Y- |( z3 \" ?节点出现故障时部分数据短时间内无法提供读写服务,不适合实时性要求特别高的7 V4 j8 z0 Y( G
    业务,如交易类业务。
    + r: H* n5 D$ t●SSD使用。Google整体架构的设计理念为通过廉价机器构建自动容错的大集2 n3 U6 b8 e- f& R  M1 r
    群,然而,随着SSD等硬件技术的发展,机器宕机的概率变得更小,SSD和SAS混合
    : D! |; W3 T! s* q" U& M存储也变得比较常见,存储和服务分离的架构有些不太适应。8 ?2 r, ?' r8 h* S, c* }; `
    ●架构的复杂性导致Bug定位很难。Bigtable依赖GFS和Chubby,这些依赖系统本
    . M# X' W; n7 J: a, U$ X身比较复杂,另外,Bigtable多级分布式索引和容错等机制内部实现都非常复杂,工* @0 ?: c" t! J. u- T
    程量巨大,使用的过程中如果发现问题很难定位。
    9 G& S% E2 {% m总体上看,Bigtable架构把可扩展性和成本做到了极致,但在线实时服务能力有
    3 b8 Q4 }# @* ^9 k/ h# V! v一定的改进空间,适合通用的离线和半线上应用场合。) G, E! h$ t) {: {
    ) E$ g9 ^! _( _& z4 E

    4 s3 G7 V4 F; ?' k$ N
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-11-21 21:06 , Processed in 0.182502 second(s), 33 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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