文章目录

  • Introduction
  • Implementation
    • Spanserver Software Stack
    • Directories and Placement
    • Data Model
  • TrueTime
  • Concurrency Control
    • Timestamp Management
      • Paxos Leader Leases
      • Assigning Timestamps to RW Transactions
      • Serving Reads at a Timestamp
      • Assigning Timestamps to RO Transactions
    • Details
      • Read-Write Transactions
      • Read-Only Transactions
      • Refinements

Introduction

Spanner是Google的全球分布式数据库,它主要具有以下特点:

  • 可细粒度动态控制数据副本的配置,包括数据的分片方式,数据的迁移等。
  • 读和写操作的外部一致性
  • 一个时间戳下跨数据库的全球一致性读

Spanner能提供全球范围内的有序事务提交时间戳,而这个功能基于TrueTime API及其实现。

Implementation


一个Spanner的部署被称为一个universe,其包含如下部分:

  • universe master:管理和控制zone的状态和信息
  • placement driver:周期性和spanservers交互,发现需要转移、更新的数据。
  • 多个zone,每个zone代表了一个数据存储单元,其包含:
    • zonemaster:管理当前zone的spanservers(如分配数据)
    • spanserver:存储和提供数据
    • local proxy:给客户端定位提供数据的spanservers

Spanserver Software Stack


Spanserver的软件协议栈各部件功能如下:

  • tablet:spanserver中的数据结构,是一个具有版本的key-value条目,其形式为(key:string, timestamp:int64) -> string。tablet的状态存储在Colossus分布式文件系统当中,并且存储于类似B+树的文件和WAL中。
  • Paxos group:每个tablet运行在Paxos协议下,代表一份数据副本,Paxos协议的状态(如log等)也存储在tablet中。多个replica组成一个Paxos group,并有一个leader进行管理。
    • leader的选举租约为10s。
    • 写操作必须经过leader,并由Paxos保证半数复制,读操作可以直接访问最新的副本。
    • leader维护lock table,用于存储如2PL的锁状态。
    • leader拥有transaction manager,用于维护事务状态和事务并发控制。
  • participant leader:基于transaction manager创建,用于协调跨Paxos group的事务,以完成2PC事务提交。

Directories and Placement


Spanner中定义了directory的概念,它是数据放置的最小单位

  • 每个Paxos group可拆成多个目录,每个目录由一系列共同前缀的键所对应的数据项组成(实际为将tablet进行划分)。
  • directory中的所有数据都具有相同的replication configuration。
  • 目录的replica在其所在的Paxos group中。
  • 目录可以转移到不同的Paxos group,以调整负载,转移操作可以在执行client operations时进行(50MB转移只需要几秒)。
  • Movedir background task用于在Paxos groups间转移目录。
  • 若一个目录过大,会被分片到不同的Paxos group,Movedir实际上移动的时分片而不是目录。

Data Model

Spanner的对外数据特征为:

  • schematized semi-relational tables:每个表的行都必须有名称,可定义外键和级联的关系。
  • a query language:一个查询语言(类SQL)。
  • general purpose transactions:通用的事务(基于2PC+2PL)

Spanner中的Data Model实例如下所示,其结构如下:

  • database由client分割成多个不同层级的hierarchy table(INTERLEAVE IN关键字)
  • 每个hierarchy table的top row为directory table,并包含key K。

TrueTime


TrueTime的实现机制:

  • 底层为GPS + atomic clock。 GPS可能会因为天线等故障出现误差,atomic clock可能会因为长时间使用导致的频率误差产生时钟漂移。
  • 每个datacenter中配置有多个time master
    • 一些使用GPS获取时间,一些使用atomic clock获取时间
    • time master之间互相校对时间,若差距过大则会将自己驱逐出去
  • 每个server中都有一个timeslave daemon
    • 每个server收集time master的时间,使用类Marzullo算法同步本地server时钟。
    • 考虑到延迟等影响,引入了时间误差ϵ\epsilonϵ

Concurrency Control

基于TrueTime API实现了一个重要特性:在timestamp t时产生的读操作,会看到所有在t之前提交的事务。

Timestamp Management

Spanner支持以下几种读写事务:

  • Read-Write:使用pessimistic lock进行并发控制。
  • Read-Only
    • 必须声明不含写操作
    • 时间戳由leader决定,无锁,可在任何足够新的副本执行
  • Snapshot Read
    • 可读取历史数据,无锁
    • 时间由客户端决定,可以是时间戳,也可以是时间下限(由Spanner具体决定,满足条件即可)

Paxos Leader Leases

Paxos的leader租约具有以下特点:

  • leader lease的默认时间为10s

    • 成功执行一次写操作会延展leader lease
    • leader lease快到期前会申请延长
  • leader可主动放弃该身份
  • 不同leader的lease interval不同
  • 假设前一个leader使用过的最大时间戳为smaxs_{max}smax​,则下一个leader的租约起始时间必须满足TT.after(smax)TT.after(s_{max})TT.after(smax​)。

Assigning Timestamps to RW Transactions

读写事务需要依赖2PL。Spanner是用在提交事务时的Paxos写操作的时间戳作为事务时间戳。

Spanner提供了读写事务时间戳的两个保证,Paxos group内单调递增和外部一致性。

Paxos group内读写事务timestamp单调递增由以下机制保证:

  • leader不同租约区间互不相交
  • leader分配的时间戳只能在自己租约区间内

WR事务的外部一致性保证为:如果事务T2T_2T2​发生在事务T1T_1T1​提交之后,则事务T2T_2T2​的提交时间戳一定大于事务T1T_1T1​的提交时间戳,即tabs(e1commit)<tabs(e2commit)⇒s1<s2t_{abs}(e_1^{commit}) < t_{abs}(e_2^{commit}) \Rightarrow s_1 < s_2tabs​(e1commit​)<tabs​(e2commit​)⇒s1​<s2​。

其中一些记号标识说明如下:

  • eistarte_i^{start}eistart​:事务TiT_iTi​开始事件。
  • eicommite_i^{commit}eicommit​:事务TiT_iTi​提交事件。
  • sis_isi​:事务TiT_iTi​的commit timestamp。
  • siservers_i^{server}siserver​:coordinate leader收到commit request事件。

WR事务的外部一致性通过以下机制保证:

  • Start:siserver≤sis_i^{server} \leq s_isiserver​≤si​。
  • Commit Wait:si<tabs(eicommit)s_i < t_{abs}(e_i^{commit})si​<tabs​(eicommit​)

证明如下:

Serving Reads at a Timestamp

每个replica都会维护一个tsafet_{safe}tsafe​,表示副本最近更新的最大时间戳,当读事务的时间戳为ttt时,可以在满足t≤tsafet \leq t_{safe}t≤tsafe​的副本上读取且tsafe=min(tsafePaxos,tsafeTM)t_{safe}=min(t_{safe}^{Paxos},t_{safe}^{TM})tsafe​=min(tsafePaxos​,tsafeTM​)。

tsafePaxost_{safe}^{Paxos}tsafePaxos​为Paxos write的最近事件,tsafeTMt_{safe}^{TM}tsafeTM​为副本对应的transaction manager维护的安全时间,其具体取值如下:

  • 若当前Paxos group没有已经prepare但没commit的事务(即没夹在2PC中间阶段的事务),则tsafeTM=∞t_{safe}^{TM}= \inftytsafeTM​=∞。
  • 若Paxos group中存在多个这种事务,则tsafeTM=mini(si,gprepare)−1t_{safe}^{TM}=min_i(s_{i,g}^{prepare})-1tsafeTM​=mini​(si,gprepare​)−1,其中si,gprepares_{i,g}^{prepare}si,gprepare​为Paxos group leader为事务TiT_iTi​回复prepare消息的timestamp。

Assigning Timestamps to RO Transactions

只读事务分为两个阶段进行:

  • 由Paxos group leader分配一个timestamp sreads_{read}sread​。

    • sreads_{read}sread​的通常选择为TT.now().latestTT.now().latestTT.now().latest
    • 若tsafet_{safe}tsafe​不够大,可能需要阻塞,因此sreads_{read}sread​可能为一个满足外部一致性的最小时间戳
    • sreads_{read}sread​也会增大smaxs_{max}smax​,保证不同leader lease不相交。
  • 进行sreads_{read}sread​的快照读,可在任何足够新的副本上读

Details

Read-Write Transactions

Spanner在执行读写事务时:

  • 写入数据先缓存于client,直到提交,因此读操作不会受写操作影响
  • 读取时使用wound-wait机制避免死锁
  • 获取读锁然后读取up-to-date数据
  • 事务活跃时client向participant leader发送心跳包
  • 当client完成所有读操作和缓存所有写操作后,开始变种的2PC

Spanner中变种的2PC协议具体如下:

  • client完成了所有读操作并缓存需要写入内容后,开始进行2PC
  • client会选择一个coordinator group并向所有的participant leader发送写请求(包括coordinator leader),并捎带prepare请求
  • participant leader:
    • 先获取写锁
    • 给回复prepare这个事件赋上时间戳siprepares_i^{prepare}siprepare​(此时更新了tsafeTMt_{safe}^{TM}tsafeTM​)
    • 使用Paxos持久化该事件,写入log(此时更新tsafePaxos)t_{safe}^{Paxos})tsafePaxos​)
    • 回复coordinator leader并携带siprepares_i^{prepare}siprepare​
  • coordinator leader:
    • 先获取写锁,等待其它participant leader的prepare所有回复
    • 给提交事件附上时间戳sss,其需要满足:
      • s>maxi(siprepare)s > max_i(s_i^{prepare})s>maxi​(siprepare​),保证tsafeTMt_{safe}^{TM}tsafeTM​的合理性
      • s>TT.now().latests > TT.now().latests>TT.now().latest,保证start阶段约束
    • 使用Paxos持久化该事件,写入log(此时更新tsafePaxos)t_{safe}^{Paxos})tsafePaxos​)
    • 等待TT.after(s)TT.after(s)TT.after(s)成立,保证commit wait约束
    • 告知客户端sss,告知事务提交完成
    • 告知其它participant leader(捎带sss),让它们也提交事务(也使用Paxos写入提交事件),并释放锁

Read-Only Transactions

只读事务需要分为时间戳sreads_{read}sread​,具体原则如下:

  • 若read scope仅限于单Paxos group:

    • 给该组的leader发起只读事务
    • leader为只读事务分配时间戳sread=LastTS()s_{read}=LastTS()sread​=LastTS(),LastTS()LastTS()LastTS()为Paxos group最近一次的commit write timestamp
  • 若scope跨多Paxos group,有多种选择:
    • 协商各个组不同的LastTS()LastTS()LastTS()
    • 选择TT.now().latestTT.now().latestTT.now().latest,但是可能需要等待tsafet_{safe}tsafe​变大

Refinements

tsafeTMt_{safe}^{TM}tsafeTM​存在的问题:当存在一个prepared但没commit的事务,tsafet_{safe}tsafe​无法变大,会阻塞sread>tsafes_{read}>t_{safe}sread​>tsafe​的读操作,即使可能并没有冲突。

解决方案:建立一个<key, prepare timestamp>的映射关系,存储在lock table中,在进行读操作时,只检查产生lock confilict的tsafet_{safe}tsafe​

LastTS()LastTS()LastTS()存在的问题:当一个事务刚被提交,一个读请求时间戳必须跟在刚提交事务的后面,造成阻塞,即使读操作不会造成冲突

解决方案,建立一个<key, commit timestamp>的映射关系,存储在lock table中,在进行读操作时,只选择产生lock confilict的最大LastTS()LastTS()LastTS()。

tsafePaxost_{safe}^{Paxos}tsafePaxos​:没有发生Paxos write时,tsafePaxost_{safe}^{Paxos}tsafePaxos​无法变大,会造成读阻塞。
解决方案:每个Paxos group leader维护一个下一个Paxos write可能会发生的最小时间戳MinNextTS(n)MinNextTS(n)MinNextTS(n),并令tsafePaxos=MinNextTS(n)−1t_{safe}^{Paxos}=MinNextTS(n) - 1tsafePaxos​=MinNextTS(n)−1。注意,MinNextTS(n)MinNextTS(n)MinNextTS(n)必须在租约内,且如果MinNextTS(n)MinNextTS(n)MinNextTS(n)超过了租约期需要先延长租约。

MIT6.824 Spanner论文精读相关推荐

  1. MIT 6.824 Raft论文精读

    文章目录 Introduction Raft Consensus Algorithm Raft Basics Leader Election Log Replication Safety Electi ...

  2. MIT 6.824 Aurora论文精读

    文章目录 Introduction Durability at Scale Replication and Correlated Failures Segmented Storage The Log ...

  3. MapReduce论文精读

    文章目录 概述 研究意义 编程模型与系统实现 编程模型 Map Reduce 示例:统计文档中所有单词的出现次数 系统实现 基本流程 容错处理 worker异常 master异常 locality T ...

  4. mit6.824 2022 lab2

    MIT6.824 2022 Raft Raft leader election log persistence log compaction 整体测试 后面发现的问题 参考代码 汇总博客:MIT6.8 ...

  5. 论文精读——CenterNet :Objects as Points

    论文精读--CenterNet :Objects as Points 论文地址:https://arxiv.org/pdf/1904.07850.pdf 机构:UT Austin,UC Berkele ...

  6. Google Spanner 论文笔记

    Google Spanner 论文笔记 架构 复制与一致性 TrueTime 事务 数据迁移 Google Spanner是谷歌的全球级分布式数据库(Golbally-Distributed Data ...

  7. 论文精读 | slam中姿态估计的图优化方法比较

    一. 摘要 对于位置环境中的自主导航问题,同步定位与建图(Simultaneous localization and mapping, SLAM)是一个非常重要的工具框架.根据SLAM字面含义可以得知 ...

  8. 李沐论文精读系列四:CLIP和改进工作串讲(LSeg、GroupViT、VLiD、 GLIPv1、 GLIPv2、CLIPasso)

    文章目录 一.CLIP 1.1 简介 1.1.1 前言 1.1.2 模型结构 1.1.3 模型效果 1.1.3.1 对自然分布偏移的鲁棒性 1.1.3.2 StyleCLIP 1.1.3.3 CLIP ...

  9. 【论文精读】UV-SLAM: Unconstrained Line-based SLAM Using Vanishing Points for Structural Mapping

    [论文精读]UV-SLAM: Unconstrained Line-based SLAM Using Vanishing Points for Structural Mapping 论文出处 ICRA ...

最新文章

  1. C 入门 第八节 指针
  2. Exchange数据库无法装载的问题
  3. Python中使用pip安装库时指定镜像源为豆瓣镜像源
  4. 经典C语言程序100例之十五
  5. Linux Socket TCP/IP通信
  6. docker镜像和容器区别
  7. 【渝粤教育】电大中专消费者心理学_1作业 题库
  8. 前端学习(1981)vue之电商管理系统电商系统之完成可选项的添加操作
  9. STM32 位带应用
  10. 5年iPhone用户换小米11 Ultra:惊叹小米变化大
  11. python 监视文件目录
  12. Coursera 斯坦福大学科学论文写作课程笔记(一)
  13. Hacking the PS4, part 1
  14. html 自适应 音乐播放器,mmPlayer:一款基于Vue的自适应Web在线音乐播放器
  15. Python之——获取电脑连接过的所有wifi名称和密码
  16. opera 无法访问网络
  17. 蓝桥杯 基础练习 分解质因数 python语言
  18. 地表温度lst数据的下载【国家青藏高原科学数据中心】
  19. spool模式导出数据库指定表的数据到Excel
  20. 参加微软学生开发者峰会,了解Azure和GitHub……

热门文章

  1. 未能加载文件或程序集一例
  2. Java:API正则
  3. java weka 聚类_# weka 聚类的使用
  4. asmca - 19c- ACFS
  5. 2023最新大猿人中控充值系统/免授权版/支持公众号H5+分销等功能
  6. Java五大invoke指令
  7. 零基础36天学c语言心得总结
  8. 远程控制软件安全吗?一文看懂ToDesk、RayLink、TeamViewer、Splashtop相关安全机制
  9. php存储MD5加密密码并验证
  10. 教你go语言如何使用go module进行golang库依赖管理