java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2630|回复: 0

《大规模分布式存储系统》第8章OceanBase架构初探【8.3】

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

    [LV.Master]出神入化

    2062

    主题

    3720

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66592

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

    发表于 2017-3-5 00:36:55 | 显示全部楼层 |阅读模式
    8.3 系统架构& ~# S4 @+ H) j, L
    8.3.1 整体架构图
    4 U: n& z6 N0 {, j  H$ AOceanBase的整体架构如图8-1所示。
    - w4 O6 z; B- Q4 `& g图 8-1 OceanBase整体架构图3 R$ B; P8 Q: \- v: \. ?* ^9 o
    OceanBase由如下几个部分组成:+ R; h! @9 m$ W7 D) h- k
    ●客户端:用户使用OceanBase的方式和MySQL数据库完全相同,支持JDBC、 C& H& @! `# ]( Y. x
    客户端访问,等等。基于MySQL数据库开发的应用程序、工具能够直接迁移到
    8 M, q/ H8 _6 V2 X" v" YOceanBase。8 m, v' L* W6 ]4 T1 i$ K
    ●RootServer:管理集群中的所有服务器,子表(tablet)数据分布以及副本管
    4 e7 S- X; i8 ]( s理。 RootServer一般为一主一备,主备之间数据强同步。
    3 n: t) D+ M, E# {4 s●UpdateServer:存储OceanBase系统的增量更新数据。UpdateServer一般为一主  n) l- r+ b  b! {& H3 O
    一备,主备之间可以配置不同的同步模式。部署时,UpdateServer进程和RootServer6 t. R% l7 {' }0 b$ ?1 D
    进程往往共用物理服务器。/ q2 c. K' ^; G- V  ~' M$ P) J
    ●ChunkServer:存储OceanBase系统的基线数据。基线数据一般存储两份或者三9 `, p0 h/ y4 f% h" ?
    份,可配置。
    7 K! H5 I7 {' D6 o●MergeServer:接收并解析用户的SQL请求,经过词法分析、语法分析、查询优% p. Z1 Q* k, Z8 L
    化等一系列操作后转发给相应的ChunkServer或者UpdateServer。如果请求的数据分布2 a$ i1 h+ a- g+ ]% `( q7 V
    在多台ChunkServer上,MergeServer还需要对多台ChunkServer返回的结果进行合并。
    & q" x5 C& x# n; ~8 ?' `客户端和MergeServer之间采用原生的MySQL通信协议,MySQL客户端可以直接访问1 d  b1 p$ V# }7 s6 T4 l
    MergeServer。
    7 T4 Z" o6 L" d9 o  A4 ?OceanBase支持部署多个机房,每个机房部署一个包含RootServer、" S% `3 ^8 u2 n8 @% `
    MergeServer、ChunkServer以及UpdateServer的完整OceanBase集群,每个集群由各自- z# {& D4 _% \/ ]  G# C
    的RootServer负责数据划分、负载均衡、集群服务器管理等操作,集群之间数据同步
    9 I8 q0 f8 y) @6 J2 k" M通过主集群的主UpdateServer往备集群同步增量更新操作日志实现。客户端配置了多
    2 s& t( W) M* `9 ]5 p+ U个集群的RootServer地址列表,使用者可以设置每个集群的流量分配比例,客户端根1 G5 X& r( m* k, t' f
    据这个比例将读写操作发往不同的集群。图8-2是双机房部署示意图。3 E! _% b3 [" T( L" F/ }
    图 8-2 OceanBase双机房部署
    6 Z$ ]0 {! C4 J8.3.2 客户端
    + ]+ g) R" y/ G/ J2 X% W& {- oOceanBase客户端与MergeServer通信,目前主要支持如下几种客户端:) S4 n1 e" M7 f5 z) Y" O
    ●MySQL客户端:MergeServer兼容MySQL协议,MySQL客户端及相关工具(如
    4 x! [( C) j+ Z! N* r% n6 m( MJava数据库访问方式JDBC)只需要将服务器的地址设置为任意一台Merge-Server的地0 m. ~! F6 Z; H4 C$ G
    址,就可以直接使用。
    ! a( E- M; Y  a6 f; b2 k●Java客户端:OceanBase内部部署了多台MergeServer,Java客户端提供对 MySQL' q! v" V$ j) p7 u5 r2 A
    标准JDBC Driver的封装,并提供流量分配、负载均衡、MergeServer异常处理等功
    9 E" r8 u% b  k: _: V+ b能。简单来讲,Java客户端首先按照一定的策略定位到某台MergeServer,接着调用
    6 ?  A6 H. t* Y) kMySQL JDBC Driver往这台MergeServer发送读写请求。Java客户端实现符合JDBC标1 }3 v- x  T7 p, x+ t. u' m
    准,能够支持Spring、iBatis等Java编程框架。' a5 S0 I+ _# l* h/ @3 m
    ●C客户端:OceanBase C客户端的功能和Java客户端类似。它首先按照一定的策
    & E+ p, R  R/ h! }略定位到某台MergeServer,接着调用MySQL标准C客户端往这台MergeServer发送读4 L# Z: _$ m5 }' T/ s
    写请求。C客户端的接口和MySQL标准C客户端接口完全相同,因此,能够通过- S# U+ ?! V! H6 t" ]; a* d& j
    LD_PRELOAD的方式将应用程序依赖的MySQL标准C客户端替换为OceanBase C客户
    # [. O) [0 l5 f端,而无需修改应用程序的代码。8 X& j" F0 H, i" N
    OceanBase集群有多台MergeServer,这些MergeServer的服务器地址存储在
    , D; z  ?, i' j$ X/ kOceanBase服务器端的系统表(与Oracle的系统表类似,存储OceanBase系统的元数8 `7 A; \4 Q, T2 H4 O
    据)内。OceanBase Java/C客户端首先请求服务器端获取MergeServer地址列表,接着, X3 N0 @/ R( G0 J0 g( y
    按照一定的策略将读写请求发送给某台MergeServer,并负责对出现故障的. t2 C  L" L1 x( S
    MergeServer进行容错处理。
    8 W7 z# }4 J5 `2 {* v; ]0 V6 yJava/C客户端访问OceanBase的流程大致如下:
    . S9 Z; l" s+ I' w$ G1)请求RootServer获取集群中MergeServer的地址列表。
    ' r4 h+ i* b8 a; |  D4 F2 B2 h2)按照一定的策略选择某台MergeServer发送读写请求。客户端与MergeServer
    " Y* r) b* X% E7 g, h, ]# c之间的通信协议兼容原生的MySQL协议,因此,只需要调用MySQL JDBC Driver或者$ m8 L6 Y! Y, Q/ x- Y0 {" \
    MySQL C客户端这样的标准库即可。客户端支持的策略主要有两种:随机以及一致% h4 h/ O3 [+ O8 j
    性哈希。一致性哈希的主要目的是将相同的SQL请求发送到同一台MergeServer,方
    0 W! u. e5 g) \, V  g) p& ?- D/ }便MergeServer对查询结果进行缓存。
    ! b/ H1 \9 F9 h2 `  x3 N3 Q2 A3)如果请求MergeServer失败,则从MergeServer列表中重新选择一台( c7 c% I$ d  E& n
    MergeServer重试;如果请求某台MergeServer失败超过一定的次数,将这台
    # b! F0 K0 X! @$ XMergeServer加入黑名单并从MergeServer列表中删除。另外,客户端会定期请求/ E0 v. R6 h* ^+ J
    RootServer更新MergeServer地址列表。2 C$ I6 b6 ~6 I
    如果OceanBase部署多个集群,客户端还需要处理多个集群的流量分配问题。使
    ) D2 K# w/ D$ d7 X5 r- G! M用者可以设置多个集群之间的流量分配比例,客户端获取到流量分配比例后,按照
    & A2 f6 a. o% c4 q这个比例将请求发送到不同的集群。
    ' x1 E# }/ m3 d/ s# f; P! _/ T' \OceanBase程序升级版本时,往往先将备集群的读取流量调整为0,这时所有的
    9 j$ t" I: P/ D( H( z4 [! ^读写请求都只发往主集群,接着升级备集群的程序版本。备集群升级完成后将流量
    2 D1 }% v  \7 v$ L7 W5 {逐步切换到备集群观察一段时间,如果没有出现异常,则将所有的流量切到备集/ Y# [: i& I" W$ u. x0 `3 y! L# t
    群,并将备集群切换为主集群提供写服务。原来的主集群变为新的备集群,升级新4 [+ t! U$ P# |8 [
    的备集群的程序版本后重新分配主备集群的流量比例。
    % A: e* X) d- \7 p7 L8.3.3 RootServer8 g: ^9 z% K; n0 F3 ?
    RootServer的功能主要包括:集群管理、数据分布以及副本管理。
    0 j6 N; v8 `) A. F/ J) Z$ DRootServer管理集群中的所有MergeServer、ChunkServer以及UpdateServer。每个
    * j2 f' Y( P4 r, c( X5 @! c集群内部同一时刻只允许一个UpdateServer提供写服务,这个UpdateServer成为主. f6 m; D+ Z0 ^: t) n  S
    UpdateServer。这种方式通过牺牲一定的可用性获取了强一致性。RootServer通过租
    $ s' P: J  `, d8 w/ i9 t3 r  |约(Lease)机制选择唯一的主UpdateServer,当原先的主UpdateServer发生故障后," D% J# [1 h( }. ?
    RootServer能够在原先的租约失效后选择一台新的UpdateServer作为主UpdateServer。
    " a9 ]% X( x0 A# ]# m4 U( R另外,RootServer与MergeServer&ChunkServer之间保持心跳(heartbeat),从而能够
    : h  D+ w* z! o- L$ w感知到在线和已经下线的MergeServer&ChunkServer机器列表。6 ?6 h; }- o  S/ a
    OceanBase内部使用主键对表格中的数据进行排序和存储,主键由若干列组成并
    $ I3 f% m0 a0 l, d- D, n且具有唯一性。在OceanBase内部,基线数据按照主键排序并且划分为数据量大致相7 N+ [7 T: k& e0 @* [% C8 j5 o9 T+ X) e( j
    等的数据范围,称为子表(tablet)。每个子表的默认大小是256MB(可配置)。
    9 X* S* a' \8 ]+ V3 FOceanBase的数据分布方式与Bigtable一样采用顺序分布,不同的是,OceanBase没有
    9 @: k* L: Q4 O# s6 N2 g采用根表(RootTable)+元数据表(MetaTable)两级索引结构,而是采用根表一级
    7 h8 {' T% c# k7 A$ L' E/ Q索引结构。# f) [6 V+ E% x7 T- }1 t, f
    如图8-3所示,主键值在[1,100]之间的表格被划分为四个子表:1~25,26~: X1 d6 @9 L2 H' N. a; p
    50,51~80以及81~100。RootServer中的根表记录了每个子表所在的ChunkServer位  u: ]. ?7 v% V, |  c( ~
    置信息,每个子表包含多个副本(一般为三个副本,可配置),分布在多台
    * h# f/ h+ N* DChunkServer中。当其中某台ChunkServer发生故障时,RootServer能够检测到,并且触
    & f: r7 ^6 M6 V发对这台ChunkServer上的子表增加副本的操作;另外,RootServer也会定期执行负载
      W3 B$ G8 D3 T) w- ~! b5 ^( c均衡,选择某些子表从负载较高的机器迁移到负载较低的机器上。5 y' i6 c, m6 e7 X
    图 8-3 基线数据子表划分
    # s, I# @! i; g* _$ a7 [4 fRootServer采用一主一备的结构,主备之间数据强同步,并通过Linux' d3 ^* S  z& r; d0 _
    HA(http://www.linux-ha.org)软件实现高可用性。主备RootServer之间共享VIP,当. K/ y* o; v; O1 W9 `
    主RootServer发生故障后,VIP能够自动漂移到备RootServer所在的机器,备. A0 [9 i0 X8 M( a+ h/ J5 j: S
    RootServer检测到以后切换为主RootServer提供服务。
    , L+ j5 z- j+ m, _2 n) f# X( j8.3.4 MergeServer7 g  Q* z6 V  Z5 x8 Z1 i
    MergeServer的功能主要包括:协议解析、SQL解析、请求转发、结果合并、多
    ! O# J2 o9 v( p! k' g$ l" c表操作等。- {, C8 ?" k4 e8 h
    OceanBase客户端与MergeServer之间的协议为MySQL协议。MergeServer首先解
    8 h) A0 V8 i* a析MySQL协议,从中提取出用户发送的SQL语句,接着进行词法分析和语法分析,
      h1 m% h+ F  p2 `+ R# ]7 z; K) t生成SQL语句的逻辑查询计划和物理查询计划,最后根据物理查询计划调用
    # q; ?; j: Z+ t7 ROceanBase内部的各种操作符。
    3 ~$ w7 B" f5 ~& r: O, T: MMergeServer缓存了子表分布信息,根据请求涉及的子表将请求转发给该子表所: w+ q+ x, m6 ?1 ^
    在的ChunkServer。如果是写操作,还会转发给UpdateServer。某些请求需要跨多个子
    , _( f# m; ]# Y. U表,此时MergeServer会将请求拆分后发送给多台ChunkServer,并合并这些$ g3 b# V( |; ^
    ChunkServer返回的结果。如果请求涉及多个表格,MergeServer需要首先从2 X3 x: M+ E5 y1 F& o; T0 l: n
    ChunkServer获取每个表格的数据,接着再执行多表关联或者嵌套查询等操作。/ _4 b; R1 q% B* V  u3 a) b
    MergeServer支持并发请求多台ChunkServer,即将多个请求发给多台
    : j4 G% p3 K& y& fChunkServer,再一次性等待所有请求的应答。另外,在SQL执行过程中,如果某个
    4 z* O4 h: W, v. ^" ]4 M子表所在的ChunkServer出现故障,MergeServer会将请求转发给该子表的其他副本所
      e% V; E4 v9 W9 I在的ChunkServer。这样,ChunkServer故障是不会影响用户查询的。
    3 Q" P  u- P9 x9 s# B9 W' t& [5 q4 NMergeServer本身是没有状态的,因此,MergeServer宕机不会对使用者产生影
    7 Z6 a) F  r/ e: p9 U/ M! `+ B4 [, t$ C( S响,客户端会自动将发生故障的MergeServer屏蔽掉。
    $ S' i! [+ p" X- d- }$ d8.3.5 ChunkServer, r' J0 O. J# s
    ChunkServer的功能包括:存储多个子表,提供读取服务,执行定期合并以及数  B1 m$ w' J7 V  [( v+ u9 p( n
    据分发。/ K) t+ ~3 a% w4 F( [' d+ p' m
    OceanBase将大表划分为大小约为256MB的子表,每个子表由一个或者多个8 Q9 f, n0 h# @
    SSTable组成(一般为一个),每个SSTable由多个块(Block,大小为4KB~64KB之
    ( |: P/ r- u0 u9 X, p; q4 W间,可配置)组成,数据在SSTable中按照主键有序存储。查找某一行数据时,需要
      p0 H3 Y7 C4 F" {首先定位这一行所属的子表,接着在相应的SSTable中执行二分查找。SSTable支持两
    ' k0 \1 Q# c- a) c$ a; B7 m种缓存模式,块缓存(Block Cache)以及行缓存(Row Cache)。块缓存以块为单位
    1 E. S! y& i1 s缓存最近读取的数据,行缓存以行为单位缓存最近读取的数据。
    2 V$ D2 t! m* fMergeServer将每个子表的读取请求发送到子表所在的ChunkServer,ChunkServer首
    + O( r- T7 g  M' {先读取SSTable中包含的基线数据,接着请求UpdateServer获取相应的增量更新数据,
    4 m3 s% R5 R+ J4 j并将基线数据与增量更新融合后得到最终结果。
    9 a, ]; k! |4 ^5 t由于每次读取都需要从UpdateServer中获取最新的增量更新,为了保证读取性
    + s) c6 H4 n9 s9 \能,需要限制UpdateServer中增量更新的数据量,最好能够全部存放在内存中。; F4 V0 y* }8 d6 [0 z; x' Z
    OceanBase内部会定期触发合并或者数据分发操作,在这个过程中,ChunkServer将从
    " j4 r7 s  x& _' d( l% ?UpdateServer获取一段时间之前的更新操作。通常情况下,OceanBase集群会在每天2 H2 \9 j1 r2 O. V- ]
    的服务低峰期(凌晨1:00开始,可配置)执行一次合并操作。这个合并操作往往也称' L1 k; X% h& G
    为每日合并。' k) O% F- K  h
    8.3.6 UpdateServer
    * T$ |( l3 |3 b3 v  \" ]UpdateServer是集群中唯一能够接受写入的模块,每个集群中只有一个主Update-
    % ^) w; b& K2 C, hServer。UpdateServer中的更新操作首先写入到内存表,当内存表的数据量超过一定
    6 l, Y1 X) S6 q# z+ \" p- q值时,可以生成快照文件并转储到SSD中。快照文件的组织方式与ChunkServer中的
    & Q* Z- S+ `5 xSSTable类似,因此,这些快照文件也称为SSTable。另外,由于数据行的某些列被更" d  l1 \" r4 r4 T% I
    新,某些列没被更新,SSTable中存储的数据行是稀疏的,称为稀疏型SSTable。
    / J7 B, S. ^6 y1 l为了保证可靠性,主UpdateServer更新内存表之前需要首先写操作日志,并同步
    ' W5 P; w! b# f9 B到备UpdateServer。当主UpdateServer发生故障时,RootServer上维护的租约将失效,
    9 S3 a; T/ A9 ]7 w, W, ]" o此时,RootServer将从备UpdateServer列表中选择一台最新的备UpdateServer切换为主
    ' ^  n% u( u3 yUpdateServer继续提供写服务。UpdateServer宕机重启后需要首先加载转储的快照文" B( C" X* v$ p, U
    件(SSTable文件),接着回放快照点之后的操作日志。+ e3 m& r2 b" m  Y7 v6 h
    由于集群中只有一台主UpdateServer提供写服务,因此,OceanBase很容易地实
    ) q: {5 k# K3 g* W7 _5 W现了跨行跨表事务,而不需要采用传统的两阶段提交协议。当然,这样也带来了一
    9 x& a5 U7 [4 k, Y$ G. e8 S; h& j* g系列的问题。由于整个集群所有的读写操作都必须经过UpdateServer,UpdateServer的
    & X; n6 q3 D" g4 a8 o3 U性能至关重要。OceanBase集群通过定期合并和数据分发这两种机制将UpdateServer( e- t& B5 T; a& ~- |9 J
    一段时间之前的增量更新源源不断地分散到ChunkServer,而UpdateServer只需要服务+ a# M4 ?/ Z( E5 j2 d& o: `
    最新一小段时间新增的数据,这些数据往往可以全部存放在内存中。另外,系统实& |0 i; v) Z  p4 `
    现时也需要对UpdateServer的内存操作、网络框架、磁盘操作做大量的优化。! l1 }* g5 P0 F5 b% ^5 Z* N) f
    8.3.7 定期合并&数据分发
    % F( ?/ ]2 X/ G$ z# N% a* y( l定期合并和数据分发都是将UpdateServer中的增量更新分发到ChunkServer中的手- l0 L% M, o0 `% R9 M  O4 T: h0 _
    段,二者的整体流程比较类似:
      g8 \0 @' v/ C1 p; f1)UpdateServer冻结当前的活跃内存表(Active MemTable),生成冻结内存
    $ {2 T& n9 D1 W表,并开启新的活跃内存表,后续的更新操作都写入新的活跃内存表。
    ' R5 `5 N/ l9 W) K2)UpdateServer通知RootServer数据版本发生了变化,之后RootServer通过心跳# B4 o) S1 ~" T- S9 t
    消息通知ChunkServer。
    . y& f4 G9 `* o* A& q1 @1 Q3)每台ChunkServer启动定期合并或者数据分发操作,从UpdateServer获取每个% X9 G' i' j9 i# ~: [
    子表对应的增量更新数据。
    $ h  n+ `0 q1 n% w* N定期合并与数据分发两者之间的不同点在于,数据分发过程中ChunkServer只是+ I  }% F4 I( w8 \. W, C% O
    将UpdateServer中冻结内存表中的增量更新数据缓存到本地,而定期合并过程中, g$ \$ `; x& A% Y$ X; Y" s
    ChunkServer需要将本地SSTable中的基线数据与冻结内存表的增量更新数据执行一次: G6 ^  E  c* ]) B: j5 [+ x
    多路归并,融合后生成新的基线数据并存放到新的SSTable中。定期合并对系统服务$ z0 T  t4 b0 F% U: y; i* C* M
    能力影响很大,往往安排在每天服务低峰期执行(例如凌晨1点开始),而数据分发
    . P: I! B* B2 w0 P3 w可以不受限制。
    8 S  K& M9 p; e' N, g如图8-4,活跃内存表冻结后生成冻结内存表,后续的写操作进入新的活跃内存
    4 d" X1 n1 I* g0 A- y" e5 s  z! d表。定期合并过程中ChunkServer需要读取UpdateServer中冻结内存表的数据、融合后
    9 I6 _7 R' _, a4 Y, d9 ?生成新的子表,即:: A& L! |7 {! @8 Y' J
    新子表=旧子表+冻结内存表
    ! R7 a4 U2 s# I$ A% T图 8-4 定期合并不停读服务8 u2 k' |2 Z  B: ?4 Z1 X5 e# l
    虽然定期合并过程中各个ChunkServer的各个子表合并时间和完成时间可能都不9 P! c* P/ ?" y4 F/ S' K
    相同,但并不影响读取服务。如果子表没有合并完成,那么使用旧子表,并且读取
    : v5 i. x& u4 N9 v3 C9 ?UpdateServer中的冻结内存表以及新的活跃内存表;否则,使用新子表,只读取新的8 B: }- |: y5 h8 D# ~5 e
    活跃内存表,即:
    9 ?& h9 o- \0 Y# Q" T+ g/ K: r查询结果=旧子表+冻结内存表+新的活跃内存表* k5 }+ p9 |2 i
    =新子表+新的活跃内存表9 t$ B1 F* p8 _+ S
      ^2 `9 \6 B5 P4 j  r3 F5 c9 g4 o& ^

    * M, C- S  q4 ]" C7 H# V
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-2-23 13:10 , Processed in 0.416258 second(s), 30 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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