java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2575|回复: 0

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

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

    [LV.Master]出神入化

    2099

    主题

    3757

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66805

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

    发表于 2017-3-6 14:41:55 | 显示全部楼层 |阅读模式
    9.5 消除更新瓶颈
    . D9 Z6 Z( D% p; OUpdateServer单点看起来像是OceanBase架构的软肋,然而,经过OceanBase团队
    9 X6 U: n1 v) A- m7 U7 @) N3 p持续不断地性能优化以及旁路导入功能的开发,单点的架构在实践过程中经受住了
    , L8 x: p& H# v/ F" I线上考验。每年淘宝网“双十一”光棍节,OceanBase系统都承载着核心的数据库业
    ) g0 B( r* t6 L务,系统访问量出现5到10倍的增长,而OceanBase只需简单地增加机器即可。
    ( t, \) B% ~$ F  u) k  y* A2 Y* U当然,UpdateServer单点架构并不是不可突破。虽然目前UpdateServer单点架构0 q8 Q" L3 z: X6 w' i4 C
    还不是瓶颈,但是OceanBase系统设计时已经留好了“后门”,以后可以通过对系统打7 L- b+ C( T1 B: B, q  O: y9 s. q; e
    补丁的方式支持UpdateServer线性扩展。当然,这里可能会做一些牺牲,比如短期内( G9 |2 s: g( d3 ~
    暂不支持全局事务,只支持针对单个用户的事务操作。
    & X# ?, w  x$ I7 e' I本节首先回顾OceanBase已经实现的优化工作,包括读写性能优化以及旁路导入1 y+ r! d, t! \! H1 \8 ~" U
    功能,接着介绍一种数据分区实现UpdateServer线性扩展的方法。
    / l% c* X! z" y' {* D9.5.1 读写优化回顾
    2 f% Y: w! Y. NOceanBase UpdateServer相当于一个内存数据库,其架构设计和“世界上最快的内) W& y6 L; A5 x# p+ N
    存数据库”MemSQL比较类似,能够支持每秒数百万次单行读写操作,这样的性能对
    7 D1 e/ V# _3 ^0 v+ a于目前关系数据库的应用场景都是足够的。为了达到这样的性能指标,我们已经完# Q5 L+ y* O% ]4 T  U! s* |3 z
    成或正在进行的工作如下。, y1 j: ^7 y4 J/ j2 e1 q6 E
    1.网络框架优化6 Y- ?- t" _: F0 ~4 {1 K
    9.2.2 节中提到,如果不经过优化,单机每秒最多能够接收的数据包个数只有5 v+ s2 d1 P$ p8 i2 A% Z
    10万个左右,而经过优化后的libeasy框架对于千兆网卡每秒最多收包个数超过50
    $ Q3 F+ f. U- n5 w: z7 M' p万,对于万兆网卡则超过100万。另外,UpdateServer内部还会在软件层面实现多块& F$ l, U1 Y9 b' \
    网卡的负载均衡,从而更好地发挥多网卡的优势。通过网络框架优化,使得单机支
    , j9 w  `# r4 b& a持百万次操作成为可能。
    - u, A: N' i+ f2.高性能内存数据结构  d5 |5 H" ]1 N. ]2 p
    UpdateServer的底层是一颗高性能内存B树。为了最大程度地发挥多核的优势,B4 H: \. J4 L+ H7 A. ?; k# {1 x3 {
    树实现时大部分情况下都做到了无锁(lock-free)。测试数据表明,即使在普通的162 T$ q2 N% T: h( w' L4 A% B* t
    核机器上,OceanBase B树每秒支持的单行修改操作都超过150万次。9 Q8 f- [2 p, s# Y
    3.写操作日志优化2 q. j% W* w' W
    在软件层面,写操作日志涉及的工作主要有如下几点:
    ; I/ d) _. p" z/ h! w2 b  z1 L! `1)成组提交。将多个写操作聚合在一起,一次性刷入磁盘中。
    " K. s) N4 _. H+ A8 w. o2)降低日志缓冲区的锁冲突。多个线程同时往日志缓冲区中追加数据,实现时
    + b- P* Y' \8 f需要尽可能地减少追加过程的锁冲突。追加过程包含两个阶段:第一个阶段是占( d  t' o! y  c. Y, p" x. p
    位,第二个阶段是拷贝数据,相比较而言,拷贝数据比较耗时。实现的关键在于只0 x* Q: m9 N1 L( Q8 X
    对占位操作互斥,而允许多线程并发拷贝数据。例如,有两个线程,线程1和线程
    ) v1 z" S; ]6 E2 }  P2,他们分别需要往缓冲区追加大小为100字节和大小为300字节的数据。假设缓冲区
    9 g7 B  Q, I5 C# N* _- u+ Q  J1 p- K0 P初始为空,那么,线程1可以首先占住位置0~100,线程2接着占住100~300。最- Z; {7 j' r  f5 C
    后,线程1和线程2并发将数据拷贝到刚才占住的位置。% k1 q7 p- A7 {4 l9 Q  V
    3)日志文件并发写入。UpdateServer中每个日志缓冲区的大小一般为2MB,如
    6 V/ T0 ~) Y7 V! E3 \" W果写入太快,那么,很快会产生多个日志缓冲区需要刷入磁盘,可以并发地将这些
    " @8 _+ M5 ~5 j) m4 b5 Z  R日志缓冲区刷入不同的磁盘。当然,UpdateServer目前并没有实现2和3这两个优化
    ) j5 y/ \& q: |6 g# p; A点。在硬件层面,UpdateServer机器需要配置较好的RAID卡。这些RAID卡自带缓
    7 c/ Y  ~( S* f$ x  f1 B0 z存,而且容量比较大(例如1GB),从而进一步提升写磁盘性能。
    5 T% ~+ `5 ~0 n/ c1 A6 f4.内存容量优化4 y9 q$ G5 R" {2 F
    随着数据不断写入,UpdateServer的内存容量将成为瓶颈。因此,有两种解决思$ B  t. U8 Q9 \: k) T; z1 w
    路。一种思路是精心设计UpdateServer的内存数据结构,尽可能地节省内存使用;另
    ( Q2 x3 ], z  F0 Y外一种思路就是将UpdateServer内存中的数据很快地分发出去。* `& K# S/ H7 n) E  w; r
    OceanBase实现了这两种思路。首先,UpdateServer会将内存中的数据编码为精
    8 O* d" o" S- X( T心设计的格式,从9.3.1节中可以看出,100以内的64位整数在内存中只需要占用两个
    & }# ]+ `! C9 |0 x字节。这种编码格式不仅能够有效地减少内存占用,而且往往使得CPU缓存能够容+ }! P0 \5 L* }1 n( o7 B
    纳更多的数据,从而弥补编码和解码操作造成的性能损失。另外,当UpdateServer的; C$ E8 e2 o- t2 F* f% |1 _* ?
    内存使用量到达一定大小时,OceanBase会自动触发数据分发操作,将UpdateServer0 P* b1 p& M9 u5 W0 H, H+ T8 _
    的数据分发到集群中的ChunkServer中,从而避免UpdateServer的内存容量成为瓶颈。
    8 |* i9 O- [8 ^5 u+ \当然,随着单机内存容量变得越来越大,普通的2U服务器已经具备1TB内存的扩展/ C# H# F$ c& D% Z% N
    能力,数据分发也可能只是一种过渡方案。
    ( R' Y8 S- X; ?+ G! ^9.5.2 数据旁路导入
    , _0 Y: K8 R7 s% s5 o虽然OceanBase内部实现了大量优化技术,但是UpdateServer单点写入对于某些* J$ O) g' b# m. W
    OLAP应用仍然可能成为问题。这些应用往往需要定期(例如每天,每个月)导入大' V7 v' W+ |- ^& ]  P( V& C2 n
    批数据,对导入性能要求很高。为此,OceanBase专门开发了旁路导入功能,本节介
    8 S4 H7 j: y, f$ n$ A绍直接将数据导入到ChunkServer中的方法(即ChunkServer旁路导入)。
    / ]9 Y1 t3 t% WOceanBase的数据按照全局有序排列,因此,旁路导入的第一步就是使用Hadoop. D. ]3 s7 ?/ [- b$ Y( u5 ?' v  @
    MapReduce这样的工具将所有的数据排好序,并且划分为一个个有序的范围,每个范3 P# P9 j+ n. s- s# \( a- ]0 J
    围对应一个SSTable文件。接着,再将SSTable文件并行拷贝到集群中所有的
    . e% `7 b, x# bChunkServer中。最后,通知RootServer要求每个ChunkServer并行加载这些SSTable文3 ^3 x9 M+ x& H
    件。每个SSTable文件对应ChunkServer的一个子表,ChunkServer加载完本地的SSTable
    . d) d" u+ m  {文件后会向RootServer汇报,RootServer接着将汇报的子表信息更新到RootTable中。2 f* b" e/ J# Z7 V9 _$ ?
    例9-7 有4台ChunkServer:A、B、C和D。所有的数据排好序后划分为6个范4 `$ W, x/ c8 U0 R. Q, g9 f
    围:r1(0~100]、r2(100~200]、r3(200~300]、r4(300~400]、r5(400~
    $ C* d* b3 z* C( ~+ }1 C) l500]、r6(500~600],对应的SSTable文件分别记为sst1,sst2,……,sst6。假设每
    - k5 F6 R3 U6 t* l: j+ z. P个子表存储两个副本,那么,拷贝完SSTable文件后,可能的分布情况为:
    , Z: X0 C) d9 zA:sst1,sst3,sst4
    4 D! r# L$ y4 t( A3 F6 M8 qB:sst2,sst3,sst5
      ?2 C) m4 b1 V% P% C/ X# ?4 r) }( LC:sst1,sst4,sst6" H$ |: v; r; y0 c8 s4 ^
    D:sst2,sst5,sst6: y; y8 s" p* m- K: {& c5 K
    接着,每个ChunkServer分别加载本地的SSTable文件,完成后向RootServer汇- R% G2 }, g  C4 Z1 A
    报。RootServer最终会将这些信息记录到RootTable中,如下:) N5 i" p, }# x% f+ I
    r1(0~100]:A、C% ~8 v2 L; M) p1 m
    r2(100~200]:B、D
    . F" ?4 Z7 d- C; N; Y0 Wr3(200~300]:A、B+ T" H) U- Q5 c! L8 c0 n/ P9 }; a& S
    r4(300~400]:A、C
    & l% @' \; `5 i+ Z$ B0 ir5(400~500]:B、D
    + T, E! @8 R5 i) S2 Rr6(500~600]:C、D
    & B; r, O, w  \如果导入的过程中ChunkServer发生故障,例如拷贝sst1到机器C失败,那么,旁7 K( L$ |7 [* t
    路导入模块会自动选择另外一台机器拷贝数据。
    $ ?7 ?2 T( U  f/ x当然,实现旁路导入功能时还需要考虑很多问题。例如,如何支持将数据导入
    $ c# r' h8 R" Y6 I5 n1 z  M到多个数据中心的主备OceanBase集群,这里不会涉及这些细节。- i* o- j3 Y& l, I' ~- s* n) `
    9.5.3 数据分区
    " j2 `5 W) s* N' J虽然我们坚持认为通过单机性能优化以及硬件性能的提升,UpdateServer单点对
    ; t- ]) _. B2 W于互联网数据库业务不会成为瓶颈。但是,随着OceanBase的应用场景越来越广,例
    ( C9 I) T4 H) G. `3 x如,存储原始日志,我们也可能需要实现更新节点可扩展。本节探讨一种可能的做
    ; m5 b/ ?* D2 \3 T法。
      c9 Y. K+ I2 a# j: fOceanBase可以借鉴关系数据库中的分区表的概念,将数据划分为多个分区,允; W6 e/ z) }9 J4 W' X1 `. e; Q8 j
    许不同的分区被不同的UpdateServer服务。例如,将所有的数据按照哈希的方式划分) `* U: s* h: P2 S0 k7 R  w
    为4096个分区,这样,同一个集群中最多允许4096个写节点。4 g* Z9 I# @3 N& b. S
    如图9-11所示,可以将Users表格和Albums的user_id列按照相同的规则做哈希,
    ! Q; h1 i. m+ ^" r: [0 Q9 H这样,同一个用户的所有数据属于相同的分区。由于同一个分区只会被同一个! @& w+ w6 p2 @  U8 X3 n
    UpdateServer服务,因此,保证了同一个用户下读写操作的事务性,另外,不同用户
    3 K4 N- _0 E* [9 f' M. ]1 q之间的事务可以通过两阶段提交或者最终一致性的方式实现。这种方式实现起来非
    4 H) b% O7 G" v3 [* H% K常简单,而且能够完全兼容SQL语法。
    # O% g$ `/ U0 G% K2 J) _, h图 9-11 哈希分区SQL语法. z: N# w; c& I
    从图8-1中的整体架构图可以看出,在目前的单更新节点架构中,UpdateServer进, }) t; ^+ `) C, J9 [
    程总是与ChunkServer进程部署到不同的服务器,而且两种服务器对硬件的要求不
    4 T- j, O6 _' L: w5 k同。如果OceanBase支持哈希分区,还能够将UpdateServer进程和ChunkServer进程部5 |( I, r  h* d
    署到一起,这样部署起来会更加方便。
    6 T# ?0 O' h9 a除了哈希分区,OceanBase还能够通过范围分区实现更新节点可扩展,即不同的* V7 G3 |/ K3 Y0 t4 \
    用户按照user_id有序分布到多台UpdateServer。虽然支持UpdateServer线性可扩展的
    5 w' X2 y+ c! {0 G# p) Q8 f架构看似“比较优雅”,但是,这件事情并不紧急。这是因为,OLTP类应用对性能的
    * k( `# r; ]+ [1 J. _需求是有天花板的(例如全世界人口共50亿,即使其中五分之一的人都在某一天产+ |# X+ @% Z4 x* R  K% X
    生了一笔交易,这一天的总交易笔数也只有10亿笔),单UpdateServer对于OLTP类数
    / X" o- \2 O  F& H% v) e* R据库业务的性能是足够的。
    ! ~4 [, C6 e4 n6 w9 f0 t: T% n: _8 M; Z9 X0 e, P8 y

    $ N( d& g, z6 T
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-4 12:29 , Processed in 0.124390 second(s), 31 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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