java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2663|回复: 0

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

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

    [LV.Master]出神入化

    2096

    主题

    3754

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66788

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

    发表于 2017-3-5 00:36:55 | 显示全部楼层 |阅读模式
    8.3 系统架构
    ( V& c1 [7 A/ k8.3.1 整体架构图' s  M) C8 p) T/ z7 e
    OceanBase的整体架构如图8-1所示。
    # X7 i8 `' G4 y2 S2 Z/ e图 8-1 OceanBase整体架构图6 Z3 w$ S9 R1 f* `! x7 j! h" G
    OceanBase由如下几个部分组成:: D. m, N1 J' b' G2 C
    ●客户端:用户使用OceanBase的方式和MySQL数据库完全相同,支持JDBC、 C+ I$ _$ N' |2 x+ q/ p  J' \. z
    客户端访问,等等。基于MySQL数据库开发的应用程序、工具能够直接迁移到' Z0 P; v- h" n- k
    OceanBase。8 E/ i- c% [( _2 W
    ●RootServer:管理集群中的所有服务器,子表(tablet)数据分布以及副本管
    2 m& x, h) Q# S) `理。 RootServer一般为一主一备,主备之间数据强同步。4 @4 r3 ~5 z/ f
    ●UpdateServer:存储OceanBase系统的增量更新数据。UpdateServer一般为一主
    / H/ u. v9 ]5 N) N% }0 O% |: Y一备,主备之间可以配置不同的同步模式。部署时,UpdateServer进程和RootServer
    . E1 ?# D- n) z. G3 h! F进程往往共用物理服务器。
    6 `( K6 F, k: x●ChunkServer:存储OceanBase系统的基线数据。基线数据一般存储两份或者三
    1 E9 e' A; {3 `9 ?. a份,可配置。
    6 [" s9 c* K9 R" A" z% M●MergeServer:接收并解析用户的SQL请求,经过词法分析、语法分析、查询优
    ; C+ @. Y5 c8 e9 n化等一系列操作后转发给相应的ChunkServer或者UpdateServer。如果请求的数据分布
    - n  f. M& j5 A2 u% \) f8 |2 S在多台ChunkServer上,MergeServer还需要对多台ChunkServer返回的结果进行合并。* R! t6 f3 P4 ~; F# v% _" i
    客户端和MergeServer之间采用原生的MySQL通信协议,MySQL客户端可以直接访问
      L1 f' W  B* |/ CMergeServer。! X* [% I; Z- X( R$ e5 e$ }# S. N
    OceanBase支持部署多个机房,每个机房部署一个包含RootServer、
    5 n8 D3 P# V4 s4 o: WMergeServer、ChunkServer以及UpdateServer的完整OceanBase集群,每个集群由各自
    $ z% a$ R1 i% A& |的RootServer负责数据划分、负载均衡、集群服务器管理等操作,集群之间数据同步
    ' u& P6 j) q# H9 e通过主集群的主UpdateServer往备集群同步增量更新操作日志实现。客户端配置了多+ G+ |$ @' O' f4 X  _2 E
    个集群的RootServer地址列表,使用者可以设置每个集群的流量分配比例,客户端根
    5 Q" S# A' i1 L% \- s3 T+ P/ P据这个比例将读写操作发往不同的集群。图8-2是双机房部署示意图。) K" ^* W# {& ^3 t3 P
    图 8-2 OceanBase双机房部署4 s' E5 o& t: d: p
    8.3.2 客户端
    3 o- `$ O  {5 a5 k/ \0 O' gOceanBase客户端与MergeServer通信,目前主要支持如下几种客户端:
    $ S5 S2 N8 R$ B& J. K( |●MySQL客户端:MergeServer兼容MySQL协议,MySQL客户端及相关工具(如' U. E; t) ^9 t  `
    Java数据库访问方式JDBC)只需要将服务器的地址设置为任意一台Merge-Server的地+ y6 w  K' E5 N; B* @* Y. [6 x
    址,就可以直接使用。
    ! N1 B( q5 c  o; T●Java客户端:OceanBase内部部署了多台MergeServer,Java客户端提供对 MySQL' Y# E' e1 F' b' w
    标准JDBC Driver的封装,并提供流量分配、负载均衡、MergeServer异常处理等功$ Z2 R; R5 q0 z1 P) _
    能。简单来讲,Java客户端首先按照一定的策略定位到某台MergeServer,接着调用3 J0 ?4 Z! W0 b& T, j
    MySQL JDBC Driver往这台MergeServer发送读写请求。Java客户端实现符合JDBC标& j2 m; o# h8 s' J& `4 Z* H
    准,能够支持Spring、iBatis等Java编程框架。
    , g$ s4 f- T$ Z* w●C客户端:OceanBase C客户端的功能和Java客户端类似。它首先按照一定的策+ u' Z# n4 A, M3 {8 K8 f
    略定位到某台MergeServer,接着调用MySQL标准C客户端往这台MergeServer发送读
    3 m7 m3 [. i$ O1 U  b写请求。C客户端的接口和MySQL标准C客户端接口完全相同,因此,能够通过. u7 _( S( r) i" \9 v
    LD_PRELOAD的方式将应用程序依赖的MySQL标准C客户端替换为OceanBase C客户8 \6 r% a" R5 H& a3 e
    端,而无需修改应用程序的代码。7 g. Y* J/ K8 i4 m9 I
    OceanBase集群有多台MergeServer,这些MergeServer的服务器地址存储在
    % r9 i+ v/ K9 a( T+ h9 COceanBase服务器端的系统表(与Oracle的系统表类似,存储OceanBase系统的元数
    3 M# J% U4 m% m据)内。OceanBase Java/C客户端首先请求服务器端获取MergeServer地址列表,接着7 ^1 w; w- N1 _
    按照一定的策略将读写请求发送给某台MergeServer,并负责对出现故障的
    * U% ]; J) U* l( NMergeServer进行容错处理。
    3 T  J  A) b1 }4 _% _Java/C客户端访问OceanBase的流程大致如下:
    8 A6 }  D  S% a8 I6 O; h* n1)请求RootServer获取集群中MergeServer的地址列表。
    " v* u: ^7 p# `/ s( J4 N2)按照一定的策略选择某台MergeServer发送读写请求。客户端与MergeServer* m6 ?* i- [- z6 K9 L
    之间的通信协议兼容原生的MySQL协议,因此,只需要调用MySQL JDBC Driver或者- W1 f- ?4 n# L( _
    MySQL C客户端这样的标准库即可。客户端支持的策略主要有两种:随机以及一致
    8 d. k; t1 z. D' m5 x, ~4 W6 i8 d$ o性哈希。一致性哈希的主要目的是将相同的SQL请求发送到同一台MergeServer,方: @- e1 {  p/ W! @. N
    便MergeServer对查询结果进行缓存。. k! i7 K6 R3 R; Q0 }( J
    3)如果请求MergeServer失败,则从MergeServer列表中重新选择一台
    + k, Q6 _. h. e  l3 O& sMergeServer重试;如果请求某台MergeServer失败超过一定的次数,将这台2 A7 [% |, c- D  s1 U; f7 s
    MergeServer加入黑名单并从MergeServer列表中删除。另外,客户端会定期请求- I9 e) U: e: i: B
    RootServer更新MergeServer地址列表。) a/ u5 C7 }0 W9 {' v# r( G; ?
    如果OceanBase部署多个集群,客户端还需要处理多个集群的流量分配问题。使! g0 R$ Y; W0 f; w5 J3 X) R
    用者可以设置多个集群之间的流量分配比例,客户端获取到流量分配比例后,按照
    5 q2 x! Y4 c( u* @+ b- y/ v6 |这个比例将请求发送到不同的集群。
    $ {+ W- q6 f5 W' `& SOceanBase程序升级版本时,往往先将备集群的读取流量调整为0,这时所有的7 w9 j* t  C2 a! j
    读写请求都只发往主集群,接着升级备集群的程序版本。备集群升级完成后将流量
    ' U5 L$ m6 F0 @2 X' |. O/ S2 ^* B逐步切换到备集群观察一段时间,如果没有出现异常,则将所有的流量切到备集
    3 o' C9 I' Z: ^) |, g群,并将备集群切换为主集群提供写服务。原来的主集群变为新的备集群,升级新
    9 H2 a5 {* D9 a. o8 T; F0 k$ m的备集群的程序版本后重新分配主备集群的流量比例。% O7 a7 P3 M' s" x) z  O
    8.3.3 RootServer; H" \+ H4 h, x2 h4 z+ U  c
    RootServer的功能主要包括:集群管理、数据分布以及副本管理。0 L( C/ O# B2 ^. n) \0 p
    RootServer管理集群中的所有MergeServer、ChunkServer以及UpdateServer。每个8 q1 \0 e* t2 v2 n7 x) ^# @
    集群内部同一时刻只允许一个UpdateServer提供写服务,这个UpdateServer成为主
    , w! N$ c* x) ^( C7 mUpdateServer。这种方式通过牺牲一定的可用性获取了强一致性。RootServer通过租
    ' G  \* r9 p1 B2 Z, _2 W5 O" U" X约(Lease)机制选择唯一的主UpdateServer,当原先的主UpdateServer发生故障后,
    ( z- f2 V2 w) T& ~/ }4 _RootServer能够在原先的租约失效后选择一台新的UpdateServer作为主UpdateServer。
    9 ?6 j0 Z% m# X另外,RootServer与MergeServer&ChunkServer之间保持心跳(heartbeat),从而能够/ A4 v# A) S. i2 _* U
    感知到在线和已经下线的MergeServer&ChunkServer机器列表。7 d+ s0 m- r4 ^" a) Z7 g
    OceanBase内部使用主键对表格中的数据进行排序和存储,主键由若干列组成并0 p/ C) B0 b" E9 m
    且具有唯一性。在OceanBase内部,基线数据按照主键排序并且划分为数据量大致相
    ; y% i" s! y  q8 f等的数据范围,称为子表(tablet)。每个子表的默认大小是256MB(可配置)。  H$ s3 |) {. r0 G
    OceanBase的数据分布方式与Bigtable一样采用顺序分布,不同的是,OceanBase没有2 ]& h9 A2 a' V) E7 k1 h
    采用根表(RootTable)+元数据表(MetaTable)两级索引结构,而是采用根表一级
    3 {6 ?* D# e  U* ^5 D索引结构。
    * T! c8 Z3 z( Z# E如图8-3所示,主键值在[1,100]之间的表格被划分为四个子表:1~25,26~3 X- G" ^$ i  O: w  d: g
    50,51~80以及81~100。RootServer中的根表记录了每个子表所在的ChunkServer位
    9 `3 t; m$ J- R8 w3 t; o0 `  a置信息,每个子表包含多个副本(一般为三个副本,可配置),分布在多台
    0 c' l$ |( ~. wChunkServer中。当其中某台ChunkServer发生故障时,RootServer能够检测到,并且触: d; v9 a( T# O" P
    发对这台ChunkServer上的子表增加副本的操作;另外,RootServer也会定期执行负载$ }8 x/ q2 E0 Q/ |, Z% j- a4 x
    均衡,选择某些子表从负载较高的机器迁移到负载较低的机器上。
    2 }3 O# Z' C, H9 O; u图 8-3 基线数据子表划分% u) o' S. X; T- l8 W6 o
    RootServer采用一主一备的结构,主备之间数据强同步,并通过Linux
    , k  Z* S' G/ S/ Q, ]/ k8 HHA(http://www.linux-ha.org)软件实现高可用性。主备RootServer之间共享VIP,当
    " d, G% y" c. M" p* |6 @! C2 e主RootServer发生故障后,VIP能够自动漂移到备RootServer所在的机器,备
    ) w% ]  i+ y! u3 c. `, G5 l% b4 hRootServer检测到以后切换为主RootServer提供服务。
    * W5 ~4 @+ R/ @& M8.3.4 MergeServer2 L: v- ]1 g7 T* p/ _3 s6 V& h
    MergeServer的功能主要包括:协议解析、SQL解析、请求转发、结果合并、多
    1 W2 W# X& y% l7 ^- p4 d表操作等。
    - d6 I9 e' `. YOceanBase客户端与MergeServer之间的协议为MySQL协议。MergeServer首先解
    + k5 L! i" w! u1 k( h0 M' U析MySQL协议,从中提取出用户发送的SQL语句,接着进行词法分析和语法分析,# T2 Z! P3 [6 U0 D0 v% T+ P. F
    生成SQL语句的逻辑查询计划和物理查询计划,最后根据物理查询计划调用
    , ]* @$ \0 S2 F+ W8 dOceanBase内部的各种操作符。
    " f( A- b4 G. B$ A+ MMergeServer缓存了子表分布信息,根据请求涉及的子表将请求转发给该子表所+ w8 a% a9 A7 [
    在的ChunkServer。如果是写操作,还会转发给UpdateServer。某些请求需要跨多个子
    - }) |1 Q) ?/ K8 {表,此时MergeServer会将请求拆分后发送给多台ChunkServer,并合并这些
    $ C  c8 D0 X+ J# NChunkServer返回的结果。如果请求涉及多个表格,MergeServer需要首先从
    + C8 c0 ^9 [0 ?. \ChunkServer获取每个表格的数据,接着再执行多表关联或者嵌套查询等操作。9 b( D8 o  A0 z* K
    MergeServer支持并发请求多台ChunkServer,即将多个请求发给多台: B( }. _3 k( ?$ b- d% V
    ChunkServer,再一次性等待所有请求的应答。另外,在SQL执行过程中,如果某个
    ) Z) F. U" k9 |子表所在的ChunkServer出现故障,MergeServer会将请求转发给该子表的其他副本所1 I' g+ x4 d0 _
    在的ChunkServer。这样,ChunkServer故障是不会影响用户查询的。9 y& B( k% I+ u( \# O+ q
    MergeServer本身是没有状态的,因此,MergeServer宕机不会对使用者产生影
    1 ^7 i0 Y0 l1 ~0 ?2 U# V' b+ \9 w4 f响,客户端会自动将发生故障的MergeServer屏蔽掉。; R& G- X/ u  b8 v4 _- }
    8.3.5 ChunkServer
    ) E; G! {9 e; zChunkServer的功能包括:存储多个子表,提供读取服务,执行定期合并以及数0 \8 }8 k4 W  ^- Y
    据分发。
    + n0 v4 S/ x2 O- g- K5 T4 |3 ~OceanBase将大表划分为大小约为256MB的子表,每个子表由一个或者多个
    & ]. {1 C9 F* [SSTable组成(一般为一个),每个SSTable由多个块(Block,大小为4KB~64KB之# T7 n, y6 i$ V+ Z
    间,可配置)组成,数据在SSTable中按照主键有序存储。查找某一行数据时,需要
      M  d5 [* V' M) ~$ t7 n) E首先定位这一行所属的子表,接着在相应的SSTable中执行二分查找。SSTable支持两5 n4 b9 g7 D% ]9 z/ N4 g
    种缓存模式,块缓存(Block Cache)以及行缓存(Row Cache)。块缓存以块为单位3 j* U2 L& c6 l+ t# s. f% u
    缓存最近读取的数据,行缓存以行为单位缓存最近读取的数据。1 ?) Z" b0 j: j# I8 N) c/ e
    MergeServer将每个子表的读取请求发送到子表所在的ChunkServer,ChunkServer首: r, ?9 {! a8 K: a) ~# ^1 B+ _- g
    先读取SSTable中包含的基线数据,接着请求UpdateServer获取相应的增量更新数据,. l0 Z& X3 G2 r# ]' t9 R
    并将基线数据与增量更新融合后得到最终结果。8 H/ M) U. r: ?% D0 s
    由于每次读取都需要从UpdateServer中获取最新的增量更新,为了保证读取性
    & c8 R- S7 i# \# y7 c& x1 e能,需要限制UpdateServer中增量更新的数据量,最好能够全部存放在内存中。
    . ?; _' j9 K" C3 Y5 q& R. F4 o& IOceanBase内部会定期触发合并或者数据分发操作,在这个过程中,ChunkServer将从
    + ]8 P+ J+ G7 c7 z9 dUpdateServer获取一段时间之前的更新操作。通常情况下,OceanBase集群会在每天
    * x2 a3 @3 ]% n! |5 h; J的服务低峰期(凌晨1:00开始,可配置)执行一次合并操作。这个合并操作往往也称4 @# t# o9 B2 a' L. s  z
    为每日合并。
    . q: c$ L; r+ S+ F8 ^; }8.3.6 UpdateServer5 ?, J3 M9 Y6 j, g+ S$ @% ~2 v
    UpdateServer是集群中唯一能够接受写入的模块,每个集群中只有一个主Update-
    , C+ Y4 K, c' |. H  l( M, }Server。UpdateServer中的更新操作首先写入到内存表,当内存表的数据量超过一定
    ) C0 j$ J( t' [4 a( \值时,可以生成快照文件并转储到SSD中。快照文件的组织方式与ChunkServer中的
    ! |' `) R' z9 p! F# w! USSTable类似,因此,这些快照文件也称为SSTable。另外,由于数据行的某些列被更5 f- K/ E7 t6 u: ?. s5 v) R
    新,某些列没被更新,SSTable中存储的数据行是稀疏的,称为稀疏型SSTable。0 [2 a( ^& a, w
    为了保证可靠性,主UpdateServer更新内存表之前需要首先写操作日志,并同步* U  [( @1 l+ Y
    到备UpdateServer。当主UpdateServer发生故障时,RootServer上维护的租约将失效,
    / r* }5 t$ O  q/ R/ w( v此时,RootServer将从备UpdateServer列表中选择一台最新的备UpdateServer切换为主
    7 G# Z, c0 d$ mUpdateServer继续提供写服务。UpdateServer宕机重启后需要首先加载转储的快照文5 X3 C% \& u7 v: o/ c1 n* j
    件(SSTable文件),接着回放快照点之后的操作日志。3 B) o2 W; F7 e8 A( t/ p
    由于集群中只有一台主UpdateServer提供写服务,因此,OceanBase很容易地实/ O- c: m- ^  Y
    现了跨行跨表事务,而不需要采用传统的两阶段提交协议。当然,这样也带来了一- T' [; G# z1 I$ w, e& f
    系列的问题。由于整个集群所有的读写操作都必须经过UpdateServer,UpdateServer的
    7 h' v) k) D* j6 f* z性能至关重要。OceanBase集群通过定期合并和数据分发这两种机制将UpdateServer7 F2 c1 d" [* y! q
    一段时间之前的增量更新源源不断地分散到ChunkServer,而UpdateServer只需要服务+ v% o+ o2 B0 w& V: \3 z6 ?
    最新一小段时间新增的数据,这些数据往往可以全部存放在内存中。另外,系统实
    9 [; |% u# U. ]/ K; P& ?7 f现时也需要对UpdateServer的内存操作、网络框架、磁盘操作做大量的优化。
    $ |2 ~: O. c0 W" c. a* w8 k8.3.7 定期合并&数据分发
    + L/ C8 t; {! Q( O  E, G" J) H: F) g定期合并和数据分发都是将UpdateServer中的增量更新分发到ChunkServer中的手
    - ^- ~* g1 A; R" m段,二者的整体流程比较类似:
    * |0 V# a5 g0 Z, ]  N- I" d1)UpdateServer冻结当前的活跃内存表(Active MemTable),生成冻结内存
    : l; @) }# u( \: Z2 O表,并开启新的活跃内存表,后续的更新操作都写入新的活跃内存表。/ B: K, d: g& z) Z+ [; |
    2)UpdateServer通知RootServer数据版本发生了变化,之后RootServer通过心跳- a7 @) j0 F& N  J9 U
    消息通知ChunkServer。
    # u; ^; }  D5 @; j1 Q6 f* {* H3)每台ChunkServer启动定期合并或者数据分发操作,从UpdateServer获取每个: y9 b" }% z3 ^$ T
    子表对应的增量更新数据。
    - F% r. c9 R3 {$ d0 `定期合并与数据分发两者之间的不同点在于,数据分发过程中ChunkServer只是
    6 D0 f+ w) H+ W& \# O1 M1 r' N% Z将UpdateServer中冻结内存表中的增量更新数据缓存到本地,而定期合并过程中& ]3 `7 q+ N% K2 r: s9 o, e# X/ s% a5 y
    ChunkServer需要将本地SSTable中的基线数据与冻结内存表的增量更新数据执行一次% x$ i, b2 H9 b1 d5 N9 u
    多路归并,融合后生成新的基线数据并存放到新的SSTable中。定期合并对系统服务1 j+ Q& h3 |" Y) E/ M- q: \1 J
    能力影响很大,往往安排在每天服务低峰期执行(例如凌晨1点开始),而数据分发4 ^8 g4 x3 @! M2 e% m' f
    可以不受限制。
    / X' m! m" n" m  U6 _( f" u如图8-4,活跃内存表冻结后生成冻结内存表,后续的写操作进入新的活跃内存0 w9 m( F* P  S! V8 [; d7 W! l
    表。定期合并过程中ChunkServer需要读取UpdateServer中冻结内存表的数据、融合后6 p2 x- B% S# a
    生成新的子表,即:0 a7 \0 z# g! b% k0 L' P# {2 V, `
    新子表=旧子表+冻结内存表
    ' M+ h& [( V7 O5 }1 Z图 8-4 定期合并不停读服务
    ' K- F) ?* h5 m* t) F( \8 x6 K1 d8 A虽然定期合并过程中各个ChunkServer的各个子表合并时间和完成时间可能都不2 f0 `. F) z% F9 Q, J! l% i
    相同,但并不影响读取服务。如果子表没有合并完成,那么使用旧子表,并且读取& b  Z" q8 u* Q' c
    UpdateServer中的冻结内存表以及新的活跃内存表;否则,使用新子表,只读取新的) J5 X7 x4 q" i3 A
    活跃内存表,即:
    ! B) ]5 l( \8 H查询结果=旧子表+冻结内存表+新的活跃内存表3 J0 w. q0 e0 w& B* E- T
    =新子表+新的活跃内存表! \4 _0 D& d0 L$ C* q' K

    0 [/ n' x1 w1 ~$ v  S, I( Q2 s3 `. l# i
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-1 13:50 , Processed in 0.307352 second(s), 33 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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