java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2574|回复: 0

《大规模分布式存储系统》第9章 分布式存储引擎【9.5】

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

    [LV.Master]出神入化

    2097

    主题

    3755

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66793

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

    发表于 2017-3-6 14:41:55 | 显示全部楼层 |阅读模式
    9.5 消除更新瓶颈) c  s' G8 }: U; T$ ~4 V
    UpdateServer单点看起来像是OceanBase架构的软肋,然而,经过OceanBase团队' \/ r: h5 v0 s4 M/ c* I* B
    持续不断地性能优化以及旁路导入功能的开发,单点的架构在实践过程中经受住了
    4 ]8 t( R+ ~4 l6 a/ ]线上考验。每年淘宝网“双十一”光棍节,OceanBase系统都承载着核心的数据库业) h$ P9 u: k  _8 M$ [
    务,系统访问量出现5到10倍的增长,而OceanBase只需简单地增加机器即可。# j9 U8 ~3 S; Z# X0 }/ w* s4 h
    当然,UpdateServer单点架构并不是不可突破。虽然目前UpdateServer单点架构
    0 ^' O% L2 N/ Y& |1 b还不是瓶颈,但是OceanBase系统设计时已经留好了“后门”,以后可以通过对系统打. ?4 W3 I" f& m- ]" ^) R3 F
    补丁的方式支持UpdateServer线性扩展。当然,这里可能会做一些牺牲,比如短期内7 r9 t, I" x  M+ ~1 z
    暂不支持全局事务,只支持针对单个用户的事务操作。
    7 s" q, P" e: B2 O$ t本节首先回顾OceanBase已经实现的优化工作,包括读写性能优化以及旁路导入
    % t. |* I1 D1 }' M! s  s7 O功能,接着介绍一种数据分区实现UpdateServer线性扩展的方法。
    9 o# {% C% C9 `+ g* [2 W9.5.1 读写优化回顾
    1 l" q( S' y: o# b* p% U+ u! I. bOceanBase UpdateServer相当于一个内存数据库,其架构设计和“世界上最快的内" \$ g$ C8 ?6 l1 V$ c( Q
    存数据库”MemSQL比较类似,能够支持每秒数百万次单行读写操作,这样的性能对
    5 x5 D* f/ U1 Y0 [  N5 b于目前关系数据库的应用场景都是足够的。为了达到这样的性能指标,我们已经完! r. ?7 c0 m# R( A' p
    成或正在进行的工作如下。
    0 N1 ?% _' S- U+ B- S! }8 D1.网络框架优化
    : ]+ O4 C) a- D( f9.2.2 节中提到,如果不经过优化,单机每秒最多能够接收的数据包个数只有
    1 e- M' C0 U' X% c; `: c( Q! U& v8 S10万个左右,而经过优化后的libeasy框架对于千兆网卡每秒最多收包个数超过50
    ( ?+ D) b6 b6 K# T万,对于万兆网卡则超过100万。另外,UpdateServer内部还会在软件层面实现多块
    # W) e( A* B4 W9 i( A4 I网卡的负载均衡,从而更好地发挥多网卡的优势。通过网络框架优化,使得单机支! g- Y; {3 L* F) t4 `: r) M
    持百万次操作成为可能。
    ) o0 E1 T7 t" ^, O2.高性能内存数据结构
    : s( m* S# L# D* Z/ d1 C7 OUpdateServer的底层是一颗高性能内存B树。为了最大程度地发挥多核的优势,B
    / v( t) ^2 A; @树实现时大部分情况下都做到了无锁(lock-free)。测试数据表明,即使在普通的16
    - L6 f# ?# Z. v) F" J0 E核机器上,OceanBase B树每秒支持的单行修改操作都超过150万次。6 X5 Y. _1 _; |0 @
    3.写操作日志优化
    * `9 o& [8 ?3 z) N! u3 A2 o, H& Q! y在软件层面,写操作日志涉及的工作主要有如下几点:5 T) v2 h7 I0 H% `% x: N6 `5 j5 F
    1)成组提交。将多个写操作聚合在一起,一次性刷入磁盘中。5 M: D1 @$ ~) _5 E' ]
    2)降低日志缓冲区的锁冲突。多个线程同时往日志缓冲区中追加数据,实现时
    : r$ \% X( o! M6 C( g* r需要尽可能地减少追加过程的锁冲突。追加过程包含两个阶段:第一个阶段是占
    2 {- i0 R9 v8 k6 G' A( g位,第二个阶段是拷贝数据,相比较而言,拷贝数据比较耗时。实现的关键在于只
    ) Q3 I9 A; K. J) D对占位操作互斥,而允许多线程并发拷贝数据。例如,有两个线程,线程1和线程- m" ^4 M1 w3 `( S: i0 m
    2,他们分别需要往缓冲区追加大小为100字节和大小为300字节的数据。假设缓冲区
    2 p; Z  l# e' d0 I5 N6 `- t0 p2 c1 q初始为空,那么,线程1可以首先占住位置0~100,线程2接着占住100~300。最% ?4 {1 K( X  \0 p" W! R
    后,线程1和线程2并发将数据拷贝到刚才占住的位置。
    5 P) O8 c0 p: X$ l% H* b3)日志文件并发写入。UpdateServer中每个日志缓冲区的大小一般为2MB,如
      z8 b( \0 i; W, ?& ?果写入太快,那么,很快会产生多个日志缓冲区需要刷入磁盘,可以并发地将这些1 J! p- F0 ~6 i. I
    日志缓冲区刷入不同的磁盘。当然,UpdateServer目前并没有实现2和3这两个优化& U9 F+ L# ^" N5 z( i& a
    点。在硬件层面,UpdateServer机器需要配置较好的RAID卡。这些RAID卡自带缓
    5 r; C# \1 Q: ~" O5 W存,而且容量比较大(例如1GB),从而进一步提升写磁盘性能。8 ]! l4 `' \; U1 A
    4.内存容量优化" @5 ?6 z) }( g  S5 j& X; N
    随着数据不断写入,UpdateServer的内存容量将成为瓶颈。因此,有两种解决思" D7 }: _5 c; f3 i, m6 ~- D
    路。一种思路是精心设计UpdateServer的内存数据结构,尽可能地节省内存使用;另
    5 s9 I& J7 b1 G& O7 J0 S+ d. i外一种思路就是将UpdateServer内存中的数据很快地分发出去。
    7 V0 d- X# Q4 g4 G1 v+ [' v; uOceanBase实现了这两种思路。首先,UpdateServer会将内存中的数据编码为精
    & l+ F  D  m* E- q心设计的格式,从9.3.1节中可以看出,100以内的64位整数在内存中只需要占用两个! P2 u1 @  q4 ?, C& R
    字节。这种编码格式不仅能够有效地减少内存占用,而且往往使得CPU缓存能够容' `5 I9 v) I7 ?; {
    纳更多的数据,从而弥补编码和解码操作造成的性能损失。另外,当UpdateServer的
    1 i$ |8 R6 F( ^* v) {内存使用量到达一定大小时,OceanBase会自动触发数据分发操作,将UpdateServer
    * B( o6 m; d" \4 A4 U7 r的数据分发到集群中的ChunkServer中,从而避免UpdateServer的内存容量成为瓶颈。
    . u, x8 v$ q# w  b当然,随着单机内存容量变得越来越大,普通的2U服务器已经具备1TB内存的扩展0 A, k# Z8 I) c" K: v$ f0 C
    能力,数据分发也可能只是一种过渡方案。
    6 K' ^# Z" z5 k; v, W& U9.5.2 数据旁路导入
    ' `" z9 c6 i+ o$ o5 [虽然OceanBase内部实现了大量优化技术,但是UpdateServer单点写入对于某些, V% \6 U6 {4 y. l2 [1 \
    OLAP应用仍然可能成为问题。这些应用往往需要定期(例如每天,每个月)导入大
    # |8 A/ Y8 y9 d" \9 v" W$ }批数据,对导入性能要求很高。为此,OceanBase专门开发了旁路导入功能,本节介
    ) _. o9 N. S5 A/ f0 K绍直接将数据导入到ChunkServer中的方法(即ChunkServer旁路导入)。3 ^1 ?3 a$ m# i# |& Q- X" U8 L
    OceanBase的数据按照全局有序排列,因此,旁路导入的第一步就是使用Hadoop
    # z: `* ^+ S) u7 Y: oMapReduce这样的工具将所有的数据排好序,并且划分为一个个有序的范围,每个范6 v$ k. }! n' I/ Y; p) w6 A
    围对应一个SSTable文件。接着,再将SSTable文件并行拷贝到集群中所有的
    # T( v" q' B5 [8 t; iChunkServer中。最后,通知RootServer要求每个ChunkServer并行加载这些SSTable文( s9 I$ r6 L5 g5 W* [
    件。每个SSTable文件对应ChunkServer的一个子表,ChunkServer加载完本地的SSTable
    ( t1 t8 b+ h2 {* G  l文件后会向RootServer汇报,RootServer接着将汇报的子表信息更新到RootTable中。
    ; l  Y& _3 \3 `* m! ?' ]例9-7 有4台ChunkServer:A、B、C和D。所有的数据排好序后划分为6个范
    7 I( Q. w& Z7 G* w( h围:r1(0~100]、r2(100~200]、r3(200~300]、r4(300~400]、r5(400~
    % _9 x0 }7 m  E. n4 K500]、r6(500~600],对应的SSTable文件分别记为sst1,sst2,……,sst6。假设每5 T+ ^$ p" K6 P  O5 h' P* k
    个子表存储两个副本,那么,拷贝完SSTable文件后,可能的分布情况为:5 J+ B, w% n& t5 C
    A:sst1,sst3,sst4
    4 A  n' g! v! K* \; @; Q9 \B:sst2,sst3,sst5
    ' r! e1 x4 t* ^. |: I. t; xC:sst1,sst4,sst6* n6 M/ j& S9 i! k1 O* m  m
    D:sst2,sst5,sst6% h; w" `8 O" e. p1 {
    接着,每个ChunkServer分别加载本地的SSTable文件,完成后向RootServer汇
    . P* Q8 `! b# X1 e7 c4 s+ P报。RootServer最终会将这些信息记录到RootTable中,如下:* ?9 J2 A4 P. m% j
    r1(0~100]:A、C
    ; b0 o6 o- S- `0 ^+ B: pr2(100~200]:B、D4 t( {: f8 E1 q; M; O2 p$ o
    r3(200~300]:A、B
    5 t% g) @* r3 P! H3 O% Ur4(300~400]:A、C! d4 G7 O3 w6 l) H2 a' e6 |
    r5(400~500]:B、D
    , V! f5 P( O- o& d6 ^6 e( w. Nr6(500~600]:C、D
    7 F- f9 g; Q: m% A: J如果导入的过程中ChunkServer发生故障,例如拷贝sst1到机器C失败,那么,旁% G  Z4 [& H& q: y4 [* I6 e
    路导入模块会自动选择另外一台机器拷贝数据。
    ) [0 [+ w) E. @当然,实现旁路导入功能时还需要考虑很多问题。例如,如何支持将数据导入) T# y2 q! U2 `3 B- P
    到多个数据中心的主备OceanBase集群,这里不会涉及这些细节。
    ( b% I8 p" V0 F& |1 p9.5.3 数据分区% ~0 T6 h+ V: ~* P5 }( i; b: x
    虽然我们坚持认为通过单机性能优化以及硬件性能的提升,UpdateServer单点对1 u( u5 l; h; L1 L- u, T2 D! y* q
    于互联网数据库业务不会成为瓶颈。但是,随着OceanBase的应用场景越来越广,例
    ! }1 r, ?7 W4 P' U" i" Y如,存储原始日志,我们也可能需要实现更新节点可扩展。本节探讨一种可能的做5 V# o+ f( W  D- `
    法。: S' X( {* [8 |4 N4 l
    OceanBase可以借鉴关系数据库中的分区表的概念,将数据划分为多个分区,允
    0 m: T+ T" N: m, A# l3 J许不同的分区被不同的UpdateServer服务。例如,将所有的数据按照哈希的方式划分
    ' Z2 z5 P: z& _$ ^- H2 P# A为4096个分区,这样,同一个集群中最多允许4096个写节点。
    - m; A0 z. H( z如图9-11所示,可以将Users表格和Albums的user_id列按照相同的规则做哈希,
    * m' R8 R6 R3 I9 \$ R: R/ F) b* d这样,同一个用户的所有数据属于相同的分区。由于同一个分区只会被同一个
    6 D; A% V: r8 FUpdateServer服务,因此,保证了同一个用户下读写操作的事务性,另外,不同用户( ]# U5 `/ {# V5 ^$ a) B" L
    之间的事务可以通过两阶段提交或者最终一致性的方式实现。这种方式实现起来非& S  m7 w* h0 {
    常简单,而且能够完全兼容SQL语法。7 k+ z9 d' V0 D1 @% @! p( U
    图 9-11 哈希分区SQL语法
    , t  X9 r# G2 D% n: n9 C% Q从图8-1中的整体架构图可以看出,在目前的单更新节点架构中,UpdateServer进
    " B6 C  H% r. D+ r# }3 c程总是与ChunkServer进程部署到不同的服务器,而且两种服务器对硬件的要求不: s, W' q; W' u% U" N2 q. b( X
    同。如果OceanBase支持哈希分区,还能够将UpdateServer进程和ChunkServer进程部
    " `0 \% P- J. y% R  g' K  g* P) H( N署到一起,这样部署起来会更加方便。
    ' q3 V% o! @7 E6 n4 ~除了哈希分区,OceanBase还能够通过范围分区实现更新节点可扩展,即不同的
    1 |" G" w4 [+ Q; o0 ?. j1 T用户按照user_id有序分布到多台UpdateServer。虽然支持UpdateServer线性可扩展的: g2 e# Y5 n4 u/ ?' H; t  M" E1 a& _2 e
    架构看似“比较优雅”,但是,这件事情并不紧急。这是因为,OLTP类应用对性能的
    & E- Y$ A/ z3 k& d' h  r+ \需求是有天花板的(例如全世界人口共50亿,即使其中五分之一的人都在某一天产
    1 B7 D5 E/ G. U0 J" N/ e生了一笔交易,这一天的总交易笔数也只有10亿笔),单UpdateServer对于OLTP类数6 B. a. u2 n& }" m' y
    据库业务的性能是足够的。& _9 ^' V' K: V* ~* H' P) f2 H
    & ]" I3 w; Q0 L! h+ t) H8 |+ @

    ; i$ _% D' L- ~$ I( S- `
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-2 18:41 , Processed in 0.113969 second(s), 33 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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