java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2572|回复: 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 消除更新瓶颈
    , u# p* z# v1 O/ q8 }UpdateServer单点看起来像是OceanBase架构的软肋,然而,经过OceanBase团队
    ; x2 z$ M: G7 z* [8 h+ W持续不断地性能优化以及旁路导入功能的开发,单点的架构在实践过程中经受住了* ~2 [( }% c+ }: S; B3 V
    线上考验。每年淘宝网“双十一”光棍节,OceanBase系统都承载着核心的数据库业: [* d" r( v; G; X! i; p
    务,系统访问量出现5到10倍的增长,而OceanBase只需简单地增加机器即可。$ _& }: K8 p4 E2 H
    当然,UpdateServer单点架构并不是不可突破。虽然目前UpdateServer单点架构
    ( U9 q! L% w9 V4 t还不是瓶颈,但是OceanBase系统设计时已经留好了“后门”,以后可以通过对系统打7 T+ X4 i+ u3 b! G& d1 k1 r7 {
    补丁的方式支持UpdateServer线性扩展。当然,这里可能会做一些牺牲,比如短期内
    4 y; ~' E7 q- M6 Y/ t1 z+ P暂不支持全局事务,只支持针对单个用户的事务操作。
    : \% \; j3 }- B8 F8 e7 Q本节首先回顾OceanBase已经实现的优化工作,包括读写性能优化以及旁路导入
    # q- z: p) O& }9 _+ j功能,接着介绍一种数据分区实现UpdateServer线性扩展的方法。; U7 y/ D9 s' a. g7 `# V
    9.5.1 读写优化回顾
    ; Z6 R. |5 N- q0 QOceanBase UpdateServer相当于一个内存数据库,其架构设计和“世界上最快的内
    + d* D" c, v* }7 f- C$ ^存数据库”MemSQL比较类似,能够支持每秒数百万次单行读写操作,这样的性能对
    # ^% v, a$ N1 Z4 V( ]( E' i0 W于目前关系数据库的应用场景都是足够的。为了达到这样的性能指标,我们已经完
    1 X% G9 t" S2 n2 g, J: R$ P成或正在进行的工作如下。6 S; H  _6 q, W# }9 Y4 [2 n
    1.网络框架优化" |* t5 {. F# ]- J5 s0 T% Z
    9.2.2 节中提到,如果不经过优化,单机每秒最多能够接收的数据包个数只有
      L! A0 x9 }% v* b7 x4 e3 _6 Z; f10万个左右,而经过优化后的libeasy框架对于千兆网卡每秒最多收包个数超过505 X) b1 p5 F+ o" {% W
    万,对于万兆网卡则超过100万。另外,UpdateServer内部还会在软件层面实现多块, k# V+ l0 c7 ~) {& `  h; q# \. T
    网卡的负载均衡,从而更好地发挥多网卡的优势。通过网络框架优化,使得单机支* u  U& L) R# F
    持百万次操作成为可能。: x- @+ Y- c/ c& w
    2.高性能内存数据结构
    " K- b* n. w3 c8 I- `UpdateServer的底层是一颗高性能内存B树。为了最大程度地发挥多核的优势,B
    7 z. ^% A, h; U' b) U6 N( E树实现时大部分情况下都做到了无锁(lock-free)。测试数据表明,即使在普通的16
    % S* ^- w* `7 e) v* b( I核机器上,OceanBase B树每秒支持的单行修改操作都超过150万次。
      D1 o# B& r! ]3.写操作日志优化* u; c7 _8 U8 _  A8 y
    在软件层面,写操作日志涉及的工作主要有如下几点:; ^# M% H# T# g" {
    1)成组提交。将多个写操作聚合在一起,一次性刷入磁盘中。
    . n  _( b/ h7 ]$ P9 y& l2)降低日志缓冲区的锁冲突。多个线程同时往日志缓冲区中追加数据,实现时
    ) e7 l* z, ^+ h2 d! T: W需要尽可能地减少追加过程的锁冲突。追加过程包含两个阶段:第一个阶段是占
    / Q* i8 l; z: s# k( e位,第二个阶段是拷贝数据,相比较而言,拷贝数据比较耗时。实现的关键在于只/ ^, |1 B* o) E7 P1 w9 N
    对占位操作互斥,而允许多线程并发拷贝数据。例如,有两个线程,线程1和线程
    2 P) H* t) N+ o, [' C2,他们分别需要往缓冲区追加大小为100字节和大小为300字节的数据。假设缓冲区) a: H$ S/ ~3 B2 O4 D. H2 ?
    初始为空,那么,线程1可以首先占住位置0~100,线程2接着占住100~300。最
    + n2 j1 @, W# a! P6 b- k后,线程1和线程2并发将数据拷贝到刚才占住的位置。+ m9 ?4 a' [# ^
    3)日志文件并发写入。UpdateServer中每个日志缓冲区的大小一般为2MB,如
    + H" U/ r5 k8 ~. d2 @8 v果写入太快,那么,很快会产生多个日志缓冲区需要刷入磁盘,可以并发地将这些1 S: g& ^' S$ n5 `2 R. m( E( P
    日志缓冲区刷入不同的磁盘。当然,UpdateServer目前并没有实现2和3这两个优化
    : Z3 X# f" ~- g. e& ?点。在硬件层面,UpdateServer机器需要配置较好的RAID卡。这些RAID卡自带缓
    ; A( s  r+ S8 R) _* V) f" L存,而且容量比较大(例如1GB),从而进一步提升写磁盘性能。
    & c6 k, }! W( s: Y; u! z" Z4 n4.内存容量优化( }) a& s: C- E* C
    随着数据不断写入,UpdateServer的内存容量将成为瓶颈。因此,有两种解决思2 S4 m5 w- x( x0 k1 N$ i5 M
    路。一种思路是精心设计UpdateServer的内存数据结构,尽可能地节省内存使用;另
    % W9 T" S' O$ t. M+ n7 d- @5 p外一种思路就是将UpdateServer内存中的数据很快地分发出去。
    / u  h: a  ?; H6 T0 ?OceanBase实现了这两种思路。首先,UpdateServer会将内存中的数据编码为精; Q( N- _: ]/ D( Q7 L! k
    心设计的格式,从9.3.1节中可以看出,100以内的64位整数在内存中只需要占用两个
    " ], Z( M- `& d8 V8 ]+ k, A字节。这种编码格式不仅能够有效地减少内存占用,而且往往使得CPU缓存能够容
    , Z8 l" \9 m- W- _/ m纳更多的数据,从而弥补编码和解码操作造成的性能损失。另外,当UpdateServer的# v1 }! ~0 o# G
    内存使用量到达一定大小时,OceanBase会自动触发数据分发操作,将UpdateServer) k' ^( j  }! T( [2 `- [
    的数据分发到集群中的ChunkServer中,从而避免UpdateServer的内存容量成为瓶颈。2 C2 j/ Z8 K. c' G6 k
    当然,随着单机内存容量变得越来越大,普通的2U服务器已经具备1TB内存的扩展0 m0 G! U# _0 f) o" k
    能力,数据分发也可能只是一种过渡方案。
    ; G9 }0 o6 v4 L+ i' @/ j9.5.2 数据旁路导入, I0 T; N" ^+ k5 L9 Q6 e( t
    虽然OceanBase内部实现了大量优化技术,但是UpdateServer单点写入对于某些
    8 E* j* t: d' H% `% U+ q* Z8 kOLAP应用仍然可能成为问题。这些应用往往需要定期(例如每天,每个月)导入大: T0 ?) t8 e) R9 i6 l" k2 Q* P
    批数据,对导入性能要求很高。为此,OceanBase专门开发了旁路导入功能,本节介9 L* J& O$ `5 P! x4 @- i+ j. a2 |: u
    绍直接将数据导入到ChunkServer中的方法(即ChunkServer旁路导入)。
    . ~& s  d4 b$ K/ \; a8 w, @OceanBase的数据按照全局有序排列,因此,旁路导入的第一步就是使用Hadoop
    ( W  l! r  i& H$ W! x8 J: RMapReduce这样的工具将所有的数据排好序,并且划分为一个个有序的范围,每个范* M) p3 i' B8 z9 T
    围对应一个SSTable文件。接着,再将SSTable文件并行拷贝到集群中所有的
    9 R1 n; R! q  Q; O& iChunkServer中。最后,通知RootServer要求每个ChunkServer并行加载这些SSTable文
    0 r# \: o( P* b) o: o件。每个SSTable文件对应ChunkServer的一个子表,ChunkServer加载完本地的SSTable, u, A2 h: A7 I' B
    文件后会向RootServer汇报,RootServer接着将汇报的子表信息更新到RootTable中。9 C& z) e" E5 f- c8 P# G
    例9-7 有4台ChunkServer:A、B、C和D。所有的数据排好序后划分为6个范
      B; J# ?" e8 p- c1 C+ U围:r1(0~100]、r2(100~200]、r3(200~300]、r4(300~400]、r5(400~" P% w& J0 Y* Y7 m8 \! R
    500]、r6(500~600],对应的SSTable文件分别记为sst1,sst2,……,sst6。假设每
    ; _( n5 U! c" Q* `1 P. x1 D个子表存储两个副本,那么,拷贝完SSTable文件后,可能的分布情况为:
    ; o! T$ H2 S3 K' ^A:sst1,sst3,sst4+ F: V( b/ Q& }* V; s+ {7 n
    B:sst2,sst3,sst5+ ]% g# ^0 w# c. i0 Q  O5 s
    C:sst1,sst4,sst6; C* @! b; O2 w* n# F, I0 o
    D:sst2,sst5,sst6! s" E, J7 V6 I+ b
    接着,每个ChunkServer分别加载本地的SSTable文件,完成后向RootServer汇; c$ e! m- j; X0 E
    报。RootServer最终会将这些信息记录到RootTable中,如下:3 Z% z6 o4 A0 C1 M8 p  e
    r1(0~100]:A、C
    ( F; |& P8 ^% A& o# B* Br2(100~200]:B、D
    # }8 J: P  \3 Jr3(200~300]:A、B  V! ~; e- v3 e
    r4(300~400]:A、C
    / z& k, y6 x8 q' o  M. ir5(400~500]:B、D6 y* H+ e4 I% L- d. a) {
    r6(500~600]:C、D
    - o3 T$ {8 [4 h2 _& ]6 [2 p! ?如果导入的过程中ChunkServer发生故障,例如拷贝sst1到机器C失败,那么,旁, T' F% ?" [# Z! \
    路导入模块会自动选择另外一台机器拷贝数据。" F$ v# r3 T- R: P
    当然,实现旁路导入功能时还需要考虑很多问题。例如,如何支持将数据导入
    , Z2 D6 w4 K. B到多个数据中心的主备OceanBase集群,这里不会涉及这些细节。* n- S9 ]5 f2 o
    9.5.3 数据分区  s! b+ i" O7 w/ D- y6 D" h
    虽然我们坚持认为通过单机性能优化以及硬件性能的提升,UpdateServer单点对- [, c3 S" k9 o1 J1 U& ~( \
    于互联网数据库业务不会成为瓶颈。但是,随着OceanBase的应用场景越来越广,例
    5 D; b) f: \* U1 L) v如,存储原始日志,我们也可能需要实现更新节点可扩展。本节探讨一种可能的做
    6 B; ]7 k4 l5 l  h, C法。% S) x2 o+ e1 o( G/ U8 ]
    OceanBase可以借鉴关系数据库中的分区表的概念,将数据划分为多个分区,允
    " O$ |4 _5 l( O许不同的分区被不同的UpdateServer服务。例如,将所有的数据按照哈希的方式划分
    - N0 W2 L0 @% U" k# U: h为4096个分区,这样,同一个集群中最多允许4096个写节点。
    7 J) b) L) R. O7 _9 Q7 p, S$ o如图9-11所示,可以将Users表格和Albums的user_id列按照相同的规则做哈希,
    . ?" y0 b/ [  F  U  K; ^8 {" Y这样,同一个用户的所有数据属于相同的分区。由于同一个分区只会被同一个: V" `9 Z, `% x4 k
    UpdateServer服务,因此,保证了同一个用户下读写操作的事务性,另外,不同用户
    ' C# j+ X) L; g( S之间的事务可以通过两阶段提交或者最终一致性的方式实现。这种方式实现起来非
    5 |3 f# g; G) R- Y& {/ W常简单,而且能够完全兼容SQL语法。
    2 k6 |- X% L  J# A; ~2 t! W% y. [图 9-11 哈希分区SQL语法% X( i! {8 K2 p( O* A4 G
    从图8-1中的整体架构图可以看出,在目前的单更新节点架构中,UpdateServer进
    / o1 G3 l; K- I, ]程总是与ChunkServer进程部署到不同的服务器,而且两种服务器对硬件的要求不
    : |. Y" Y" R# ]4 m* C/ b$ B同。如果OceanBase支持哈希分区,还能够将UpdateServer进程和ChunkServer进程部
    1 P5 O1 W* a, H' X+ ^3 s6 |署到一起,这样部署起来会更加方便。
    ( C" }8 G7 N: y除了哈希分区,OceanBase还能够通过范围分区实现更新节点可扩展,即不同的
    , b, d9 Y% I* A6 v4 }用户按照user_id有序分布到多台UpdateServer。虽然支持UpdateServer线性可扩展的! I) f6 K$ D' ^
    架构看似“比较优雅”,但是,这件事情并不紧急。这是因为,OLTP类应用对性能的% V# \. r& U& K) Y6 h
    需求是有天花板的(例如全世界人口共50亿,即使其中五分之一的人都在某一天产
    * I* A# }; [' D1 n, r生了一笔交易,这一天的总交易笔数也只有10亿笔),单UpdateServer对于OLTP类数( X9 ]. H! s' |, f  p& j
    据库业务的性能是足够的。
    # _- p( u- r* w; O* g6 S* W* f( c: A- y# g. h. [3 M2 n; ~+ x
    , V4 T2 W) T0 T4 K7 m. |; O% x
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-4-1 14:44 , Processed in 0.117229 second(s), 29 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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