java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2571|回复: 0

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

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

    [LV.Master]出神入化

    2096

    主题

    3754

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66788

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

    发表于 2017-3-6 14:41:55 | 显示全部楼层 |阅读模式
    9.5 消除更新瓶颈
    % Q* r; m+ i  d7 U7 z* r2 f8 hUpdateServer单点看起来像是OceanBase架构的软肋,然而,经过OceanBase团队5 L8 a* v* @% ?5 P' F
    持续不断地性能优化以及旁路导入功能的开发,单点的架构在实践过程中经受住了, B5 q" ~2 g; T+ ~6 P
    线上考验。每年淘宝网“双十一”光棍节,OceanBase系统都承载着核心的数据库业
    2 |) g! C5 ^  }. |6 @" D务,系统访问量出现5到10倍的增长,而OceanBase只需简单地增加机器即可。% p2 i  G- x. \0 j
    当然,UpdateServer单点架构并不是不可突破。虽然目前UpdateServer单点架构
    . l$ }* E+ L$ q% |8 N0 ?还不是瓶颈,但是OceanBase系统设计时已经留好了“后门”,以后可以通过对系统打, q. c5 Y# n. h/ Y
    补丁的方式支持UpdateServer线性扩展。当然,这里可能会做一些牺牲,比如短期内8 l6 t; O# U* @
    暂不支持全局事务,只支持针对单个用户的事务操作。* _2 D' J! E7 E+ a  ~
    本节首先回顾OceanBase已经实现的优化工作,包括读写性能优化以及旁路导入
    5 N+ k6 R, A% j: n3 [; T功能,接着介绍一种数据分区实现UpdateServer线性扩展的方法。- f& M* a" T! a
    9.5.1 读写优化回顾) A) D7 l7 A5 M' h/ F; d
    OceanBase UpdateServer相当于一个内存数据库,其架构设计和“世界上最快的内
    6 D' r( i) O1 t# P' r存数据库”MemSQL比较类似,能够支持每秒数百万次单行读写操作,这样的性能对+ ?; h7 v1 d( A7 a* q! }8 N. w
    于目前关系数据库的应用场景都是足够的。为了达到这样的性能指标,我们已经完$ i7 h) d' k: u, {6 G
    成或正在进行的工作如下。
    ! [, T% b8 c5 Q( D! Z- k* `/ `1.网络框架优化4 |- y; u; O' w  a
    9.2.2 节中提到,如果不经过优化,单机每秒最多能够接收的数据包个数只有
    5 {- z' c- `3 ], m10万个左右,而经过优化后的libeasy框架对于千兆网卡每秒最多收包个数超过50
    - q, a2 i, Q! @万,对于万兆网卡则超过100万。另外,UpdateServer内部还会在软件层面实现多块
    6 M" t' E" U. L: {' o: n网卡的负载均衡,从而更好地发挥多网卡的优势。通过网络框架优化,使得单机支; Z  i9 l7 w7 |% B# N0 M& F
    持百万次操作成为可能。" Y9 ?6 J& R  ~4 E$ _$ F
    2.高性能内存数据结构6 l% [, k' c& X, J  E# w/ G' g
    UpdateServer的底层是一颗高性能内存B树。为了最大程度地发挥多核的优势,B) B6 f; O0 v" g" I3 i  v1 I9 {
    树实现时大部分情况下都做到了无锁(lock-free)。测试数据表明,即使在普通的16
    ; Q2 l- [; B! w8 ]* u) v3 r, U2 d核机器上,OceanBase B树每秒支持的单行修改操作都超过150万次。
    ( C8 Q0 _  k0 t# b3.写操作日志优化7 |7 _. n* B( s( ]! K
    在软件层面,写操作日志涉及的工作主要有如下几点:" \) V! U! {( S2 B& ^7 P
    1)成组提交。将多个写操作聚合在一起,一次性刷入磁盘中。- ^5 h0 c, r! @) w: l' K' k9 X1 ]3 O  j& d
    2)降低日志缓冲区的锁冲突。多个线程同时往日志缓冲区中追加数据,实现时
    7 V( t! s% n  R( x4 T) k需要尽可能地减少追加过程的锁冲突。追加过程包含两个阶段:第一个阶段是占
    ( ^: i# T5 c8 e2 n# r8 F" V0 o/ L位,第二个阶段是拷贝数据,相比较而言,拷贝数据比较耗时。实现的关键在于只
    . q- z% D  O! l; W; j对占位操作互斥,而允许多线程并发拷贝数据。例如,有两个线程,线程1和线程. s  }( A7 `/ s+ O/ U6 F$ A
    2,他们分别需要往缓冲区追加大小为100字节和大小为300字节的数据。假设缓冲区6 p5 ~: ?+ Q! h
    初始为空,那么,线程1可以首先占住位置0~100,线程2接着占住100~300。最
    : m) P; `# i+ y后,线程1和线程2并发将数据拷贝到刚才占住的位置。* v; a0 [1 f1 t, e6 j( q
    3)日志文件并发写入。UpdateServer中每个日志缓冲区的大小一般为2MB,如% Y, E0 y: M. T
    果写入太快,那么,很快会产生多个日志缓冲区需要刷入磁盘,可以并发地将这些
    8 q5 s' z5 t9 K$ M0 k# _日志缓冲区刷入不同的磁盘。当然,UpdateServer目前并没有实现2和3这两个优化3 G. ~7 ?4 P! |$ t: _
    点。在硬件层面,UpdateServer机器需要配置较好的RAID卡。这些RAID卡自带缓+ X  a' O' Z4 ]' _
    存,而且容量比较大(例如1GB),从而进一步提升写磁盘性能。- n2 @9 v" H& }, V# C  M5 d
    4.内存容量优化
    ; e8 X" e2 Q! P. O. ]! h  i: }/ w随着数据不断写入,UpdateServer的内存容量将成为瓶颈。因此,有两种解决思1 o* I9 \& a, _5 y
    路。一种思路是精心设计UpdateServer的内存数据结构,尽可能地节省内存使用;另
    ) j- A, Z- C9 g! C- Y外一种思路就是将UpdateServer内存中的数据很快地分发出去。
    ( Q  f2 k1 }3 T* `+ Y3 x$ N4 UOceanBase实现了这两种思路。首先,UpdateServer会将内存中的数据编码为精; z- t4 s* @# @/ G
    心设计的格式,从9.3.1节中可以看出,100以内的64位整数在内存中只需要占用两个
    " Q% e0 Y  z) A* |7 R/ G' F+ f/ G' G字节。这种编码格式不仅能够有效地减少内存占用,而且往往使得CPU缓存能够容
    & c5 Z& q. L) }# F, Q# W/ C# n9 W纳更多的数据,从而弥补编码和解码操作造成的性能损失。另外,当UpdateServer的
      Q8 w. [9 ?/ ]& E3 o内存使用量到达一定大小时,OceanBase会自动触发数据分发操作,将UpdateServer$ A! [* }$ Z; M0 [8 X
    的数据分发到集群中的ChunkServer中,从而避免UpdateServer的内存容量成为瓶颈。+ o! z$ [; w8 d) k2 z
    当然,随着单机内存容量变得越来越大,普通的2U服务器已经具备1TB内存的扩展; T* c# r0 C; H; J' C( b
    能力,数据分发也可能只是一种过渡方案。7 N( Q+ i* E' ~% {6 F+ J
    9.5.2 数据旁路导入
    " m  J9 O5 y: n虽然OceanBase内部实现了大量优化技术,但是UpdateServer单点写入对于某些
    9 {4 F. a) }( r5 oOLAP应用仍然可能成为问题。这些应用往往需要定期(例如每天,每个月)导入大
    6 q! ]$ W! A5 u9 y* D2 r" j批数据,对导入性能要求很高。为此,OceanBase专门开发了旁路导入功能,本节介. z; x1 ]( |; Y; `; N! y5 }- M
    绍直接将数据导入到ChunkServer中的方法(即ChunkServer旁路导入)。" I' C  a; p* B7 U
    OceanBase的数据按照全局有序排列,因此,旁路导入的第一步就是使用Hadoop% e8 ?9 ~( q6 T3 m: o( T" A
    MapReduce这样的工具将所有的数据排好序,并且划分为一个个有序的范围,每个范+ C, t' Y9 Q2 \6 C# X
    围对应一个SSTable文件。接着,再将SSTable文件并行拷贝到集群中所有的
      F; c  s3 F3 dChunkServer中。最后,通知RootServer要求每个ChunkServer并行加载这些SSTable文
    - b- h* G7 B9 j4 W件。每个SSTable文件对应ChunkServer的一个子表,ChunkServer加载完本地的SSTable7 j' P7 A  Q! U
    文件后会向RootServer汇报,RootServer接着将汇报的子表信息更新到RootTable中。+ R" O; m8 |! O) s  {
    例9-7 有4台ChunkServer:A、B、C和D。所有的数据排好序后划分为6个范
    ' A- l2 `% U( ]5 D  ^' N2 X6 |5 n: I围:r1(0~100]、r2(100~200]、r3(200~300]、r4(300~400]、r5(400~
    . U3 M1 \$ [1 t4 b/ `1 L500]、r6(500~600],对应的SSTable文件分别记为sst1,sst2,……,sst6。假设每, ~: e8 [0 S3 O6 e* c0 _7 Q
    个子表存储两个副本,那么,拷贝完SSTable文件后,可能的分布情况为:: k8 {/ b# @7 X* v2 z
    A:sst1,sst3,sst4
    - a$ @9 v0 p9 [5 B1 o4 DB:sst2,sst3,sst5
    1 i" \  U* d9 W  HC:sst1,sst4,sst6
    , x' m$ g8 r! m% s7 X# |D:sst2,sst5,sst6) a& j! ?- R$ v7 o- x+ n
    接着,每个ChunkServer分别加载本地的SSTable文件,完成后向RootServer汇* P( J/ w; ~2 K: ?% l* X; V' _
    报。RootServer最终会将这些信息记录到RootTable中,如下:
    # U" a/ ?' X4 e9 ~' i9 A2 Jr1(0~100]:A、C
    + L% U# u! q- {; g1 Wr2(100~200]:B、D# d6 t, V: X, v! G  c: I# f! D' D
    r3(200~300]:A、B* x' [5 ?! @$ v
    r4(300~400]:A、C
    # l! I1 f) p- a* Q1 Q6 xr5(400~500]:B、D  G5 G! o- b% t+ i! F' }/ L
    r6(500~600]:C、D
    % O# Q# h3 l0 H$ I3 a; W如果导入的过程中ChunkServer发生故障,例如拷贝sst1到机器C失败,那么,旁- ^: B" G3 Q( ?3 J. }! J& Z
    路导入模块会自动选择另外一台机器拷贝数据。
    " k# _/ M7 N) `7 Q% h4 Z当然,实现旁路导入功能时还需要考虑很多问题。例如,如何支持将数据导入
    9 J. R( C% G& M0 t) T3 Z! U到多个数据中心的主备OceanBase集群,这里不会涉及这些细节。
    9 {% d8 i) R* Z9.5.3 数据分区) T4 z1 R- V& _( ^/ i  i5 c
    虽然我们坚持认为通过单机性能优化以及硬件性能的提升,UpdateServer单点对
    ( A) c! v& L) L+ h; i于互联网数据库业务不会成为瓶颈。但是,随着OceanBase的应用场景越来越广,例1 [$ _5 u2 B9 \6 z- y* }' a
    如,存储原始日志,我们也可能需要实现更新节点可扩展。本节探讨一种可能的做( R; T9 V5 E1 y" o
    法。
    8 s7 f/ d' [) n; C  ~6 U5 a! rOceanBase可以借鉴关系数据库中的分区表的概念,将数据划分为多个分区,允9 m) {3 w& k8 ]7 Y! i
    许不同的分区被不同的UpdateServer服务。例如,将所有的数据按照哈希的方式划分
    # W2 c) H* w! G$ z* m# f: U为4096个分区,这样,同一个集群中最多允许4096个写节点。
    # ]2 t- r: d! _0 {. l; T( {2 ~4 Y* N如图9-11所示,可以将Users表格和Albums的user_id列按照相同的规则做哈希,, _2 W. ~5 I+ Y! V: [% H+ y  i
    这样,同一个用户的所有数据属于相同的分区。由于同一个分区只会被同一个& w. i% z3 F1 a" }5 m: u+ l' Q; P
    UpdateServer服务,因此,保证了同一个用户下读写操作的事务性,另外,不同用户  ]/ \8 n: o( }' z9 R7 `! {
    之间的事务可以通过两阶段提交或者最终一致性的方式实现。这种方式实现起来非" f1 Z) C8 ^$ G: Y7 Q7 q1 ~; C
    常简单,而且能够完全兼容SQL语法。
    . P! D1 C1 P3 F' z$ a# e: I图 9-11 哈希分区SQL语法
    : D/ }- W  M, h7 V从图8-1中的整体架构图可以看出,在目前的单更新节点架构中,UpdateServer进
    * ?3 `! F0 k- J6 o$ k0 u3 I程总是与ChunkServer进程部署到不同的服务器,而且两种服务器对硬件的要求不
    : C; }5 X' t# Y5 f. J- ~7 E同。如果OceanBase支持哈希分区,还能够将UpdateServer进程和ChunkServer进程部
    8 ^: q+ u5 i0 ]2 l署到一起,这样部署起来会更加方便。
    % X& w; p/ ~" w2 p* s$ s除了哈希分区,OceanBase还能够通过范围分区实现更新节点可扩展,即不同的  @/ [/ F, Z, q8 O
    用户按照user_id有序分布到多台UpdateServer。虽然支持UpdateServer线性可扩展的
    : C) ^8 h$ J" A3 p2 o架构看似“比较优雅”,但是,这件事情并不紧急。这是因为,OLTP类应用对性能的
    * H+ M) ^! q6 {9 t# o" ~5 k1 Z* s需求是有天花板的(例如全世界人口共50亿,即使其中五分之一的人都在某一天产
    / d1 m( C% E. O! O9 a0 u% q生了一笔交易,这一天的总交易笔数也只有10亿笔),单UpdateServer对于OLTP类数
    , N6 k9 X6 l6 z3 ~( ?据库业务的性能是足够的。0 E& V! M, s5 M) G! K* s( I( d
    3 I6 X1 H0 g  K: c- a6 l+ o

    2 T$ v: x! {5 B; A: d
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-1 14:11 , Processed in 0.154402 second(s), 33 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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