java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2511|回复: 0

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

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

    [LV.Master]出神入化

    2040

    主题

    3698

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66476

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

    发表于 2017-3-6 14:41:55 | 显示全部楼层 |阅读模式
    9.5 消除更新瓶颈
    - q( e$ Q  `  {( h- AUpdateServer单点看起来像是OceanBase架构的软肋,然而,经过OceanBase团队9 ^* h1 `4 a  z. r
    持续不断地性能优化以及旁路导入功能的开发,单点的架构在实践过程中经受住了* ]& J/ \$ ?8 y+ g* e/ f' `3 c
    线上考验。每年淘宝网“双十一”光棍节,OceanBase系统都承载着核心的数据库业- V8 q* ^8 d) s( T
    务,系统访问量出现5到10倍的增长,而OceanBase只需简单地增加机器即可。
    * _1 U, ?. `" o- m0 u当然,UpdateServer单点架构并不是不可突破。虽然目前UpdateServer单点架构
    / N8 z8 @# E6 k$ U  W" {% r% D$ k还不是瓶颈,但是OceanBase系统设计时已经留好了“后门”,以后可以通过对系统打8 I" V6 n- [/ @/ O* M1 E3 T- b  {
    补丁的方式支持UpdateServer线性扩展。当然,这里可能会做一些牺牲,比如短期内
    3 Y" }( H( Z* T+ y暂不支持全局事务,只支持针对单个用户的事务操作。7 J  x, X0 p8 D
    本节首先回顾OceanBase已经实现的优化工作,包括读写性能优化以及旁路导入
    " [1 ]# Q4 R/ ^! \6 v1 B+ H; o$ H功能,接着介绍一种数据分区实现UpdateServer线性扩展的方法。! k  A# j8 ]! P0 Z9 I. W
    9.5.1 读写优化回顾
    / V0 \/ E; @1 g% L! Y- A. D# kOceanBase UpdateServer相当于一个内存数据库,其架构设计和“世界上最快的内; f* r* D& G* f6 b
    存数据库”MemSQL比较类似,能够支持每秒数百万次单行读写操作,这样的性能对# G' q* H- ~: V
    于目前关系数据库的应用场景都是足够的。为了达到这样的性能指标,我们已经完0 d/ T/ P7 Z7 L$ d) b
    成或正在进行的工作如下。+ D7 s. n, R2 K; \
    1.网络框架优化
    9 c0 P. [' f/ m& ?4 ]) j9.2.2 节中提到,如果不经过优化,单机每秒最多能够接收的数据包个数只有
    7 i. a! `/ \; Q10万个左右,而经过优化后的libeasy框架对于千兆网卡每秒最多收包个数超过501 }5 H) g" ?) a1 f
    万,对于万兆网卡则超过100万。另外,UpdateServer内部还会在软件层面实现多块
    8 e, v) K' Y2 p& ]" s网卡的负载均衡,从而更好地发挥多网卡的优势。通过网络框架优化,使得单机支# Y" g4 r; b+ v2 @
    持百万次操作成为可能。
    ! w% U  m% C& \2.高性能内存数据结构$ G; K# ~" i$ [
    UpdateServer的底层是一颗高性能内存B树。为了最大程度地发挥多核的优势,B
    3 l; }- N1 N( d; k树实现时大部分情况下都做到了无锁(lock-free)。测试数据表明,即使在普通的163 ]3 N9 V4 d" J
    核机器上,OceanBase B树每秒支持的单行修改操作都超过150万次。
    " v0 Z. A2 C' g& S+ ]2 _& p3.写操作日志优化/ k1 g. R. R3 g5 q/ S
    在软件层面,写操作日志涉及的工作主要有如下几点:
    9 C8 B; A% [; I* n$ x1)成组提交。将多个写操作聚合在一起,一次性刷入磁盘中。
    " Y/ n* {- ~! r% y8 o% M$ o2)降低日志缓冲区的锁冲突。多个线程同时往日志缓冲区中追加数据,实现时& I7 T2 Z2 Q* `0 B+ S5 J1 T
    需要尽可能地减少追加过程的锁冲突。追加过程包含两个阶段:第一个阶段是占
      y( ^7 j' I0 @2 {5 W+ ^, v' E' _位,第二个阶段是拷贝数据,相比较而言,拷贝数据比较耗时。实现的关键在于只
    1 U5 I7 b: y( J. M3 F; J6 w) B; x对占位操作互斥,而允许多线程并发拷贝数据。例如,有两个线程,线程1和线程
    ' y  H  w* L# I% R' ?. j2,他们分别需要往缓冲区追加大小为100字节和大小为300字节的数据。假设缓冲区
    1 p0 B3 f: B1 p7 G初始为空,那么,线程1可以首先占住位置0~100,线程2接着占住100~300。最+ d2 X- @4 h$ k0 N+ c5 A- p
    后,线程1和线程2并发将数据拷贝到刚才占住的位置。
    % ?$ ~+ h! u4 y- p3)日志文件并发写入。UpdateServer中每个日志缓冲区的大小一般为2MB,如
    4 c5 l' b$ s+ _' Z3 }! ^% K果写入太快,那么,很快会产生多个日志缓冲区需要刷入磁盘,可以并发地将这些
    9 [+ Y+ v; i: P日志缓冲区刷入不同的磁盘。当然,UpdateServer目前并没有实现2和3这两个优化
    $ ?$ E8 |* @. {& ]( Q4 E9 ?% j点。在硬件层面,UpdateServer机器需要配置较好的RAID卡。这些RAID卡自带缓- W/ Y3 }9 b/ X; [8 G. J/ I
    存,而且容量比较大(例如1GB),从而进一步提升写磁盘性能。
    9 F* t: C# G% K7 M# S4 _, R4.内存容量优化# G0 i, o9 a& W; p4 Z; }
    随着数据不断写入,UpdateServer的内存容量将成为瓶颈。因此,有两种解决思1 y$ i! q9 h- Z8 N' s+ Y7 s
    路。一种思路是精心设计UpdateServer的内存数据结构,尽可能地节省内存使用;另4 _5 `  H0 s% @# C( `
    外一种思路就是将UpdateServer内存中的数据很快地分发出去。* {8 z: K" [. K$ E, y* J
    OceanBase实现了这两种思路。首先,UpdateServer会将内存中的数据编码为精
    ) J: M  {# e- ?; l& p4 r心设计的格式,从9.3.1节中可以看出,100以内的64位整数在内存中只需要占用两个
      i2 \  X2 U  j: @* b. w- ]3 Z" J字节。这种编码格式不仅能够有效地减少内存占用,而且往往使得CPU缓存能够容
    ! [+ Y2 s+ B( W$ ]纳更多的数据,从而弥补编码和解码操作造成的性能损失。另外,当UpdateServer的
    2 H* {  P( D+ W; y2 B内存使用量到达一定大小时,OceanBase会自动触发数据分发操作,将UpdateServer
    9 D7 Y3 E$ ^% o3 u/ Y1 d的数据分发到集群中的ChunkServer中,从而避免UpdateServer的内存容量成为瓶颈。
    0 Z' f5 }$ v( V8 G3 W当然,随着单机内存容量变得越来越大,普通的2U服务器已经具备1TB内存的扩展7 I6 M% v8 O9 L6 ]$ G
    能力,数据分发也可能只是一种过渡方案。
    & ?7 s" E9 V0 d' y; y0 {9.5.2 数据旁路导入
    6 @! w, p$ o/ g2 Q虽然OceanBase内部实现了大量优化技术,但是UpdateServer单点写入对于某些
    0 r$ K5 v2 E5 B/ pOLAP应用仍然可能成为问题。这些应用往往需要定期(例如每天,每个月)导入大  I8 _& S! c0 [% m# E8 Y8 J
    批数据,对导入性能要求很高。为此,OceanBase专门开发了旁路导入功能,本节介
    ! D% K  v& |7 n9 U1 ^; `  N绍直接将数据导入到ChunkServer中的方法(即ChunkServer旁路导入)。
    3 [4 }$ u/ U2 n* D, vOceanBase的数据按照全局有序排列,因此,旁路导入的第一步就是使用Hadoop% i/ g1 q- w' N( v% N& e
    MapReduce这样的工具将所有的数据排好序,并且划分为一个个有序的范围,每个范
    ' B# p8 X4 j$ h, R* H围对应一个SSTable文件。接着,再将SSTable文件并行拷贝到集群中所有的
    : H5 z* n$ N% N$ u: J- x- XChunkServer中。最后,通知RootServer要求每个ChunkServer并行加载这些SSTable文
    . D) l: T6 D4 C9 h% r件。每个SSTable文件对应ChunkServer的一个子表,ChunkServer加载完本地的SSTable
    : @( L. b' }. O  X文件后会向RootServer汇报,RootServer接着将汇报的子表信息更新到RootTable中。
    / o1 ?( `" k) F  e" S# c例9-7 有4台ChunkServer:A、B、C和D。所有的数据排好序后划分为6个范3 I; R" G- q6 Q' t- A
    围:r1(0~100]、r2(100~200]、r3(200~300]、r4(300~400]、r5(400~
    $ J3 i& l7 K: ]$ Z" x4 F! T500]、r6(500~600],对应的SSTable文件分别记为sst1,sst2,……,sst6。假设每
    ; l# c4 I: I. _* Q: z$ j个子表存储两个副本,那么,拷贝完SSTable文件后,可能的分布情况为:
    + E) ?) w  n* i  Y; f2 BA:sst1,sst3,sst4
    8 [" d8 N- |# O3 dB:sst2,sst3,sst5
    " z" }" b: E9 p) gC:sst1,sst4,sst6
    5 @0 p* k1 v* C7 LD:sst2,sst5,sst6
    * E; U0 F( e0 g' W9 \2 W. I$ l接着,每个ChunkServer分别加载本地的SSTable文件,完成后向RootServer汇% P* j& ?4 C* X$ J- Z1 O$ j2 [
    报。RootServer最终会将这些信息记录到RootTable中,如下:
    2 M- T. U7 Q0 _( a3 Ar1(0~100]:A、C
    9 A* U/ A& F; Q; y( \6 M8 U5 d4 Nr2(100~200]:B、D. y/ M1 A5 s# \! }4 m2 `0 P
    r3(200~300]:A、B: h$ u' o1 I+ ?6 l
    r4(300~400]:A、C
    4 B  P; V! U9 [' M! q+ `r5(400~500]:B、D1 p- T* f% c1 a& W
    r6(500~600]:C、D  z2 p( G  c: B; B5 v$ G
    如果导入的过程中ChunkServer发生故障,例如拷贝sst1到机器C失败,那么,旁
    * P/ ^: }' X& S; o2 c路导入模块会自动选择另外一台机器拷贝数据。
    2 S- I$ F  G7 l1 V2 |2 b  D当然,实现旁路导入功能时还需要考虑很多问题。例如,如何支持将数据导入
    $ ~, T4 E1 J( z( y) e& z到多个数据中心的主备OceanBase集群,这里不会涉及这些细节。1 x, C# j6 v4 @1 @: S( L
    9.5.3 数据分区5 [, p4 _+ \- p* F. t# h9 c
    虽然我们坚持认为通过单机性能优化以及硬件性能的提升,UpdateServer单点对
    % l5 d% _+ Q6 g: ?( m7 a0 B7 r于互联网数据库业务不会成为瓶颈。但是,随着OceanBase的应用场景越来越广,例) D  [" W$ S" O6 S# _: _
    如,存储原始日志,我们也可能需要实现更新节点可扩展。本节探讨一种可能的做
    8 K# T9 A/ \: R) c3 p+ k1 G# y法。
    # L2 c- `8 h" zOceanBase可以借鉴关系数据库中的分区表的概念,将数据划分为多个分区,允
    # [+ }( q) K: K2 T许不同的分区被不同的UpdateServer服务。例如,将所有的数据按照哈希的方式划分
      r5 n% Q& {; N: X, c; T  r" w# j* M为4096个分区,这样,同一个集群中最多允许4096个写节点。
    7 L: B* C, x) I6 _9 L3 s' o如图9-11所示,可以将Users表格和Albums的user_id列按照相同的规则做哈希,' v5 W- y) |/ D7 Z
    这样,同一个用户的所有数据属于相同的分区。由于同一个分区只会被同一个
    3 M+ W$ o3 s" |3 T' AUpdateServer服务,因此,保证了同一个用户下读写操作的事务性,另外,不同用户
    ' N! ]# N  A- R之间的事务可以通过两阶段提交或者最终一致性的方式实现。这种方式实现起来非1 ~) m6 J. r' U
    常简单,而且能够完全兼容SQL语法。
    5 k. S4 u2 B1 p' I图 9-11 哈希分区SQL语法
    % t# Z# W% T( s& Y( u7 _. W! r从图8-1中的整体架构图可以看出,在目前的单更新节点架构中,UpdateServer进
    3 J7 B# M. A  q. x程总是与ChunkServer进程部署到不同的服务器,而且两种服务器对硬件的要求不$ {( w+ Q' `7 K( S/ N
    同。如果OceanBase支持哈希分区,还能够将UpdateServer进程和ChunkServer进程部
    7 \7 [( x% I% i# i署到一起,这样部署起来会更加方便。
    % P0 I( ?) z  E8 _8 u除了哈希分区,OceanBase还能够通过范围分区实现更新节点可扩展,即不同的
    8 a& ?+ n$ k2 O6 E用户按照user_id有序分布到多台UpdateServer。虽然支持UpdateServer线性可扩展的" m- X4 ~% t  f- h$ _
    架构看似“比较优雅”,但是,这件事情并不紧急。这是因为,OLTP类应用对性能的4 D" `% y2 m! z: b* K" i5 i: Z
    需求是有天花板的(例如全世界人口共50亿,即使其中五分之一的人都在某一天产- w1 V2 A1 z7 R- {. e  I
    生了一笔交易,这一天的总交易笔数也只有10亿笔),单UpdateServer对于OLTP类数
    + }$ P( M2 v1 G" O1 P" N  X2 N据库业务的性能是足够的。5 y+ \& n& X4 n/ v/ Y$ v; S

    ; r6 j) z% l9 Q
    " T3 s- O. J, _' A
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-1-22 14:43 , Processed in 0.438193 second(s), 30 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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