zoukankan      html  css  js  c++  java
  • Spanner:谷歌新一代全球部署的列式数据库

    Spanner 是一个可扩展的、全球分布式的数据库,提供分布式ACID。

    架构

    image

    • universe:一个部署的实例成为universe,目前谷歌有3个,分别为开发/测试/线上

    • Zone:一个数据中心,相当于一个Hbase/Bigtable

    • Universemaster: 监控这个universe里zone级别的状态信息

    • Placement driver:提供跨区数据迁移时管理功能

    • Zonemaster:相当于BigTable的Master。管理Spanserver上的数据

    • Location proxy:存储数据的Location信息。客户端要先访问他才知道数据在那个Spanserver上

    • Spanserver:相当于BigTable的ThunkServer,用于存储数据

    SpanServer

    image

    • tablet:一张表的多个横切的组合(相当于bigtable多个tablet组合),拥有多个副本
    • paxos:每个tablet上都有一个tablet状态机。相关副本的集合成为一个paxos group。
    • lock table:leader采用锁的方式实现并发控制
    • transaction manager:采用两阶段提交完成跨paxos group(多个tablet)的分布式事务。如果事务集中在单个paxos group,可以绕过transaction manager。
    • participan leader和coordinator leader:事务管理器用于实现了participan leader。然后其中一个一个paxos group,被选举为协调者。它的leader和slave分别被称为coordinator leader和coordinator slave

    总结:

    1. 使用paxos协议保证了副本的一致性
    2. 多个tablet之间选举协调者(如何选?paxos?),采用两阶段提交处理分布式事务

    目录和放置

    • 目录:一个表的横切,相当鱼bigtable的tablet movedir后台任务可以让目录在多个paxos group之间迁移

    数据模型

    image

    spanner数据库的表必须被客户端切割为一个或多个层次结构。使用INTERLEAVE IN语句声明这种层次结构。父表和子孙表相同的第一列放在一起,这样用户定义了这张大表的位置关系。DELETE CASCADE代表级连删除

    TrueTime

    采用GPS和原子钟提供了TrueTime API

    image

    并发控制

    spanner提供外部一致性,无锁的只读事务。一定要区分spanner客户端看到的写操作和paxos看到的写操作

    时间戳管理

    spanner支持的事务类型:

    1. 读写事务(包括单独的写事务)
    2. 只读事务(预先声明的快照隔离事务)
    3. 快照读

    image

    paxos领导者租约

    paxos leader有租约时间,可以隐式或显示地延长自己的租约时间。

    为读写事务分配时间戳

    事务读和写采用两段锁协议。当事务获得所有锁后,就给事务分配时间戳。这个时间戳是分配给paxos写操作的,代表事务的提交时间。

    spanner依赖以下单调性:每个paxos组内(跨越多个leader,事务相关group吧?)会分配单调递增的时间戳。

    spanner外部一致性:如果事务T2在事务T1提交后开始执行,那么事务T1的时间戳一定比T1的时间戳大。

    某个时间戳下的读操作

    每个副本都会跟踪记录一个值, 这个值被称为安全时间 t(safe), tsafe=min(tsafe_Paxos , tsafe_TM)。小于这个安全时间的读操作,都可以被读取。

    为只读事务分配时间戳

    一个只读事务分成两个阶段执行: 分配一个时间戳TT.now().latest, 然后当成 快照读来执行事务读操作。

    细节

    读写事务

    将读写事务分为读操作,写操作。写操作先在客户端缓存,所以读操作并不会看到当前事务写的数据。

    读操作

    读操作先执行,使用伤停等待来避免死锁。读操作执行的时候会获取读锁

    写操作

    1. 客户端发起所有写操作的两阶段提交协议,将所有写操作发送给作为协调者的领导者。
    2. 非协调者领导者首先执行预备提交,写操作开始要获取写锁,并将预备提交写入日志
    3. 协调者领导者获取写锁直接提交,写入paxos(时间戳比所有预备提交时间戳大)
    4. 协调者领导者等待获得的提交时间戳成为真实的过去,告知所有非协调者者领导者提交事务,并告知客户端。

    时间戳单调性:非协调者leader预备提交->协调者leader获取提交时间戳,提交->协调者等待获得的提交时间戳成为真实的过去->告知非协调者leader和客户端提交,提交后释放锁。

    理解:两阶段提交不能单独使用,这里面配合了写锁,paxos协议才保证了事务的一致性。

    流程

    image

    思考

    采用wound-wait解决死锁:

    1. 当较新的任务尝试获得锁,等待直到锁释放
    2. 当较老的任务尝试获得锁,结束较新任务

    只读事务

    对于只读事务,spanner指定一个读事务时间戳。

    1. 只需要读一个paxos group:直接读请求发给paxos leader,获取一个最新已提交事务时间戳,返回给客户端。
    2. 需要读多个paxos group:
      1. 复杂方式:获取所有paxos group,得到最新的提交事务时间戳
      2. 简单方式:等到当前时间戳成为确定的过去,s_read = TT.now().latest

    总结

    1. spanner事务隔离级别为可串行化
    2. 采用两阶段提交协议,锁表(不知道粒度,猜测为tablet级),paxos协议实现事务,TrueTime等待提交(必须有啊,因为只读事务不加锁)
    3. TrueTime API用于给数据加上全局唯一的版本号
      1. 用于实现外部一致性,T1提交后T2才开始,那么此时T1的时间戳肯定小于T2的时间戳
      2. 提供了一致性快照读

    分布式事务中的悲观锁和MVCC

    下面是一点自己的想法

    1. 事务一般采用两阶段提交的方式
    2. 底层数据采用类paxos一致性协议保证可用性和一致性
    3. 悲观锁不需要全局时间戳,乐观锁需要全局时间戳(或者全局唯一的版本号)

    参考资料

    spanner的一些思考

  • 相关阅读:
    如何使用 Python 创建一名可操控的角色玩家
    Unity查找物体的四大主流方法及区别
    JavaFX桌面应用开发-鼠标事件和键盘事件
    profiler-gpu分析记录
    JavaFX桌面应用开发-Button(按钮)与事件
    CodeCombat代码全记录(Python学习利器)--Kithgard地牢代码1
    spine骨骼动画组件使用详解
    微信小程序animation
    LeetCode--不同路径
    Learning opencv续不足(七)线图像的设计D
  • 原文地址:https://www.cnblogs.com/biterror/p/6909886.html
Copyright © 2011-2022 走看看