java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2609|回复: 0

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

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

    [LV.Master]出神入化

    2096

    主题

    3754

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66788

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

    发表于 2017-3-4 12:02:10 | 显示全部楼层 |阅读模式
    第6章 分布式表格系统
    ) o3 Y5 t4 Q! ~! l% a3 \分布式表格系统对外提供表格模型,每个表格由很多行组成,通过主键唯一标
    * p) v& Z" P4 z) P- ]! n识,每一行包含很多列。整个表格在系统中全局有序,适用3.3.2节中讲的顺序分' ?2 z( d' D7 g. |: b9 a' E+ ?- T
    布。
    & c1 r5 |' Y  oGoogle Bigtable是分布式表格系统的始祖,它采用双层结构,底层采用GFS作为
    : ]$ G9 K$ m3 k9 E2 B9 H4 A5 _; X持久化存储层。GFS+Bigtable双层架构是一种里程碑式的架构,其他系统,包括  X5 g8 n6 r' v* K1 f  @& ~
    Microsoft分布式存储系统Windows Azure Storage以及开源的Hadoop系统,均为其模仿7 a; s$ @/ u- l
    者。Bigtable的问题在于对外接口不够丰富,因此,Google后续开发了两套系统,一
    $ ?1 X/ |3 N; B套是Megastore,构建在Bigtable之上,提供更加丰富的使用接口;另外一套是
    , b# i0 u/ e8 pSpanner,支持跨多个数据中心的数据库事务,下一章会专门介绍。& q) x4 Y) y1 N! i+ q  v& R1 Y
    本章首先详细介绍Bigtable的架构及实现,接着分析Megastore的架构,最后介绍
    & b8 l( z; y7 [: r, M+ SMicrosoft Azure Storage的架构。
    ) g& T$ L; M$ Q* o8 H6.1 Google Bigtable
    6 s0 a0 j/ g( {6 q5 `6 Z& OBigtable是Google开发的基于GFS和Chubby的分布式表格系统。Google的很多数4 A& y8 W- q# D1 ?' T
    据,包括Web索引、卫星图像数据等在内的海量结构化和半结构化数据,都存储在
    3 U* \# P6 o7 C" X4 W* h: wBigtable中。与Google的其他系统一样,Bigtable的设计理念是构建在廉价的硬件之* D( w- e* q" q$ k+ _8 x% Q
    上,通过软件层面提供自动化容错和线性可扩展性能力。" t4 Y. |5 O+ R, V' S
    Bigtable系统由很多表格组成,每个表格包含很多行,每行通过一个主键(Row8 y( d8 t' g' o$ y% `1 p1 F; `
    Key)唯一标识,每行又包含很多列(Column)。某一行的某一列构成一个单元* i7 Q1 S! O3 i: _
    (Cell),每个单元包含多个版本的数据。整体上看,Bigtable是一个分布式多维映
      E. U( R7 D  J2 V4 V射表,如下所示:& v$ `; m: N) P' F' Y
    (row:string,column:string,timestamp:int64)->string4 |' M1 C. v( D' t4 u$ @5 l3 B
    另外,Bigtable将多个列组织成列族(column family),这样,列名由两个部分; B% L% K4 f9 [5 D' C
    组成:(column family,qualifier)。列族是Bigtable中访问控制的基本单元,也就是- d3 G6 d, E& z3 ]. P( `5 a
    说,访问权限的设置是在列族这一级别上进行的。Bigtable中的列族在创建表格的时2 u) H; G8 B# P2 }, k
    候需要预先定义好,个数也不允许过多;然而,每个列族包含哪些qualifier是不需要
    1 b4 x0 l4 c3 R  `3 V! ~$ a预先定义的,qualifier可以任意多个,适合表示半结构化数据。
    ! g; |5 R+ Z# N; [Bigtable数据的存储格式如图6-1所示。
    8 C& I9 @0 ?; x图 6-1 Bigtable数据存储格式
    5 o9 p$ I9 _- ]; i1 qBigtable中的行主键可以是任意的字符串,最大不超过64KB。Bigtable表中的数
    + m* ^0 g* }7 j据按照行主键进行排序,排序使用的是字典序。图6-1中行主键com.cnn.www是域名
    8 s  g, K4 a" n+ L, V. L0 {www.cnn.com变换后的结果,这样做的好处是使得所有www.cnn.com下的子域名在系. S3 y& X% g7 ?" G
    统中连续存放。这一行数据包含两个列族:"contents"和"anchor"。其中,列2 X- T4 \$ Q( m2 E: }9 T5 z
    族"anchor"又包含两个列,qualifier分别为"cnnsi.com"和"my:look.ca"。  t$ T- M' z( C) ?1 d; p
    Google的很多服务,比如Web检索和用户的个性化设置,都需要保存不同时间的
    - c/ L) V; H$ h, C数据,这些不同的数据版本必须通过时间戳来区分。图6-1中的t 4 、t 5 和t 6 表示保存了) ^4 N$ G3 ^- D2 I
    三个时间点获取的网页。为了简化不同版本的数据管理,Bigtable提供了两种设置:
    $ n' W1 U6 M6 n9 k0 C一种是保留最近的N个不同版本,另一种是保留限定时间内的所有不同版本,比如可
    3 c* M5 K+ B' \$ L$ y以保存最近10天的所有不同版本的数据。失效的版本将会由Bigtable的垃圾回收机制- R" v! _6 `$ H. a  ~; q$ @0 s- }
    自动删除。& p- `% @( h: ?! F0 V8 M! j( m0 X
    6.1.1 架构# y$ G& E* C' h) V! s3 i
    Bigtable构建在GFS之上,为文件系统增加一层分布式索引层。另外,Bigtable依
    6 Q1 k; q$ P7 h- }5 p' i赖Google的Chubby(即分布式锁服务)进行服务器选举及全局信息维护。
    ' k3 j, j+ U9 d+ V9 K, s+ q如图6-2所示,Bigtable将大表划分为大小在100~200MB的子表(tablet),每个
    " c1 e1 r! u* Z) s7 n& u/ x# M子表对应一个连续的数据范围。Bigtable主要由三个部分组成:客户端程序库, T0 {. B# z  \; s' q
    (Client)、一个主控服务器(Master)和多个子表服务器(Tablet Server)。
    % L* M% {& t, F  Z2 [4 M. e$ `/ O* r: K图 6-2 Bigtable的整体架构
    , W: c3 p$ W7 q8 K0 e6 x* o●客户端程序库(Client):提供Bigtable到应用程序的接口,应用程序通过客户* ]9 V' J, B5 ^
    端程序库对表格的数据单元进行增、删、查、改等操作。客户端通过Chubby锁服务9 h# u7 W* y5 N. v/ v
    获取一些控制信息,但所有表格的数据内容都在客户端与子表服务器之间直接传
    # x. M6 D: X5 ?! l. y送;2 C, s6 t8 l4 I; i! v( ]1 |
    ●主控服务器(Master):管理所有的子表服务器,包括分配子表给子表服务$ K) |$ a4 J/ O7 ?+ {3 M# F
    器,指导子表服务器实现子表的合并,接受来自子表服务器的子表分裂消息,监控$ M5 e" `' x. M  ~
    子表服务器,在子表服务器之间进行负载均衡并实现子表服务器的故障恢复等。
    % @' j1 x' t* J3 P  Q5 w, G% C1 p●子表服务器(Tablet Server):实现子表的装载/卸出、表格内容的读和写,子; o3 ?  z0 C/ T! b& W
    表的合并和分裂。Tablet Server服务的数据包括操作日志以及每个子表上的sstable数1 ~( n9 S! C, `& m0 h2 a7 Y1 `
    据,这些数据存储在底层的GFS中。' U3 c( t/ e- N& g4 i+ A$ p7 A; U
    Bigtable依赖于Chubby锁服务完成如下功能:
    ! ?4 }; @3 I2 e: l8 W1)选取并保证同一时间内只有一个主控服务器;
    ) R: p! y0 [9 o6 w2)存储Bigtable系统引导信息;
    ; Q, E" S- s' Z3)用于配合主控服务器发现子表服务器加入和下线;
    ' [- z/ W6 A. T$ F& w. v9 U" Q4)获取Bigtable表格的schema信息及访问控制信息。' P  v; F) s# L; H0 j6 Q
    Chubby是一个分布式锁服务,底层的核心算法为Paxos。Paxos算法的实现过程需! _3 H2 Q' r9 M" ^* U0 ^) s& |
    要一个“多数派”就某个值达成一致,进而才能得到一个分布式一致性状态。也就是
    5 j$ W- b( J' c& a% h" a+ n- B* V说,只要一半以上的节点不发生故障,Chubby就能够正常提供服务。Chubby服务部: n5 T7 Q2 L' t5 s0 W, g! w
    署在多个数据中心,典型的部署为两地三数据中心五副本,同城的两个数据中心分
    9 M+ z; G' b' I2 y6 R) A别部署两个副本,异地的数据中心部署一个副本,任何一个数据中心整体发生故障
    6 w' i; [- s. [7 I* x# ~5 Z  c9 s都不影响正常服务。  {: a) l+ \# {9 c; K, M% g. J
    Bigtable包含三种类型的表格:用户表(User Table)、元数据表(Meta Table)4 {- i- o" P$ H& D: r
    和根表(Root Table)。其中,用户表存储用户实际数据;元数据表存储用户表的元. H" |* d2 i5 G0 o, p
    数据;如子表位置信息、SSTable及操作日志文件编号、日志回放点等,根表用来存
      m2 |2 o  g3 y& U/ m储元数据表的元数据;根表的元数据,也就是根表的位置信息,又称为Bigtable引导9 h( a% e. V  f
    信息,存放在Chubby系统中。客户端、主控服务器以及子表服务器执行过程中都需
    + N8 r# m* ~: Y$ d/ u! U4 Q$ t. W要依赖Chubby服务,如果Chubby发生故障,Bigtable系统整体不可用。
    - J8 w! M; [* G; s  k" j6.1.2 数据分布, c, B: X, X* K, o
    Bigtable中的数据在系统中切分为大小100~200MB的子表,所有的数据按照行! }& X/ m* ~9 U7 a: _: O
    主键全局排序。Bigtable中包含两级元数据,元数据表及根表。用户表在进行某些操0 p! c; I& [8 s) N/ \0 |# K' Y# \
    作,比如子表分裂的时候需要修改元数据表,元数据表的某些操作又需要修改根. b# L- n4 W' f$ K6 v$ b
    表。通过使用两级元数据,提高了系统能够支持的数据量。假设平均一个子表大小
    & R3 K+ m4 v4 R# o% K为128MB,每个子表的元信息为1KB,那么一级元数据能够支持的数据量为  [* \$ d8 _: R
    128MB×(128MB/1KB)=16TB,两级元数据能够支持的数据量为
    6 x1 F4 L$ x" X0 t* d/ H% r16TB×(128MB/1KB)=2048 PB,满足几乎所有业务的数据量需求。如图6-3所示。
    : D% N. ]3 K% \2 T; Z* W7 P图 6-3 Bigtable数据结构) P7 b' r" u6 w0 d! E; T5 F0 P. X
    客户端查询时,首先从Chubby中读取根表的位置,接着从根表读取所需的元数
    , K& |& K, ~5 ^5 |据子表的位置,最后就可以从元数据子表中找到待查询的用户子表的位置。为了减
    % ~! v  L+ i+ I7 |! _少访问开销,客户端使用了缓存(cache)和预取(prefetch)技术。子表的位置信息
    ( D; s4 N4 R% v# F( M( r) q被缓存在客户端,客户端在寻址时首先查找缓存,一旦缓存为空或者缓存信息过7 m9 @6 k% x1 |* _/ v8 J# r3 _% i9 V
    期,客户端就需要请求子表服务器的上一级元数据表获取位置信息,比如用户子表
    : v7 `; ~) [' Y1 Q- d缓存过期需要请求元数据表,元数据子表缓存过期需要请求根表,根表缓存过期需
    , Z* v7 O7 R2 P! U: M! i要读取Chubby中的引导信息。如果缓存为空,最多需要三次请求;如果缓存信息过* ~8 W. H' u1 i& K' }
    期,最多需要六次请求,其中三次用来确定信息是过期的,另外三次获取新的地9 D8 Y9 k1 f; Q; Z/ ]8 ?
    址。预取则是在每次访问元数据表时不仅仅读取所需的子表元数据,而是读取连续
    8 f' g% I! i3 N* K& Z& O1 r的多个子表元数据,这样查找下一个子表时不需要再次访问元数据表。
    * C$ Z0 I1 T& `. R3 X6 {' l6.1.3 复制与一致性
    . u1 U! f. A5 r: t3 [Bigtable系统保证强一致性,同一个时刻同一个子表只能被一台Tablet Server服8 }# q7 Z' ~. W" G/ Q
    务,也就是说,Master将子表分配给某个Tablet Server服务时需要确保没有其他的
    - V; Q, F6 U: u! H, b6 A2 ]Tablet Server正在服务这个子表。这是通过Chubby的互斥锁机制保证的,Tablet Server
    8 [( @$ v1 h2 \8 S启动时需要获取Chubby互斥锁,当Tablet Server出现故障,Master需要等到Tablet$ ^+ R! E* `: t7 p2 D
    Server的互斥锁失效,才能把它上面的子表迁移到其他Tablet Server。8 C$ Z- V5 x* }, `
    Bigtable的底层存储系统为GFS(参见前面4.1节)。GFS本质上是一个弱一致性4 z0 u0 d2 E  t! {, @) d! i
    系统,其一致性模型只保证“同一个记录至少成功写入一次”,但是可能存在重复记* w1 l9 T3 `/ c. x0 ]/ C- n4 m4 e; l
    录,而且可能存在一些补零(padding)记录。
    6 B& o4 Q0 Y3 T7 ^Bigtable写入GFS的数据分为两种:
    & v, c% a9 z9 X) ^# C+ {0 R●操作日志。当Tablet Server发生故障时,它上面服务的子表会被集群中的其他
    8 d/ q$ ]! E: ]3 |0 n. k. DTablet Server加载继续提供服务。加载子表可能需要回放操作日志,每条操作日志都
    9 ^7 @- y6 x2 j9 J- y% C有唯一的序号,通过它可以去除重复的操作日志。
    2 g6 ]% V) J& v8 I  }2 h●每个子表包含的SSTable数据。如果写入GFS失败可以重试并产生多条重复记
    * N, ?4 \. U2 i" o& D录,但是Bigtable只会索引最后一条写入成功的记录。1 }8 \7 v( V" b6 W6 R$ V
    Bigtable本质上是构建在GFS之上的一层分布式索引,通过它解决了GFS遗留的  C" F3 C2 D# Y8 R# ~2 ?$ Q1 j/ g
    一致性问题,大大简化了用户使用。/ S( j2 @$ j2 ^, [  @# N9 t- ?; T
    6.1.4 容错  G4 Y. p$ E  C( I2 E
    Bigtable中Master对Tablet Server的监控是通过Chubby完成的,Tablet Server在初始
    & }6 J1 r  w3 }3 c* n- ?% F9 v4 G0 K化时都会从Chubby中获取一个独占锁。通过这种方式所有的Tablet Server基本信息被
    : Y) U+ V; ]$ F保存在Chubby中一个称为服务器目录(Server Directory)的特殊目录之中。Master通' e# {) u: _0 c$ j; o; `$ e6 {
    过检测这个目录以随时获取最新的Tablet Server信息,包括目前活跃的Tablet Server,
    1 Y( k1 j+ K: r$ P. p以及每个Tablet Server上现已分配的子表。对于每个Tablet Server,Master会定期询问其
    % i0 B- b; H2 c独占锁的状态。如果Tablet Server的锁丢失或者没有回应,则此时可能有两种情况,7 }- f1 m4 p6 x0 m2 g( i
    要么是Chubby出现了问题,要么是Tablet Server出现了问题。对此Master首先自己尝
    / D! j) A: D& H+ f$ e4 |试获取这个独占锁,如果失败说明是Chubby服务出现问题,否则说明是Tablet Server
    $ E4 `  I3 y/ Q出现了问题。Master将中止这个Tablet Server并将其上的子表全部迁移到其他Tablet# c3 @1 k2 ]$ t3 o  q! {
    Server。
    , d- ~1 Z" m. w( e& e2 ?每个子表持久化的数据包含两个部分:操作日志以及SSTable。Tablet Server发生: {* X8 V3 ^6 X+ j7 `9 {
    故障时某些子表的一些更新操作还在内存中,需要通过回放操作日志来恢复。为了
    9 B8 l! H2 u+ o. ~: Q提高性能,Tablet Server没有为它服务的每个子表写一个操作日志文件,而是把所有
    % }: Z+ A$ B/ f; u; T它服务的子表的操作日志混在一起写入GFS,每条日志通过<表格编号,行主键,日
    % |: ], [% ]+ t: @. u志序列号>来唯一标识。当某个Tablet Server宕机后,Master将该Tablet Server服务的  I2 u, _. \8 M2 P1 J) K- n+ m0 X
    子表分配给其他Tablet Server。为了减少Tablet Server从GFS读取的日志数据量,
    7 R3 q. z1 {" Q4 u5 R+ OMaster将选择一些Tablet Server对日志进行分段排序。排好序后,同一个子表的操作
    / @' T( ~) P& d5 g7 k日志连续存放,Tablet Server恢复某个子表时只需要读取该子表对应的操作日志即+ v* K& V6 L: h1 O3 t
    可。Master需要尽可能选择负载低的Tablet Server执行排序,并且需要处理排序任务
    + k3 B" l6 V2 L  D1 X. j. \失败的情况。
    / E# @! b; \7 S1 |Bigtable Master启动时需要从Chubby中获取一个独占锁,如果Master发生故障,. W* m0 m2 i8 f& ?$ Q( d! k9 u
    Master的独占锁将过期,管理程序会自动指定一个新的Master服务器,它从Chubby成( R% v* D3 ^6 u# ^
    功获取独占锁后可以继续提供服务。
    2 H! R; ]% V0 R3 u6.1.5 负载均衡3 d% O0 I$ \: b# @% V* Y! A
    子表是Bigtable负载均衡的基本单位。Tablet Server定期向Master汇报状态,当状
    % ~$ C  q5 A) J2 H态检测时发现某个Tablet Server上的负载过重时,Master会自动对其进行负载均衡,
    ( a2 Q3 c2 `0 d# y即执行子表迁移操作。子表迁移分为两步:第一步请求原有的Tablet Server卸载子
    # Z# P: I8 u9 m" L表;第二步选择一台负载较低的Tablet Server加载子表。Master发送命令请求原有的
    . J6 O* e" {5 \9 S) k+ H$ G$ TTablet Server卸载子表,原有Tablet Server解除加在子表上的互斥锁,而新的Tablet* L2 h% L5 I* M9 i( R# A
    Server加载子表时需要首先获取互斥锁。如果原有Tablet Server发生故障,新的Tablet' O7 x1 I# X3 }! i+ ?' |
    Server需要等待原有Tablet Server加在子表上的互斥锁过期。子表迁移前原有的Tablet+ G, d( z7 ]& g) ~  Y6 r
    Server会对其执行Minor Compaction操作,将内存中的更新操作以SSTable文件的形式2 r; c+ T) |* y& b$ i
    转储到GFS中,因此,负载均衡带来的子表迁移在新的Tablet Server上不需要回放操
    4 `% @/ J# U$ Q" A作日志。
    ! y7 K# @; o, K& Y子表迁移的过程中有短暂的时间需要停服务,为了尽可能减少停服务的时间,
    9 v  T# X+ m9 E; t% c4 t3 n* b1 K/ JBigtable内部采用两次Minor Compaction的策略。具体操作如下:
    ' J& q! c' k8 _/ F& ^0 \% e6 y& T1)原有Tablet Server对子表执行一次Minor Compaction操作,操作过程中仍然允8 x1 g  C. J. a% J7 F9 y7 J( m- w
    许写操作。
    / `1 T1 N; _0 F2)停止子表的写服务,对子表再次执行一次Minor Compaction操作。由于第一
    - T6 u' L. d, Z% W( k次Minor Compaction过程中写入的数据一般比较少,第二次Minor Compaction的时间7 O2 q3 U2 s" D2 n$ {* g) ^
    会比较短。
    / D; W( H9 `3 W* Z由于Bigtable负载均衡的过程中会停一会读写服务,负载均衡策略不应当过于激' Q# T. t6 s) C9 d3 y. J
    进。负载均衡涉及的因素很多,Tablet Server通过心跳定时将读、写个数、磁盘、内
    - x5 Y) R  S# W/ V, x! K' C存负载等信息发送给Master,Master根据负载计算公式计算出需要迁移的子表,然后放
    0 H) E$ `/ T& s; Y1 T& l入迁移队列中等待执行。9 X% z, ]# y/ M, @' d
    6.1.6 分裂与合并
    * ^; [2 l4 E  }) s; P随着数据不断写入和删除,某些子表可能太大,某些子表可能太小,需要执行, q, x+ V/ y  Z7 J+ j
    子表分裂与合并操作。顺序分布与哈希分布的区别在于哈希分布往往是静态的,而8 l! i0 v/ ?2 D3 Z! r7 d
    顺序分布是动态的,需要通过分裂与合并操作动态调整。. [& R% k+ d5 g- _$ S" q" ]! U
    Bigtable每个子表的数据分为内存中的MemTable和GFS中的多个SSTable,由于+ j* j0 _; @1 {: L$ a3 ]8 h
    Bigtable中同一个子表只被一台Tablet Server服务,进行分裂时比较简单。Bigtable上5 r$ `% [- m' `
    执行分裂操作不需要进行实际的数据拷贝工作,只需要将内存中的索引信息分成两
    4 _) j' |' K# l# s份,比如分裂前子表的范围为(起始主键,结束主键],在内存中将索引分成(起始) i) P5 O* g% Z. x& G0 [
    主键,分裂主键]和(分裂主键,结束主键]两个范围。例如,某个子表(1,10]的分9 q* h  ]0 F+ ~
    裂主键为5,那么,分裂后生成的两个子表的数据范围为:(1,5]和(5,10]。分裂& w. ^, w6 O- |. O6 q; \8 `
    以后两个子表各自写不同的MemTable,等到执行Compaction操作时再根据分裂后的
    - r6 o1 I3 f) i1 ^子表范围生成不同的SSTable,无用的数据自然成为垃圾被回收。1 [3 r) u0 z% s/ }
    分裂操作由Tablet Server发起,需要修改元数据,即用户表的分裂需要修改元数/ j! j0 |. Q- ]7 b$ v, b5 A9 g
    据表,元数据表的分裂需要修改根表。分裂操作需要增加一个子表,相当于在元数
    9 h1 v: y, G3 i: o据表中增加一行,通过Bigtable的行事务保证原子性。只要修改元数据表成功,分裂' E* C) ]1 K3 x( D9 X, g# @
    操作就算成功。分裂成功后Tablet Server将向Master汇报,如果出现Tablet Server故  E+ Y# y0 H  s/ {5 G
    障,Master可能丢失汇报分裂消息。新的Tablet Server加载这个子表时将发现它已经
    1 k; f0 f4 L. i' Q+ c0 _& ]/ T2 m分裂,并通知Master。& M# S2 ], O+ L5 ]3 |  N- c
    合并操作由Master发起,相比分裂操作要更加复杂。由于待合并的两个子表可能3 D$ Y9 I) x3 @& @# s
    被不同的Tablet Server加载,合并的第一步需要迁移其中一个子表,以使它们在同一
    ! @8 ^: h3 y8 x( `6 e$ p个Tablet Server上,接着通知Tablet Server执行子表合并。子表合并操作具体实现时非; L8 I& |  d. P9 t/ X8 z
    常麻烦,有兴趣的读者可以自行思考。
    $ y  K) B7 D8 l6.1.7 单机存储  O; w$ N) y+ s! l6 O
    如图6-4所示,Bigtable采用Merge-dump存储引擎。数据写入时需要先写操作日# i0 q5 M8 O) x+ O$ M
    志,成功后应用到内存中的MemTable中,写操作日志是往磁盘中的日志文件追加数4 Z  P% p3 V9 T& G  w2 {' q0 W
    据,很好地利用了磁盘设备的特性。当内存中的MemTable达到一定大小,需要将; V- w- z' R8 b' S- b7 ?9 A
    MemTable转储(Dump)到磁盘中生成SSTable文件。由于数据同时存在MemTable和5 k4 K1 m8 r' T% C4 c
    可能多个SSTable中,读取操作需要按从旧到新的时间顺序合并SSTable和内存中的
    ; y8 S* a/ Q1 T# l- ~MemTable数据。数据在SSTable中连续存放,因此可以同时满足随机读取和顺序读取2 R/ h3 w, X: ?  t- ?4 ]; K6 b
    两种需求。为了防止磁盘中的SSTable文件过多,需要定时将多个SSTable通过
    ; ^9 a) z6 R0 K4 L+ _compaction过程合并为一个SSTable,从而减少后续读操作需要读取的文件个数。一
    " W: l# ?' I/ q; W- }& i! n' M: w般情况下,如果写操作比较少,我们总是能够使得对每一份数据同时只存在一个
    % O, I/ v" u2 Y/ _: W8 ?; W$ A3 gSSTable和一个MemTable,也就是说,随机读取和顺序读取都只需要访问一次磁盘,- ~, u2 I/ Z* F  N3 T* _
    这对于线上服务基本上都是成立的。
      l$ n. o; \; ^. r7 s图 6-4 Bigtable单机存储引擎- R7 i4 \( E0 j: S
    插入、删除、更新、增加(Add)等操作在Merge-dump引擎中都看成一回事,除* ?8 I: b8 _, i0 `5 S+ l, o
    了最早生成的SSTable外,SSTable中记录的只是操作,而不是最终的结果,需要等到- S  j6 t" ~8 H: z
    读取(随机或者顺序)时才合并得到最终结果。( T! l# h3 l3 q+ |& H9 ]! C. i
    Bigtable中包含三种Compaction策略:Minor Compaction、Merging Compaction和
    , h) {: |: `9 t5 ?; {/ |. j7 oMajor Compaction。其中,Minor Compaction把内存中的MemTable转储到GFS中,
    6 ~' Y2 T# J  _8 N/ GMerging Compaction和Major Compaction合并GFS中的多个SSTable文件生成一个更大
      R, m" }1 f. d2 p6 p/ N的SSTable。Minor Compaction主要是为了防止内存占用过多,Merging和Major
    0 x+ Z# a7 Z' x' ~# vCompaction则是为了防止读取文件个数过多。Major Compaction与Merging Compaction
    ) E+ ^" n7 A6 M$ A) c7 e3 N的区别在于Major Compaction会合并所有的SSTable文件和内存中的MemTable,生成5 w" E. d/ q9 B2 n6 k2 Q6 H
    最终结果;而Merging Compaction生成的SSTable文件可能包含一些操作,比如删除、$ D8 D/ ~6 _7 f4 R) N9 N5 L
    增加等。5 {' T- G6 N8 v6 \' U) i/ Y* r
    数据在SSTable中按照主键有序存储,每个SSTable由若干个大小相近的数据块3 d+ f9 C7 c$ j# V$ Q) z
    (Block)组成,每个数据块包含若干行。数据块的大小一般在8~64KB之间,允许9 t" [( m! g0 T7 v4 D, D1 T( a; _
    用户配置。Tablet Server的缓存包括两种:块缓存(Block Cache)和行缓存(Row* S, m& w) K0 G2 R: ?; K
    Cache)。其中,块缓存的单位为SSTable中的数据块,行缓存的单位为一行记录。随
    : W& o9 ]4 k+ x/ V6 n( }机读取时,首先查找行缓存;如果行缓存不命中,接着再查找块缓存。另外,
    ( g( c, R; r: N; t4 wBigtable还支持布隆过滤器(Bloom Filter),如果读取的数据行在SSTable中不存在,
    3 G& _, r& y8 I可以通过布隆过滤器发现,从而避免一次读取GFS文件操作。
    5 K6 \- d4 L4 a+ o) F: t6 l6.1.8 垃圾回收
    # c  E: ?' t% `! T/ DCompaction后生成新的SSTable,原有的SSTable成为垃圾需要被回收掉。每个子) ^. b8 i$ n& x& E# ?
    表正在引用的SSTable文件保存在元数据中。Master定期执行垃圾回收任务,这是一
      p# b8 w/ l8 B. X3 X个标记删除(mark-and-sweep)过程。首先扫描GFS获取所有的SSTable文件,接着扫
    + A4 _$ O+ j' m* P9 Q/ B描根表和元数据表获取所有正在使用的SSTable文件,如果GFS中的SSTable没被任何
    8 T, `$ d, [8 {, x4 K一个子表使用,说明可以被回收掉。这里需要注意,由于Tablet Server执行9 b) {. b& b8 l8 i! K7 y$ r* d
    Compaction操作生成一个全新的SSTable与修改元数据这两个操作不是原子的,垃圾5 S" g, q1 N. X: h, d& K
    回收需要避免删除刚刚生成但还没有记录到元数据中的SSTable文件。一种比较简单
    8 h6 _+ T8 }2 E6 |4 Y$ G4 y的做法是垃圾回收只删除至少一段时间,比如1小时没有被使用的SSTable文件。
    % `* h) R/ y  K. E7 v& @* l- b6.1.9 讨论) ?3 d8 W8 `/ \& p/ U8 `( a
    GFS+Bigtable两层架构以一种很优雅的方式兼顾系统的强一致性和可用性。底层! P9 T( q; a1 C
    文件系统GFS是弱一致性系统,可用性和性能很好,但是多客户端追加可能出现重复
    / ^+ B( g3 _8 c. A, R3 M7 I5 _记录等数据不一致问题;上层的表格系统Bigtable通过多级分布式索引的方式使得系. R3 r/ f# `: t" C9 g
    统对外整体表现为强一致性。Bigtable最大的优势在于线性可扩展,单台机器出现故( x, z+ z4 r' a3 p0 g
    障可将服务迅速(一分钟以内)迁移到整个集群。Bigtable架构最多可支持几千台的
    - \* n9 M* @, W6 B集群规模,通过自动化容错技术大大降低了存储成本。5 p6 L6 _& m0 N1 q
    Bigtable架构也面临一些问题,如下所示:
    ; P6 t; z& _$ O" F1 u0 k2 Y! u●单副本服务。Bigtable架构非常适合离线或者半线上应用,然而,Tablet Server" [: d5 y5 ^: q- K$ @' x; @
    节点出现故障时部分数据短时间内无法提供读写服务,不适合实时性要求特别高的+ H: n7 I+ w( e8 C
    业务,如交易类业务。
    " l- L" s. `1 N$ c' ?+ K●SSD使用。Google整体架构的设计理念为通过廉价机器构建自动容错的大集
    ' W- m# j+ c, [群,然而,随着SSD等硬件技术的发展,机器宕机的概率变得更小,SSD和SAS混合7 {0 U  g6 k4 R4 i" E
    存储也变得比较常见,存储和服务分离的架构有些不太适应。
    ; t, _, M, F' z1 l$ C, \9 J* ^●架构的复杂性导致Bug定位很难。Bigtable依赖GFS和Chubby,这些依赖系统本
    % I& `" N$ E2 C$ v: V身比较复杂,另外,Bigtable多级分布式索引和容错等机制内部实现都非常复杂,工) ]- {7 K  f% {
    程量巨大,使用的过程中如果发现问题很难定位。: _0 f  E* b) S  C! f5 T$ U* r
    总体上看,Bigtable架构把可扩展性和成本做到了极致,但在线实时服务能力有
    . a* p5 ^( E. \( y* }一定的改进空间,适合通用的离线和半线上应用场合。
    . p- s! Y6 l! X9 O4 F4 o' `# ?% J' W
    + c0 b# k- f8 j' T7 d8 s+ u
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-1 13:57 , Processed in 0.317115 second(s), 30 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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