java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2316|回复: 0

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

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

    [LV.Master]出神入化

    2025

    主题

    3683

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66105

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

    发表于 2017-3-4 12:02:10 | 显示全部楼层 |阅读模式
    第6章 分布式表格系统9 }, }: L- A( Y/ }( H7 G6 h
    分布式表格系统对外提供表格模型,每个表格由很多行组成,通过主键唯一标
    , k! K: r' s/ l, U+ K识,每一行包含很多列。整个表格在系统中全局有序,适用3.3.2节中讲的顺序分6 m; F- Y- M" @" r0 x5 O
    布。& F$ N6 h5 Z0 Y
    Google Bigtable是分布式表格系统的始祖,它采用双层结构,底层采用GFS作为6 c" `: r. y& }8 U! O0 a; M
    持久化存储层。GFS+Bigtable双层架构是一种里程碑式的架构,其他系统,包括  k4 Z9 X7 J# x0 J. |" W5 y4 }/ m  Q
    Microsoft分布式存储系统Windows Azure Storage以及开源的Hadoop系统,均为其模仿
    + |1 k) m* H8 h8 t9 z者。Bigtable的问题在于对外接口不够丰富,因此,Google后续开发了两套系统,一. G7 f7 f3 N9 `+ X' [- T" H4 ^
    套是Megastore,构建在Bigtable之上,提供更加丰富的使用接口;另外一套是4 E$ M  V) `1 C4 P- J7 l
    Spanner,支持跨多个数据中心的数据库事务,下一章会专门介绍。) |8 o' x% c5 g5 r5 V. \+ u. g
    本章首先详细介绍Bigtable的架构及实现,接着分析Megastore的架构,最后介绍0 _% p5 H8 r" W6 L) f; j
    Microsoft Azure Storage的架构。
    ) R- @% `. S5 A1 B( _% v: L$ B. S& C6.1 Google Bigtable
    2 {5 A" }  D, ?) i/ c4 {+ m2 qBigtable是Google开发的基于GFS和Chubby的分布式表格系统。Google的很多数
    & r- A' v. C* f/ R# ^据,包括Web索引、卫星图像数据等在内的海量结构化和半结构化数据,都存储在
    * `0 j0 b8 A. \. `Bigtable中。与Google的其他系统一样,Bigtable的设计理念是构建在廉价的硬件之
    3 j8 v& ?3 A+ x7 J0 c7 ]上,通过软件层面提供自动化容错和线性可扩展性能力。6 V$ y7 M  n) t* Z# i
    Bigtable系统由很多表格组成,每个表格包含很多行,每行通过一个主键(Row9 N4 T4 e8 s. i, s
    Key)唯一标识,每行又包含很多列(Column)。某一行的某一列构成一个单元
    0 Z. X2 ]6 L" q3 p4 R  Z(Cell),每个单元包含多个版本的数据。整体上看,Bigtable是一个分布式多维映
    . Q: B  {; S4 Z7 o& ~射表,如下所示:
    ' |0 o+ N1 V6 A7 _  k% E1 M(row:string,column:string,timestamp:int64)->string1 _: e2 u; l1 J9 S  p4 }4 ^6 W% B
    另外,Bigtable将多个列组织成列族(column family),这样,列名由两个部分# y7 `( {* |' P0 o. J
    组成:(column family,qualifier)。列族是Bigtable中访问控制的基本单元,也就是+ B9 V* A' h0 F% P/ ~
    说,访问权限的设置是在列族这一级别上进行的。Bigtable中的列族在创建表格的时
    $ v6 S1 [: g5 h候需要预先定义好,个数也不允许过多;然而,每个列族包含哪些qualifier是不需要* J+ @; g' e9 S! V
    预先定义的,qualifier可以任意多个,适合表示半结构化数据。
    4 B: M; A$ b; F( dBigtable数据的存储格式如图6-1所示。! ~7 G+ C; y% H2 K: r% ?9 U2 k
    图 6-1 Bigtable数据存储格式
    . C  |# X2 X% n: Q" NBigtable中的行主键可以是任意的字符串,最大不超过64KB。Bigtable表中的数3 t/ E2 Z* i5 @* ?
    据按照行主键进行排序,排序使用的是字典序。图6-1中行主键com.cnn.www是域名
    / Q: q5 o7 p7 j3 Y& Wwww.cnn.com变换后的结果,这样做的好处是使得所有www.cnn.com下的子域名在系9 t: n& v9 C$ s7 F6 O  n( s( |
    统中连续存放。这一行数据包含两个列族:"contents"和"anchor"。其中,列
    * F9 l, F* P' F7 x族"anchor"又包含两个列,qualifier分别为"cnnsi.com"和"my:look.ca"。
    4 c2 {& y# c& iGoogle的很多服务,比如Web检索和用户的个性化设置,都需要保存不同时间的
    6 B# Z" ~& i! n( f- B数据,这些不同的数据版本必须通过时间戳来区分。图6-1中的t 4 、t 5 和t 6 表示保存了
    * n: n2 {( g  }三个时间点获取的网页。为了简化不同版本的数据管理,Bigtable提供了两种设置:
      T  U: \: L( Q$ R一种是保留最近的N个不同版本,另一种是保留限定时间内的所有不同版本,比如可
    2 N0 [+ R* B5 E3 w以保存最近10天的所有不同版本的数据。失效的版本将会由Bigtable的垃圾回收机制
    2 I/ G/ N; f. U0 m自动删除。
    8 c7 g$ J" ~' i3 E. M# C6.1.1 架构
    & k0 B$ ^" o! J3 Q- VBigtable构建在GFS之上,为文件系统增加一层分布式索引层。另外,Bigtable依
      G: U0 g+ y9 [1 n( K" s3 B赖Google的Chubby(即分布式锁服务)进行服务器选举及全局信息维护。' z. s5 s/ E( N& b8 K
    如图6-2所示,Bigtable将大表划分为大小在100~200MB的子表(tablet),每个
    " h- [' C& X' F0 N' h9 p  f子表对应一个连续的数据范围。Bigtable主要由三个部分组成:客户端程序库
    0 p: A9 B7 \" J+ W$ w3 P! a: Y(Client)、一个主控服务器(Master)和多个子表服务器(Tablet Server)。9 N: e/ E% [  F9 W; M7 w0 K, f  o
    图 6-2 Bigtable的整体架构
    : r' g6 {0 P: N2 |/ H, U●客户端程序库(Client):提供Bigtable到应用程序的接口,应用程序通过客户+ ~7 x+ i' X% V, {$ n8 f# U/ K7 {
    端程序库对表格的数据单元进行增、删、查、改等操作。客户端通过Chubby锁服务
    - T/ ]' `# f+ }$ O$ d/ ~8 U% ]% [获取一些控制信息,但所有表格的数据内容都在客户端与子表服务器之间直接传- G( M' f- ^6 u2 `! @
    送;8 d, h& `0 H( W- J# a! C
    ●主控服务器(Master):管理所有的子表服务器,包括分配子表给子表服务. Y. o% Z' B; v: E% N- R
    器,指导子表服务器实现子表的合并,接受来自子表服务器的子表分裂消息,监控
    ( q  a4 N+ ]2 j. |2 R9 b8 m: e/ E子表服务器,在子表服务器之间进行负载均衡并实现子表服务器的故障恢复等。- w5 x; t4 w6 U
    ●子表服务器(Tablet Server):实现子表的装载/卸出、表格内容的读和写,子
    + L' p+ j1 R, x表的合并和分裂。Tablet Server服务的数据包括操作日志以及每个子表上的sstable数( r6 V3 X0 c6 e) S0 m# W" B# H
    据,这些数据存储在底层的GFS中。' f  W* D5 ^. t
    Bigtable依赖于Chubby锁服务完成如下功能:) @) O0 f, K. u! j- d! X8 L
    1)选取并保证同一时间内只有一个主控服务器;
    - W% o; d9 X- u% q2)存储Bigtable系统引导信息;- g- a1 y  I& C( x# [
    3)用于配合主控服务器发现子表服务器加入和下线;
    ( {' s  [6 x$ y' y/ b7 ?3 O  E4)获取Bigtable表格的schema信息及访问控制信息。
    8 _/ {* Q8 L7 @# ]% V5 c: CChubby是一个分布式锁服务,底层的核心算法为Paxos。Paxos算法的实现过程需/ M5 u( s2 D/ q- B! i
    要一个“多数派”就某个值达成一致,进而才能得到一个分布式一致性状态。也就是
    6 ^6 s; i% m5 H( p说,只要一半以上的节点不发生故障,Chubby就能够正常提供服务。Chubby服务部2 f  F  ]5 [3 P5 ^
    署在多个数据中心,典型的部署为两地三数据中心五副本,同城的两个数据中心分% }$ r" _& E/ g
    别部署两个副本,异地的数据中心部署一个副本,任何一个数据中心整体发生故障& ^. k# R6 K/ a
    都不影响正常服务。$ m4 ?' K3 L6 s5 }- @5 o8 A
    Bigtable包含三种类型的表格:用户表(User Table)、元数据表(Meta Table)$ V0 l6 \8 l# i9 a8 |1 I
    和根表(Root Table)。其中,用户表存储用户实际数据;元数据表存储用户表的元
    3 M, L. x! Q; k4 y, g数据;如子表位置信息、SSTable及操作日志文件编号、日志回放点等,根表用来存
    * X: K) F* B3 L3 V: W储元数据表的元数据;根表的元数据,也就是根表的位置信息,又称为Bigtable引导
    6 |: @' W: B* |6 k- y' q/ u信息,存放在Chubby系统中。客户端、主控服务器以及子表服务器执行过程中都需
    # o$ S, e5 o; a1 c要依赖Chubby服务,如果Chubby发生故障,Bigtable系统整体不可用。
    8 Y1 d2 Y. V! K6 n" ?6.1.2 数据分布1 q8 Z8 T3 N7 o9 ]' l9 E6 N
    Bigtable中的数据在系统中切分为大小100~200MB的子表,所有的数据按照行
    : X, X; A! u! ~3 H! k主键全局排序。Bigtable中包含两级元数据,元数据表及根表。用户表在进行某些操$ ?( A+ j" k3 i( X5 X5 _, Y9 i
    作,比如子表分裂的时候需要修改元数据表,元数据表的某些操作又需要修改根
    ) W4 u! ~( T9 g4 z表。通过使用两级元数据,提高了系统能够支持的数据量。假设平均一个子表大小+ ?. F- z3 |- y& F, w( m& A% w
    为128MB,每个子表的元信息为1KB,那么一级元数据能够支持的数据量为8 |/ k. E- R7 Y  S- @
    128MB×(128MB/1KB)=16TB,两级元数据能够支持的数据量为
    # k# A% y9 h4 i/ ~16TB×(128MB/1KB)=2048 PB,满足几乎所有业务的数据量需求。如图6-3所示。
    5 C) I( ^  C! i6 c图 6-3 Bigtable数据结构
    / O  b4 J7 e3 `- B# T+ ?+ L5 M客户端查询时,首先从Chubby中读取根表的位置,接着从根表读取所需的元数
    6 T& F8 k- D- i$ \& M  ^" L据子表的位置,最后就可以从元数据子表中找到待查询的用户子表的位置。为了减
    6 `( x+ C/ B- h7 _4 c; d- L) ~2 _  G少访问开销,客户端使用了缓存(cache)和预取(prefetch)技术。子表的位置信息
    ) Q; K$ C  B. ~/ W  w( n被缓存在客户端,客户端在寻址时首先查找缓存,一旦缓存为空或者缓存信息过9 P" f* m) Q; I! _/ C
    期,客户端就需要请求子表服务器的上一级元数据表获取位置信息,比如用户子表
    - K5 x( {: b8 T7 ~  o* x# ]缓存过期需要请求元数据表,元数据子表缓存过期需要请求根表,根表缓存过期需( D( S% |/ E( u/ _) m2 A
    要读取Chubby中的引导信息。如果缓存为空,最多需要三次请求;如果缓存信息过% T: F7 n  K7 I5 z. E5 I( x' @
    期,最多需要六次请求,其中三次用来确定信息是过期的,另外三次获取新的地
    " ^) ~9 {6 K/ }8 E* S址。预取则是在每次访问元数据表时不仅仅读取所需的子表元数据,而是读取连续
    % {+ A8 @; a2 W" @6 q6 A9 N! S0 P! y的多个子表元数据,这样查找下一个子表时不需要再次访问元数据表。
    8 S2 k- f# c6 Z$ Y$ f8 N# u" q6.1.3 复制与一致性
    0 h6 [3 |1 [! e* s: HBigtable系统保证强一致性,同一个时刻同一个子表只能被一台Tablet Server服8 d/ o  C) M6 s6 t& {& O* x* q
    务,也就是说,Master将子表分配给某个Tablet Server服务时需要确保没有其他的5 j# {) Q& n# B) e* J6 P! k4 k
    Tablet Server正在服务这个子表。这是通过Chubby的互斥锁机制保证的,Tablet Server0 X5 H' y6 K/ |5 t/ K& p. r. d8 D
    启动时需要获取Chubby互斥锁,当Tablet Server出现故障,Master需要等到Tablet4 x$ `3 m/ l' d3 l  |3 {. M) t
    Server的互斥锁失效,才能把它上面的子表迁移到其他Tablet Server。& \8 E% r) K) V- X3 }
    Bigtable的底层存储系统为GFS(参见前面4.1节)。GFS本质上是一个弱一致性
    ' q  t0 m4 N4 @8 ]% F/ V+ ~* X系统,其一致性模型只保证“同一个记录至少成功写入一次”,但是可能存在重复记7 A! H) }" @7 V, i% K* ^+ }  r
    录,而且可能存在一些补零(padding)记录。; g0 j; Z- A8 O! t. @6 `1 j3 B
    Bigtable写入GFS的数据分为两种:
    ' m' a* Q; F7 ^$ n! ^●操作日志。当Tablet Server发生故障时,它上面服务的子表会被集群中的其他
    : }; S& h+ L; b; UTablet Server加载继续提供服务。加载子表可能需要回放操作日志,每条操作日志都
    " y) R  c2 q3 M% H: R4 ~  g4 b5 ^有唯一的序号,通过它可以去除重复的操作日志。
    2 x3 t8 N3 M/ ^% s3 ]" O# M●每个子表包含的SSTable数据。如果写入GFS失败可以重试并产生多条重复记" t+ ~1 p+ t! l' v0 }- i
    录,但是Bigtable只会索引最后一条写入成功的记录。
    + ]' _; J  v+ T! _# _( [Bigtable本质上是构建在GFS之上的一层分布式索引,通过它解决了GFS遗留的) R4 C; `* _" @( B$ c0 J; C+ \' J
    一致性问题,大大简化了用户使用。$ ^8 o$ b7 |5 }$ o
    6.1.4 容错
    $ Y+ F$ S0 U8 q9 E, O7 VBigtable中Master对Tablet Server的监控是通过Chubby完成的,Tablet Server在初始
    5 V% r3 L: ~- w' w4 Z化时都会从Chubby中获取一个独占锁。通过这种方式所有的Tablet Server基本信息被
      j6 N, G/ \9 k1 Q' h9 q9 I7 j" F保存在Chubby中一个称为服务器目录(Server Directory)的特殊目录之中。Master通
    : b  e! P; ]+ R. f过检测这个目录以随时获取最新的Tablet Server信息,包括目前活跃的Tablet Server,! W/ c) [* ?+ f
    以及每个Tablet Server上现已分配的子表。对于每个Tablet Server,Master会定期询问其
    ' D$ `! T6 P) `# @2 y独占锁的状态。如果Tablet Server的锁丢失或者没有回应,则此时可能有两种情况,
    * h, A  j& g" Q) @/ v要么是Chubby出现了问题,要么是Tablet Server出现了问题。对此Master首先自己尝
    9 V, d' x5 k: S$ q0 L* _试获取这个独占锁,如果失败说明是Chubby服务出现问题,否则说明是Tablet Server
    , Z0 @( A" D/ W5 `1 T8 ~+ }出现了问题。Master将中止这个Tablet Server并将其上的子表全部迁移到其他Tablet! b& u" b0 r- |+ u
    Server。' G  t$ o/ @; Y+ n2 _; c+ {
    每个子表持久化的数据包含两个部分:操作日志以及SSTable。Tablet Server发生
    - `3 a& m/ K" B" |; D  ?/ C故障时某些子表的一些更新操作还在内存中,需要通过回放操作日志来恢复。为了! a) p" H. |* a- U& ^1 A7 u( Q6 J
    提高性能,Tablet Server没有为它服务的每个子表写一个操作日志文件,而是把所有, Y* H* {. A5 G0 s) q" Q
    它服务的子表的操作日志混在一起写入GFS,每条日志通过<表格编号,行主键,日
    - e& j8 m7 _3 M1 ]志序列号>来唯一标识。当某个Tablet Server宕机后,Master将该Tablet Server服务的, b1 S2 D" q& `
    子表分配给其他Tablet Server。为了减少Tablet Server从GFS读取的日志数据量,, q6 f  F2 D/ n+ i2 V. S0 c
    Master将选择一些Tablet Server对日志进行分段排序。排好序后,同一个子表的操作
    7 \  e" q& P) ^- U日志连续存放,Tablet Server恢复某个子表时只需要读取该子表对应的操作日志即: ?& Z' k1 N) f" j  L8 P  k, ]
    可。Master需要尽可能选择负载低的Tablet Server执行排序,并且需要处理排序任务
    - {! X7 p' Z2 l. u. o+ d/ q- p失败的情况。
    $ P! n" u9 a2 M0 P1 WBigtable Master启动时需要从Chubby中获取一个独占锁,如果Master发生故障,9 Z' s; Q1 p7 g* n9 |/ ^9 w1 k
    Master的独占锁将过期,管理程序会自动指定一个新的Master服务器,它从Chubby成( P* O) B' c  T3 g
    功获取独占锁后可以继续提供服务。
    * ^. l" \9 |9 m* A9 Q( o! c6 i6.1.5 负载均衡
    & {  n7 d% r' M, c子表是Bigtable负载均衡的基本单位。Tablet Server定期向Master汇报状态,当状
    & l8 B& J; M  B( c态检测时发现某个Tablet Server上的负载过重时,Master会自动对其进行负载均衡,# _8 E' M0 W4 y9 G0 M% e- c
    即执行子表迁移操作。子表迁移分为两步:第一步请求原有的Tablet Server卸载子/ `) B: x& M  G, E3 o. S
    表;第二步选择一台负载较低的Tablet Server加载子表。Master发送命令请求原有的
    ; e* \; k/ I) J1 R- L6 a3 ~) {Tablet Server卸载子表,原有Tablet Server解除加在子表上的互斥锁,而新的Tablet
    & Q1 B: w& u6 D$ n$ X0 H) zServer加载子表时需要首先获取互斥锁。如果原有Tablet Server发生故障,新的Tablet
    ( ?1 W% F$ [0 H. S3 ?Server需要等待原有Tablet Server加在子表上的互斥锁过期。子表迁移前原有的Tablet. u, C  U0 F2 \$ R, ~/ \. d
    Server会对其执行Minor Compaction操作,将内存中的更新操作以SSTable文件的形式0 M2 U) e% s+ K+ G& p: G4 n
    转储到GFS中,因此,负载均衡带来的子表迁移在新的Tablet Server上不需要回放操
    , t( e# v6 r; P! [0 B6 V1 ]3 J作日志。( R& t1 K5 V6 n9 x4 f2 D
    子表迁移的过程中有短暂的时间需要停服务,为了尽可能减少停服务的时间,- r  R& C. S1 G( Y9 {! A- r& z
    Bigtable内部采用两次Minor Compaction的策略。具体操作如下:( s% Y& u, V7 m$ R+ S0 z
    1)原有Tablet Server对子表执行一次Minor Compaction操作,操作过程中仍然允' Q0 F  |0 i0 @0 r" S. ?
    许写操作。
    2 G( B+ e: ^7 i: F* V; C1 |9 v2)停止子表的写服务,对子表再次执行一次Minor Compaction操作。由于第一
    0 n+ @  @( t- `* p4 s次Minor Compaction过程中写入的数据一般比较少,第二次Minor Compaction的时间% a7 b2 m7 N( ?) u
    会比较短。
    3 Y) K6 J* V2 w6 P  \6 l; v由于Bigtable负载均衡的过程中会停一会读写服务,负载均衡策略不应当过于激& R" P8 i: w; o1 A% \7 p
    进。负载均衡涉及的因素很多,Tablet Server通过心跳定时将读、写个数、磁盘、内  x- m3 B- E0 y( [& b
    存负载等信息发送给Master,Master根据负载计算公式计算出需要迁移的子表,然后放, O( _" m/ ?% I& I- S) p0 X
    入迁移队列中等待执行。
    8 G* O8 P/ H! }! K. X& p" o/ r6.1.6 分裂与合并* e7 g8 V8 b+ Z
    随着数据不断写入和删除,某些子表可能太大,某些子表可能太小,需要执行
    / S- C: D* @+ T) N: D! @* g子表分裂与合并操作。顺序分布与哈希分布的区别在于哈希分布往往是静态的,而: V- S$ H+ w- Z. F  p( z
    顺序分布是动态的,需要通过分裂与合并操作动态调整。
    3 C; g) F6 ?3 P) KBigtable每个子表的数据分为内存中的MemTable和GFS中的多个SSTable,由于
    1 R. s/ N8 e2 E+ bBigtable中同一个子表只被一台Tablet Server服务,进行分裂时比较简单。Bigtable上
    2 ~, R1 B+ n, w执行分裂操作不需要进行实际的数据拷贝工作,只需要将内存中的索引信息分成两
    / E% w0 ~3 E2 {1 B份,比如分裂前子表的范围为(起始主键,结束主键],在内存中将索引分成(起始
    0 P$ X9 N7 v& _主键,分裂主键]和(分裂主键,结束主键]两个范围。例如,某个子表(1,10]的分
    9 g, D: n8 a% ~6 Q% s( K+ f裂主键为5,那么,分裂后生成的两个子表的数据范围为:(1,5]和(5,10]。分裂! v! m) B3 h: [3 |0 k, M$ o
    以后两个子表各自写不同的MemTable,等到执行Compaction操作时再根据分裂后的& I* e0 P+ J6 P0 u3 u
    子表范围生成不同的SSTable,无用的数据自然成为垃圾被回收。
    9 e, S& Q/ p; N0 g7 Q; u% J分裂操作由Tablet Server发起,需要修改元数据,即用户表的分裂需要修改元数
    ! c7 C' P, T# V' M# h据表,元数据表的分裂需要修改根表。分裂操作需要增加一个子表,相当于在元数
    " f& j9 B+ \7 [$ ]0 ^据表中增加一行,通过Bigtable的行事务保证原子性。只要修改元数据表成功,分裂3 h, y; t* B$ w9 M% ]
    操作就算成功。分裂成功后Tablet Server将向Master汇报,如果出现Tablet Server故
    9 W7 L! E2 E  {+ X0 {4 D( v  _% S障,Master可能丢失汇报分裂消息。新的Tablet Server加载这个子表时将发现它已经. p) ~0 l8 e# Q4 x% ^9 v; ]
    分裂,并通知Master。" F7 D" p& k4 @. i
    合并操作由Master发起,相比分裂操作要更加复杂。由于待合并的两个子表可能
    5 X* @5 @. D0 m' `5 }/ Z; \/ R" Y! d被不同的Tablet Server加载,合并的第一步需要迁移其中一个子表,以使它们在同一" ^' }" H3 Z9 W: O
    个Tablet Server上,接着通知Tablet Server执行子表合并。子表合并操作具体实现时非8 B4 o; N  m9 k5 h8 T" X* J
    常麻烦,有兴趣的读者可以自行思考。
    0 {1 W' @" Q. {: q% B$ @/ U6.1.7 单机存储: c7 _  c% M: @4 n4 L
    如图6-4所示,Bigtable采用Merge-dump存储引擎。数据写入时需要先写操作日' Q( C$ F5 e( ~# v
    志,成功后应用到内存中的MemTable中,写操作日志是往磁盘中的日志文件追加数
    ! b/ G! J$ U* K% Q5 j% [* l7 M' {据,很好地利用了磁盘设备的特性。当内存中的MemTable达到一定大小,需要将0 T# f* w2 f: D$ W0 s4 l# Q" V
    MemTable转储(Dump)到磁盘中生成SSTable文件。由于数据同时存在MemTable和
    ; a3 [# V( o: j6 `7 d3 S可能多个SSTable中,读取操作需要按从旧到新的时间顺序合并SSTable和内存中的
    " _2 m; ?( A4 N: \* J, wMemTable数据。数据在SSTable中连续存放,因此可以同时满足随机读取和顺序读取4 r  k) A7 a& {2 c/ m
    两种需求。为了防止磁盘中的SSTable文件过多,需要定时将多个SSTable通过: C( u5 Q/ P, y8 e/ l
    compaction过程合并为一个SSTable,从而减少后续读操作需要读取的文件个数。一
    7 t: e; [* Q0 K$ G! O般情况下,如果写操作比较少,我们总是能够使得对每一份数据同时只存在一个# f, L' N4 ^  E/ A0 _9 B$ c
    SSTable和一个MemTable,也就是说,随机读取和顺序读取都只需要访问一次磁盘,* l) j5 y! a, E' s+ _9 O; Z6 i
    这对于线上服务基本上都是成立的。
    ( @- r8 F( G( G1 x7 H3 ~( r5 x图 6-4 Bigtable单机存储引擎
    7 ]' [9 j+ {! Z2 p插入、删除、更新、增加(Add)等操作在Merge-dump引擎中都看成一回事,除
    & G2 @3 J" v6 D+ \, K' y了最早生成的SSTable外,SSTable中记录的只是操作,而不是最终的结果,需要等到
    6 J2 k7 {$ R2 t! s3 O读取(随机或者顺序)时才合并得到最终结果。9 _# h9 e  m! G% o) B
    Bigtable中包含三种Compaction策略:Minor Compaction、Merging Compaction和2 W  l5 T8 H( y$ W9 K
    Major Compaction。其中,Minor Compaction把内存中的MemTable转储到GFS中,; k2 f4 S: m) W- ?# C# |: S- {' Y/ N
    Merging Compaction和Major Compaction合并GFS中的多个SSTable文件生成一个更大
    # _4 k% p, r2 J4 p9 M& m: _' ^的SSTable。Minor Compaction主要是为了防止内存占用过多,Merging和Major
    ' ]7 i2 R! c! P: D- |+ z$ v" kCompaction则是为了防止读取文件个数过多。Major Compaction与Merging Compaction
    # M8 T. c8 I( S9 m( `4 K# e的区别在于Major Compaction会合并所有的SSTable文件和内存中的MemTable,生成
    , o3 @( R6 k1 p4 N  g$ {最终结果;而Merging Compaction生成的SSTable文件可能包含一些操作,比如删除、
    7 B$ N& y3 X. L  H' c( S& m增加等。
    ' I$ j! ]1 J/ u+ K数据在SSTable中按照主键有序存储,每个SSTable由若干个大小相近的数据块
    / @( ], ^4 w) i* l9 O! N' K" i  s(Block)组成,每个数据块包含若干行。数据块的大小一般在8~64KB之间,允许
    ' X4 r: m$ d9 d5 d: \2 g& D1 ^用户配置。Tablet Server的缓存包括两种:块缓存(Block Cache)和行缓存(Row
    ) ^- D$ d* F( V- J+ ^1 vCache)。其中,块缓存的单位为SSTable中的数据块,行缓存的单位为一行记录。随( M* f+ |+ j# n5 _2 @
    机读取时,首先查找行缓存;如果行缓存不命中,接着再查找块缓存。另外,6 X4 H0 W$ Z" g
    Bigtable还支持布隆过滤器(Bloom Filter),如果读取的数据行在SSTable中不存在,
    & p* z% h2 O7 Q( X' v( k  |可以通过布隆过滤器发现,从而避免一次读取GFS文件操作。( Z: F$ v( A8 L9 O! r5 h
    6.1.8 垃圾回收. b2 z4 [( @; l& N6 j  Y4 }
    Compaction后生成新的SSTable,原有的SSTable成为垃圾需要被回收掉。每个子) S0 p5 f8 ]  h' c0 h
    表正在引用的SSTable文件保存在元数据中。Master定期执行垃圾回收任务,这是一+ @1 ~: u" N& \) {
    个标记删除(mark-and-sweep)过程。首先扫描GFS获取所有的SSTable文件,接着扫4 M6 L1 ?9 D, @0 u  h6 ?& Y
    描根表和元数据表获取所有正在使用的SSTable文件,如果GFS中的SSTable没被任何
    1 g& T$ J0 G. z; t  ^* B一个子表使用,说明可以被回收掉。这里需要注意,由于Tablet Server执行
    4 c) z4 _- k7 O% `4 _+ YCompaction操作生成一个全新的SSTable与修改元数据这两个操作不是原子的,垃圾9 I2 T; N/ y& U+ Y  p
    回收需要避免删除刚刚生成但还没有记录到元数据中的SSTable文件。一种比较简单/ a4 i6 p! z3 i; Q
    的做法是垃圾回收只删除至少一段时间,比如1小时没有被使用的SSTable文件。5 D$ G# F' Q4 d& g& E- z, _3 P
    6.1.9 讨论! L/ _2 G  @$ a* C- M( B
    GFS+Bigtable两层架构以一种很优雅的方式兼顾系统的强一致性和可用性。底层
    ' k9 E$ d$ L! L( Y9 n文件系统GFS是弱一致性系统,可用性和性能很好,但是多客户端追加可能出现重复; a' I+ G' g+ Y( z+ M
    记录等数据不一致问题;上层的表格系统Bigtable通过多级分布式索引的方式使得系
    * H) f0 A4 {+ J6 |0 |" a统对外整体表现为强一致性。Bigtable最大的优势在于线性可扩展,单台机器出现故
    " C8 f( t4 q% R0 n障可将服务迅速(一分钟以内)迁移到整个集群。Bigtable架构最多可支持几千台的3 j- j! {7 o) E4 i
    集群规模,通过自动化容错技术大大降低了存储成本。
    + P7 H! t0 E. @, OBigtable架构也面临一些问题,如下所示:) q, u, w: p* e6 b8 z( C( q
    ●单副本服务。Bigtable架构非常适合离线或者半线上应用,然而,Tablet Server
    ( a5 L1 g6 T0 A1 O5 G$ c节点出现故障时部分数据短时间内无法提供读写服务,不适合实时性要求特别高的
    6 Q& s, ~7 D8 X! V3 }& L/ X业务,如交易类业务。' h9 N9 v  H  W/ w7 Z5 X
    ●SSD使用。Google整体架构的设计理念为通过廉价机器构建自动容错的大集' [* [( s, B2 }( G
    群,然而,随着SSD等硬件技术的发展,机器宕机的概率变得更小,SSD和SAS混合
    # X2 e$ t# k# u8 C8 n: q存储也变得比较常见,存储和服务分离的架构有些不太适应。0 ?- g1 S( P4 _- T& _. b8 k
    ●架构的复杂性导致Bug定位很难。Bigtable依赖GFS和Chubby,这些依赖系统本
    6 u8 R5 r+ Z, }身比较复杂,另外,Bigtable多级分布式索引和容错等机制内部实现都非常复杂,工* L& a& P" V9 C+ }. d
    程量巨大,使用的过程中如果发现问题很难定位。, F5 L& s2 F& x4 [
    总体上看,Bigtable架构把可扩展性和成本做到了极致,但在线实时服务能力有0 C/ T( {3 H! {4 S* r
    一定的改进空间,适合通用的离线和半线上应用场合。, s7 g  {& g. ?

    - F& i) i# y& I! E, A( A
    3 A' I, i, K* v% h# K+ S' s
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-7 03:07 , Processed in 0.067864 second(s), 29 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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