java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2479|回复: 0

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

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

    [LV.Master]出神入化

    2025

    主题

    3683

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66375

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

    发表于 2017-3-6 14:41:55 | 显示全部楼层 |阅读模式
    9.5 消除更新瓶颈% N5 Y0 N3 @6 \
    UpdateServer单点看起来像是OceanBase架构的软肋,然而,经过OceanBase团队
    ; ~6 t0 E1 V. _* [持续不断地性能优化以及旁路导入功能的开发,单点的架构在实践过程中经受住了) P9 }' e# X( H, r
    线上考验。每年淘宝网“双十一”光棍节,OceanBase系统都承载着核心的数据库业
    7 ?+ S. P; x1 _1 P务,系统访问量出现5到10倍的增长,而OceanBase只需简单地增加机器即可。
      s7 {7 S  A: k. F7 ^当然,UpdateServer单点架构并不是不可突破。虽然目前UpdateServer单点架构* j9 g1 i# B' X4 j( [0 s& p0 I: i
    还不是瓶颈,但是OceanBase系统设计时已经留好了“后门”,以后可以通过对系统打5 Z$ H$ B6 M' M1 z: p( n2 C
    补丁的方式支持UpdateServer线性扩展。当然,这里可能会做一些牺牲,比如短期内% M& ?* m( d0 J3 p! p* ^
    暂不支持全局事务,只支持针对单个用户的事务操作。
    & B& P$ a" D7 M6 M本节首先回顾OceanBase已经实现的优化工作,包括读写性能优化以及旁路导入6 u3 p' @5 b7 s, N, _( {$ A
    功能,接着介绍一种数据分区实现UpdateServer线性扩展的方法。2 C) @% a+ W0 ~, Z" C
    9.5.1 读写优化回顾+ ?+ J# D2 H, e% P: R6 q
    OceanBase UpdateServer相当于一个内存数据库,其架构设计和“世界上最快的内9 s1 ^0 w8 f$ {6 ~/ N. e3 P. Z7 P9 p
    存数据库”MemSQL比较类似,能够支持每秒数百万次单行读写操作,这样的性能对6 v8 _" O  ^2 z- c, z% e- v
    于目前关系数据库的应用场景都是足够的。为了达到这样的性能指标,我们已经完2 v3 X% I2 W, ?0 E* u
    成或正在进行的工作如下。/ f8 h. Q0 r# A5 d0 k9 e
    1.网络框架优化
    9 |- R1 _! O( l; w" j0 u4 m" d9.2.2 节中提到,如果不经过优化,单机每秒最多能够接收的数据包个数只有
    ! L0 n+ I1 o5 s+ K10万个左右,而经过优化后的libeasy框架对于千兆网卡每秒最多收包个数超过50
    % Y, r0 x+ h! F& t+ I; K: W万,对于万兆网卡则超过100万。另外,UpdateServer内部还会在软件层面实现多块
    2 F+ t* j' d' K网卡的负载均衡,从而更好地发挥多网卡的优势。通过网络框架优化,使得单机支4 @: T, S0 j" P7 j8 ]1 n$ t
    持百万次操作成为可能。
    2 t6 T+ O) ]/ A: E. d, M+ x2.高性能内存数据结构
    2 `* \! v3 `8 a, nUpdateServer的底层是一颗高性能内存B树。为了最大程度地发挥多核的优势,B' d6 q. P0 o* x* |5 T
    树实现时大部分情况下都做到了无锁(lock-free)。测试数据表明,即使在普通的16
    7 E9 M! l) Z" |/ x" ]( k7 I% \核机器上,OceanBase B树每秒支持的单行修改操作都超过150万次。+ X( `/ h2 n% x+ z
    3.写操作日志优化& F- y4 A/ t2 }
    在软件层面,写操作日志涉及的工作主要有如下几点:
    . x% B" p+ A5 U1)成组提交。将多个写操作聚合在一起,一次性刷入磁盘中。) `: e) T5 I6 V) u( b! d, c
    2)降低日志缓冲区的锁冲突。多个线程同时往日志缓冲区中追加数据,实现时
    ; S& U- X, @  Z! u需要尽可能地减少追加过程的锁冲突。追加过程包含两个阶段:第一个阶段是占
    / t: R1 D5 n: O1 Q/ q位,第二个阶段是拷贝数据,相比较而言,拷贝数据比较耗时。实现的关键在于只; t! g* y1 `- g0 L
    对占位操作互斥,而允许多线程并发拷贝数据。例如,有两个线程,线程1和线程& v: q' o" ?$ |- U
    2,他们分别需要往缓冲区追加大小为100字节和大小为300字节的数据。假设缓冲区
    3 C9 B9 H/ U: F. o, d初始为空,那么,线程1可以首先占住位置0~100,线程2接着占住100~300。最
    8 j, W& ^( d. |; D8 v后,线程1和线程2并发将数据拷贝到刚才占住的位置。
    * ]) J9 t. U) n6 ^5 N3)日志文件并发写入。UpdateServer中每个日志缓冲区的大小一般为2MB,如( k, X5 d4 s, S& }( N, u
    果写入太快,那么,很快会产生多个日志缓冲区需要刷入磁盘,可以并发地将这些$ L. ~7 U3 k/ B3 ?3 C# ?# c9 r
    日志缓冲区刷入不同的磁盘。当然,UpdateServer目前并没有实现2和3这两个优化% _% E/ B8 {- P$ O
    点。在硬件层面,UpdateServer机器需要配置较好的RAID卡。这些RAID卡自带缓
    - ~: j1 j1 U5 w. S; X- R" j存,而且容量比较大(例如1GB),从而进一步提升写磁盘性能。9 d4 q: W0 j2 h
    4.内存容量优化
    9 n& Z& F8 X- T" {4 u* ?) r3 C随着数据不断写入,UpdateServer的内存容量将成为瓶颈。因此,有两种解决思
    0 h2 m. B/ n1 L" @, D路。一种思路是精心设计UpdateServer的内存数据结构,尽可能地节省内存使用;另% M  ^, X$ k- Y- w4 ?" y) o
    外一种思路就是将UpdateServer内存中的数据很快地分发出去。% R% Y0 q$ [+ m
    OceanBase实现了这两种思路。首先,UpdateServer会将内存中的数据编码为精7 N- E. y2 j8 Y# u6 I7 z. ^
    心设计的格式,从9.3.1节中可以看出,100以内的64位整数在内存中只需要占用两个
    5 I$ }" d6 q! _  H6 p" x" j! r字节。这种编码格式不仅能够有效地减少内存占用,而且往往使得CPU缓存能够容
    " q- P6 Q4 |' [. A/ k" x. ?纳更多的数据,从而弥补编码和解码操作造成的性能损失。另外,当UpdateServer的' Q' A# J$ z, Z& t; D  _; I% k9 {! B
    内存使用量到达一定大小时,OceanBase会自动触发数据分发操作,将UpdateServer
    8 O! t! s8 N! `! h) ^的数据分发到集群中的ChunkServer中,从而避免UpdateServer的内存容量成为瓶颈。
    3 A+ i  C: K5 _当然,随着单机内存容量变得越来越大,普通的2U服务器已经具备1TB内存的扩展* Y; f; d8 N' ]# C% L
    能力,数据分发也可能只是一种过渡方案。
    ; E$ X) R) a: E* f3 N) L' T9.5.2 数据旁路导入- f. z+ v' C! C; K4 c# X$ {
    虽然OceanBase内部实现了大量优化技术,但是UpdateServer单点写入对于某些
    / X# y( F7 r5 ~7 J% J$ POLAP应用仍然可能成为问题。这些应用往往需要定期(例如每天,每个月)导入大
    0 L. n1 z8 ^  W* X% e- N批数据,对导入性能要求很高。为此,OceanBase专门开发了旁路导入功能,本节介
    ' k' N+ D) k1 O% Y绍直接将数据导入到ChunkServer中的方法(即ChunkServer旁路导入)。
    ( b* L7 o% b/ |OceanBase的数据按照全局有序排列,因此,旁路导入的第一步就是使用Hadoop9 G% g) t; P! o" m+ ~  z* |
    MapReduce这样的工具将所有的数据排好序,并且划分为一个个有序的范围,每个范
    7 f' e5 c3 t, i1 z- I+ S围对应一个SSTable文件。接着,再将SSTable文件并行拷贝到集群中所有的- L* H6 P1 r& x7 Y
    ChunkServer中。最后,通知RootServer要求每个ChunkServer并行加载这些SSTable文
    - H0 O# }% S9 y# i5 X件。每个SSTable文件对应ChunkServer的一个子表,ChunkServer加载完本地的SSTable& y) f/ `) }# v* I
    文件后会向RootServer汇报,RootServer接着将汇报的子表信息更新到RootTable中。$ g3 d3 e3 ^, I" X
    例9-7 有4台ChunkServer:A、B、C和D。所有的数据排好序后划分为6个范
    9 y, d) l! P. U- b7 m围:r1(0~100]、r2(100~200]、r3(200~300]、r4(300~400]、r5(400~; g1 {0 T+ L$ H1 z
    500]、r6(500~600],对应的SSTable文件分别记为sst1,sst2,……,sst6。假设每
    ! [* s9 J" v% x! t4 J9 h个子表存储两个副本,那么,拷贝完SSTable文件后,可能的分布情况为:
    1 C' r. ?, H0 P, l9 M* `" h" FA:sst1,sst3,sst4
    4 Y! U6 `& K! r" \$ YB:sst2,sst3,sst55 ~" ]  X; T$ @3 K) D
    C:sst1,sst4,sst6! R+ A2 l; @" u8 ?8 j9 V9 [, n
    D:sst2,sst5,sst6$ e# z0 {3 N/ F8 d# q  N
    接着,每个ChunkServer分别加载本地的SSTable文件,完成后向RootServer汇
    & E; @- C( n  `: q+ L" y! b1 \; J报。RootServer最终会将这些信息记录到RootTable中,如下:* \1 i7 E5 m1 _: o" J
    r1(0~100]:A、C) U  W$ J& o0 k9 \/ [7 R- Y
    r2(100~200]:B、D+ v4 S0 `6 L$ [, L; s
    r3(200~300]:A、B- n' b; F  e3 J& _$ r5 V9 i- `9 I
    r4(300~400]:A、C
    2 K' H* x0 Y# vr5(400~500]:B、D
    1 G2 b5 c$ ~* F/ Q* ]/ B$ M5 Hr6(500~600]:C、D( f, d0 C; d# P2 H$ B. \* u
    如果导入的过程中ChunkServer发生故障,例如拷贝sst1到机器C失败,那么,旁( b! C6 t5 ^7 t! W
    路导入模块会自动选择另外一台机器拷贝数据。* y8 }! `( x5 q* Q0 L; [+ p/ V
    当然,实现旁路导入功能时还需要考虑很多问题。例如,如何支持将数据导入4 n) {$ H; `; Q+ Y& m
    到多个数据中心的主备OceanBase集群,这里不会涉及这些细节。
    ( z/ S6 U; v0 e) P* M, j6 }9.5.3 数据分区
    : j; ]: i3 M+ J' i8 e虽然我们坚持认为通过单机性能优化以及硬件性能的提升,UpdateServer单点对
    ! L  Y1 [/ ~4 v- q. }- S5 N9 u7 N于互联网数据库业务不会成为瓶颈。但是,随着OceanBase的应用场景越来越广,例
    2 k" X! }8 o4 H如,存储原始日志,我们也可能需要实现更新节点可扩展。本节探讨一种可能的做
    5 K# Y+ K8 F( _. q9 [法。! z5 B9 l8 }2 G2 _4 o8 d
    OceanBase可以借鉴关系数据库中的分区表的概念,将数据划分为多个分区,允
      W5 d" W4 N8 g5 t- t* y许不同的分区被不同的UpdateServer服务。例如,将所有的数据按照哈希的方式划分
    ' i2 ~7 n7 y6 E$ Z  O- I( _/ d为4096个分区,这样,同一个集群中最多允许4096个写节点。
    ) X6 s4 m2 T' }& o, ~# P' L( L如图9-11所示,可以将Users表格和Albums的user_id列按照相同的规则做哈希,! q$ w) m* K; Y- R; ]
    这样,同一个用户的所有数据属于相同的分区。由于同一个分区只会被同一个
    0 l$ B& A1 y# \) I! e  fUpdateServer服务,因此,保证了同一个用户下读写操作的事务性,另外,不同用户
    & T5 ?! d' F) i之间的事务可以通过两阶段提交或者最终一致性的方式实现。这种方式实现起来非
    & z" T9 f# C9 a7 B常简单,而且能够完全兼容SQL语法。
    3 j3 X+ R. q. M+ G# V( y0 C图 9-11 哈希分区SQL语法$ H& }( r* X# H0 y
    从图8-1中的整体架构图可以看出,在目前的单更新节点架构中,UpdateServer进
    ; @* h/ {9 P# M程总是与ChunkServer进程部署到不同的服务器,而且两种服务器对硬件的要求不* S0 v5 K3 L5 F- A" c  `
    同。如果OceanBase支持哈希分区,还能够将UpdateServer进程和ChunkServer进程部
    0 E" Y  G' h& ~0 S署到一起,这样部署起来会更加方便。
    " g: S6 v. {  S& h& h& g+ t除了哈希分区,OceanBase还能够通过范围分区实现更新节点可扩展,即不同的
    4 v+ F2 a/ u* o- g; p* _用户按照user_id有序分布到多台UpdateServer。虽然支持UpdateServer线性可扩展的0 ]7 W! V3 v3 [6 P6 E
    架构看似“比较优雅”,但是,这件事情并不紧急。这是因为,OLTP类应用对性能的
    . ~% M$ a9 c# R$ }2 J! G9 Y! g需求是有天花板的(例如全世界人口共50亿,即使其中五分之一的人都在某一天产/ Z' u, h/ b6 _* t
    生了一笔交易,这一天的总交易笔数也只有10亿笔),单UpdateServer对于OLTP类数
    9 X; L3 d# B- ~& i2 m2 r$ }1 ~据库业务的性能是足够的。: X: |* J8 x5 [$ {3 b  C# }, {
    " h9 E8 v# P$ g/ w$ |; O

    # h# f. v2 I6 U* D% g  u
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-12-22 14:01 , Processed in 0.147454 second(s), 30 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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