java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2739|回复: 0

《大规模分布式存储系统》第7章 分布式数据库【7.3】

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

    [LV.Master]出神入化

    2096

    主题

    3754

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66788

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

    发表于 2017-3-4 14:06:55 | 显示全部楼层 |阅读模式
    7.3 Google Spanner2 Z6 {* Q' t# L" l. N# w
    Google Spanner是Google的全球级分布式数据库(Globally-Distributed
    $ d/ N6 K% V! j0 `- G. E7 A  ?Database)。Spanner的扩展性达到了全球级,可以扩展到数百个数据中心,数百万5 s5 J. K; S% X0 q5 M/ ]( m. t0 l( J
    台机器,上万亿行记录。更为重要的是,除了夸张的可扩展性之外,它还能通过同8 t; f7 l/ i9 ~7 C
    步复制和多版本控制来满足外部一致性,支持跨数据中心事务。
    3 [, Z+ ]; Z/ a& \% B无论从学术研究还是工程实践的角度看,Spanner都是一个划时代的分布式存储6 A6 G/ U0 b9 G8 l9 r
    系统。Spanner的成功说明了一点,分布式技术能够和数据库技术有机地结合起来,
    1 U  n+ h7 C+ M4 w* X+ z通过分布式技术实现高可扩展性,并呈现给使用者类似关系数据库的数据模型。# s" i0 {9 p& G0 [/ X& B
    7.3.1 数据模型
    0 V0 v5 y7 T" n' e$ d# G* dSpanner的数据模型与6.2节中介绍的Megastore系统比较类似。  S9 M; a* a9 n
    如图7-6所示,对于一个典型的相册应用,需要存储其用户和相册,可以用上面
    # g" D4 }* T6 [的两个SQL语句来创建表。Spanner的表是层次化的,最底层的表是目录表
    8 `4 |& W. l& ^3 W+ u- r# ](Directorytable),其他表创建时,可以用INTERLEAVE IN PARENT来表示层次关
    # E9 w" m% D6 \; N系。Spanner中的目录相当于Megastore中的实体组,一个用户的信息(user_id,email)3 t: ?- O9 _) f$ i8 B& k! c1 p
    以及这个用户下的所有相片信息构成一个目录。实际存储时,Spanner会将同一个目# e  S( S% D! d  G) Z$ I
    录的数据存放到一起,只要目录不太大,同一个目录的每个副本都会分配到同一台. Y3 I7 f+ v5 z/ b- W$ A" Q
    机器。因此,针对同一个目录的读写事务大部分情况下都不会涉及跨机操作。+ A: E0 x" E* S- w+ \+ ]: p$ [
    图 7-6 Spanner数据模型
    / D. l/ M' K) t! m# x% T! M7.3.2 架构) |' d7 C2 |6 F/ @; e% H8 x, H
    Spanner构建在Google下一代分布式文件系统Colossus之上。Colossus是GFS的延  S8 P# y/ @. i) S+ Z' r6 w
    续,相比GFS,Colossus的主要改进点在于实时性,并且支持海量小文件。, B$ w4 l4 z9 W, r/ f, \0 l
    由于Spanner是全球性的,因此它有两个其他分布式存储系统没有的概念:
    1 k& g- E3 c3 C0 r+ h●Universe。一个Spanner部署实例称为一个Universe。目前全世界有3个,一个开
      Z7 n9 s* b. J7 b- |7 U; U发、一个测试、一个线上。Universe支持多数据中心部署,且多个业务可以共享同一
    ! \; ]. m) [: a) s5 P6 E/ a  \个Universe。$ b7 |; I7 n+ U) _& _9 |
    ●Zones。每个Zone属于一个数据中心,而一个数据中心可能有多个Zone。一般
    $ K8 n  M  E+ f( c4 H7 C/ J+ G$ T来说,Zone内部的网络通信代价较低,而Zone与Zone之间通信代价很高。) t4 g% C; L% E' G5 c" W5 t
    如图7-7所示,Spanner系统包含如下组件:
    0 }5 p$ y7 s6 m图 7-7 Spanner整体架构
    1 O& S$ v" X8 M$ q' [2 c4 K●Universe Master:监控这个Universe里Zone级别的状态信息。
    0 V) h1 O8 h5 |0 Q5 A2 u4 F" P●Placement Driver:提供跨Zone数据迁移功能。
    , F- M$ C2 q7 z# v% _6 S$ X●Location Proxy:提供获取数据的位置信息服务。客户端需要通过它才能够知道
    ) O% `0 k3 B$ f2 z+ d3 N, r- t数据由哪台Spanserver服务。
    5 Q3 s+ \& @( V2 p9 d6 F  h●Spanserver:提供存储服务,功能上相当于Bigtable系统中的Tablet Server。
    ! z& j' i' f! I2 a  P! C1 M每个Spanserver会服务多个子表,而每个子表又包含多个目录。客户端往Spanner
    8 y# P1 k" J0 {; w( D9 Z& V5 }- C6 z6 ?发送读写请求时,首先查找目录所在的Spanserver,接着从Spanserver读写数据。
    + k4 u+ j. [. u( }* w+ {1 R+ i- W这里面有一个问题:如何存储目录与Spanserver之间的映射关系?假设每个用户, y3 z$ j, w8 s* X7 q8 ^
    对应一个目录,全球总共有50亿用户,那么,映射关系的数据规模为几十亿到几百$ M% T$ s' ]8 d( V- Z( p- F5 x0 _
    亿,单台服务器无法存放。Spanner论文中没有明确说明,笔者猜测这里的做法和
    7 H# M! C& m$ t3 \: S+ ~, O3 ^. {# cBigtable类似,即将映射关系这样的元数据信息当成元数据表格,和普通用户表格采
    ) W5 p+ W! k: z; L, g5 z5 W取相同的存储方式。3 ^+ k% u7 N! u4 T5 g* w$ V
    7.3.3 复制与一致性
    : d2 a7 {: [; U0 ?% \8 G如图7-8所示,每个数据中心运行着一套Colossus,每个机器有100~1000个子0 Z+ D& M+ u# O$ b+ B2 n
    表,每个子表会在多个数据中心部署多个副本。为了同步系统中的操作日志,每个9 O+ ^  l* {2 k1 H
    子表上会运行一个Paxos状态机。Paxos协议会选出一个副本作为主副本,这个主副本: P0 W2 I- Q( S0 [) a$ h. [) l
    的寿命默认是10秒。正常情况下,这个主副本会在快要到期的时候将自己再次选为
    ! _5 n/ p# z( L& }2 `2 v2 j主副本;如果出现异常,例如主副本所在的spanserver宕机,其他副本会在10秒后通
    6 \# h  Z" u; s过Paxos协议选举为新的主副本。: Q" m; x' R( K# z2 j; z9 K
    图 7-8 Spanner多集群复制
    ; _6 A2 |* e5 l9 I' p通过Paxos协议,实现了跨数据中心的多个副本之间的一致性。另外,每个主副
    5 ?- g, l0 a8 u本所在的Spanserver还会实现一个锁表用于并发控制,读写事务操作某个子表上的目1 m; N! F% U! f/ t5 f
    录时需要通过锁表避免多个事务之间互相干扰。  d+ Q2 C$ L( g5 L' g5 {' M
    除了锁表,每个主副本上还有一个事务管理器。如果事务在一个Paxos组里面,4 S/ y" p2 R0 O$ {& g
    可以绕过事务管理器。但是一旦事务跨多个Paxos组,就需要事务管理器来协调。
    4 Y! t0 j9 Q1 o锁表实现单个Paxos组内的单机事务,事务管理器实现跨多个Paxos组的分布式事9 L- j) W" C" N6 Y. Q- M
    务。为了实现分布式事务,需要实现3.7.1节中提到的两阶段提交协议。有一个Paxos
    / P0 z5 a* Y% F) K: ?组的主副本会成为两阶段提交协议中的协调者,其他Paxos组的主副本为参与者。  W/ T- F$ G  J( W9 v1 s
    7.3.4 TrueTime: P0 P- Z/ L, P% P" G/ h% i
    为了实现并发控制,数据库需要给每个事务分配全局唯一的事务id。然而,在分) Y- D! M0 d$ \1 N5 K" W! l: h$ z- [
    布式系统中,很难生成全局唯一id。一种方式是采用Google Percolator(Google
    # }: g# g* u0 bCaffeine的底层存储系统)中的做法,即专门部署一套Oracle数据库用于生成全局唯( Z9 a* N# c. e) \
    一id。虽然Oracle逻辑上是一个单点,但是实现的功能单一,因而能够做得很高效。- g& \! \& \3 |9 D) B
    Spanner选择了另外一种做法,即全球时钟同步机制TrueTime。
    2 r$ ]: N" @! d6 ^3 v& A0 ?TrueTime是一个提供本地时间的接口,但与Linux上的gettimeofday接口不一样的
    & V8 t) r: r2 w5 y8 M( g是,它除了可以返回一个时间戳t,还会给出一个误差e。例如,返回的时间戳是20点2 d: K9 \# e% Q- N- z! j/ |3 \
    23分30秒100毫秒,而误差是5毫秒,那么真实的时间在20点23分30秒95毫秒到105毫, j* F" Q$ x+ P" r4 Y( \8 M
    秒之间。真实的系统e平均下来只有4毫秒。
    ( E* R* t- X+ a( P; cTrueTime API实现的基础是GPS和原子钟。之所以要用两种技术来处理,是因为# `  a4 u: ~5 Z0 y) u
    导致这两种技术失效的原因是不同的。GPS会有一个天线,电波干扰会导致其失灵。- h4 M' w, \, ~# ?4 Y- q5 v
    原子钟很稳定。当GPS失灵的时候,原子钟仍然能保证在相当长的时间内,不会出现& M' U" \/ u% ^4 a; A
    偏差。
    ( H/ S" u) @; L( k- L每个数据中心需要部署一些主时钟服务器(Master),其他机器上部署一个从时8 Q9 D6 l- r3 @# z' {
    钟进程(Slave)来从主时钟服务器同步时钟信息。有的主时钟服务器用GPS,有的2 ^. \, h% }6 k1 u
    主时钟服务器用原子钟。每个从时钟进程每隔30秒会从若干个主时钟服务器同步时$ L! r7 V6 w" ], F% V
    钟信息。主时钟服务器自己还会将最新的时间信息和本地时钟比对,排除掉偏差比
    - ]$ _+ \& \: X0 c4 \较大的结果。
    : p/ I% c5 g9 p$ j/ X  j5 G7.3.5 并发控制. o+ C9 ?  |2 y6 V) F$ z  J, H
    Spanner使用TrueTime来控制并发,实现外部一致性,支持以下几种事务:3 A/ j. E- E+ ?6 c  b  g
    ●读写事务
    * @- k  p7 ?' D' B●只读事务# w3 _4 R5 c- _! s
    ●快照读,客户端提供时间戳: O/ {1 Z) o2 G
    ●快照读,客户端提供时间范围
    7 U4 k" ], }) ~7 h8 d1.不考虑TrueTime
    # u8 h/ K! V& Q# E* D# b; ^首先,不考虑TrueTime的影响,也就是说,假设TrueTime API获得的时间是精确
    , O3 H4 Q0 i; \' d4 y的。如果事务读写的数据只属于同一个Paxos组,那么,每个读写事务的执行步骤如7 N9 N% v$ k1 h4 r) h3 F
    下:3 x9 |/ E% `' A  |1 s
    1)获取系统的当前时间戳;, F1 L" L3 U, z6 o- I2 _( T/ P
    2)执行读写操作,并将第1步取得的时间戳作为事务的提交版本。/ T. S; ]; r% m7 a3 E
    每个只读事务的执行步骤如下:  j, h4 G0 B: J
    1)获取系统的当前时间戳,作为读事务的版本;1 g+ Y' y( q0 c% {' U: [
    2)执行读取操作,返回客户端所有提交版本小于读事务版本的事务操作结果。, l/ y5 ~2 ?- V& n+ t/ ^8 e& m2 ]
    快照读和只读事务的区别在于:快照读将指定读事务的版本,而不是取系统的
    % R" f+ ?* ~" R& S当前时间戳。
    8 t3 p" K# s$ p/ V5 o如果事务读写的数据涉及多个Paxos组,那么,对于读写事务,需要执行一次两: D7 ?8 _9 Q7 j+ u
    阶段提交协议,执行步骤如下:( W6 w2 V# j# R7 e& C* C, r
    1)Prepare:客户端将数据发往多个Paxos组的主副本,同时,协调者主副本发
    + V  [* T4 v) k  D  ]起prepare协议,请求其他的参与者主副本锁住需要操作的数据。9 \. m7 Z1 p6 K$ m4 L+ o5 g
    2)Commit:协调者主副本发起Commit协议,要求每个参与者主副本执行提交操' m8 s8 X% E* e+ U# A$ J
    作并解除Prepare阶段锁定的数据。协调者主副本可以将它的当前时间戳作为该事务
    & u5 H4 k( K8 s' `2 J2 K9 g的提交版本,并发送给每个参与者主副本。4 Y7 u/ k6 o8 K
    只读事务读取每个Paxos组中提交版本小于读事务版本的事务操作结果。需要注2 |4 a' z* {  ]. A7 ^
    意的是,只读事务需要保证不会读到不完整的事务。假设有一个读写事务修改了两- U8 F; P7 [3 F( L6 O
    个Paxos组:Paxos组A和Paxos组B,Paxos组A上的修改已提交,Paxos组B上的修改还未
    ; T& [- q& P( E$ l3 P* s# ^提交。那么,只读事务会发现Paxos组B处于两阶段提交协议中的Prepare阶段,需要
    # H. c3 U& f2 Z2 W等待一会,直到Paxos组B上的修改生效后才能读到正确的数据。
    9 j' N1 U3 q) G, e. N9 O  D# J2.考虑TrueTime
    , Z  k$ q5 x' C3 U& q8 X. D! h, J如果考虑TrueTime,并发控制变得复杂。这里的核心思想在于,只要事务T1的
    " Y0 W+ v# |- b提交操作早于事务T2的开始操作,即使考虑TrueTime API的误差因素(-e到+e之间,* }. d$ J% ~1 v( x/ a; p0 C
    e值平均为4ms),Spanner也能保证事务T1的提交版本小于事务T2的提交版本。
    5 M# w- j! n& w2 u+ G1 \6 f2 \! T; pSpanner使用了一种称为延迟提交(Commit Wait)的手段,即如果事务T1的提交版本
    5 D! f6 T! t- l1 e/ a% u为时间戳t commit ,那么,事务T1会在t commit +e之后才能提交。另外,如果事务T2开始
    & `& H6 i6 _5 a2 |) ~# j( `& d的绝对时间为t abs ,那么事务T2的提交版本至少为t abs +e。这样,就保证了事务T1和T24 p  L4 R" T2 C0 `4 M
    之间严格的顺序,当然,这也意味着每个写事务的延时至少为2e。从这一点也可以5 _6 c( ], v# l& z2 I  @$ P
    看出,Spanner实现功能完备的全球数据库是付出了一定代价的,设计架构时不能盲
    9 j. U: d" b8 A% O% d目崇拜。
    * D$ {! {  N; m7.3.6 数据迁移* Q0 Z. m5 u/ R% ]" `
    目录是Spanner中对数据分区、复制和迁移的基本单位,用户可以指定一个目录
    / K/ w( U$ `& k2 h8 c0 }7 o4 r有多少个副本,分别存放在哪些机房中,例如将用户的目录存放在这个用户所在地5 X( ]- [7 Y. t) U: r' k0 L. r9 x
    区附近的几个机房中。! d7 }. [4 |- j3 F6 \* H5 ?
    一个Paxos组包含多个目录,目录可以在Paxos组之间移动。Spanner移动一个目
    2 b! k$ Z8 e8 Y0 l- n7 _/ {7 i录一般出于以下几种考虑:
    7 w8 M7 Y  ~, e; \7 `5 O●某个Paxos组的负载太大,需要切分;0 j, M  F1 _; s/ I
    ●将数据移动到离用户更近的地方,减少访问延时;
    5 g! [+ u% h3 u( D●把经常一起访问的目录放进同一个Paxos组。
    $ W/ N/ }0 U* v8 @1 d7 S移动目录的操作在后台进行,不影响前台的客户端读写操作。一般来说,移动. T: q/ r# V) y$ a3 q  M- e
    一个50MB的目录大约只需要几秒钟时间。实现时,首先将目录的实际数据移动到指1 m) K, h' Q( a2 p5 |% v) @
    定位置,然后再用一个原子操作更新元数据,从而完成整个移动过程。
    ! t! {( k. g& q7.3.7 讨论$ S9 F3 ?% @% r8 p( J  r$ u% t
    Google的分布式存储系统一步步地从Bigtable到Megastore,再到Spanner,这也印
    * |% g: _+ I$ m5 H0 J证了分布式技术和传统关系数据库技术融合的必然性,即底层通过分布式技术实现8 M) R# ^) l" n
    可扩展性,上层通过关系数据库的模型和接口将系统的功能暴露给用户。
    4 M$ B. v4 g# y5 E) a' Z  {  l阿里巴巴的OceanBase系统在设计之初就考虑到这两种技术融合的必然性,因
    2 {$ y, ?4 ~) F( }$ z4 D+ M- |此,一开始就将系统的最终目标定为:可扩展的关系数据库。目前,OceanBase已经% M0 n% n7 d$ Q) d4 I8 ~+ {' f
    开发完成了部分功能并在阿里巴巴各个子公司获得广泛的应用。本书第三篇将详细' R; l- C9 a! S9 Q
    介绍OceanBase的技术细节。
    : e5 U: r  Z# Q' B- P6 T; i1 D/ {) g3 j; X- D" n/ s
    3 Z" ^9 Q7 ~$ k# p- H
    回复

    使用道具 举报

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

    本版积分规则

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

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

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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