深入理解Spanner事务

转载请附本文链接:https://blog.csdn.net/maxlovezyy/article/details/103745151

最近读了论文Spanner,发现其事务的实现还是蛮有意思的,设计上有一些不是很显而易见的地方,这里记录一下,希望能对更多的人有所帮助。下面先介绍一下其实现事务的基本依托和组件,之后再详细分析一下其事务的实现。

引子

目前数据库的数据模型基本上都是MVCC的模型,读不需要上锁,基于快照即可,写的话也不需要in-place地更改,对IO来讲也是很友好的,具有很好的性能。另一方面,对于数据库的串行化技术来讲,主要有两种手段,一个是锁,一个是基于时间戳排序,时间戳可以和MVCC很好地结合。

Spanner也采用了MVCC的数据模型,通过锁和时间戳排序结合的方式来保证事务的ACID特性。另外,Spanner是一个全球化的数据库,这意味着它的时间戳不能像Percolator中提到的一个集中的时钟服务来提供了,其用到的是下节中介绍的TrueTime,这是一个类似于NTP的一套时钟保证机制,可以认为是一个能提供误差有界的、精度很高的物理时间的时钟机制。

TrueTime

Spanner通过原子钟和GPS授时结合,提供了上下误差在2ms以内的物理时钟服务,其API如下:

MethodReturns
TT.now()TTinterval: [earliest, latest]
TT.after(t)true if t has definitely passed
TT.before(t)true if t has definitely not arrived

可以看出,TrueTime API得到的当前时间不是我们物理意义上的一个绝对时间戳值,而是一个时间范围,这个时间范围包含了此时的绝对物理时间,也就是说earlist和latest绝对时间戳的上下界。

架构

在这里插入图片描述
上图为Spanner的软件架构,可以看出,每一个复制组的leader都有一个transaction manager实例,其也作为事务的参与者的leader。在事务2PC的过程中,client会选取一个参与者leader作为协调者(coordinator)来完成2PC过程。

事务概览

Spanner支持读写事务(read-write transaction)、只读事务(read-only)和快照读(snapshot read)。默认Spanner支持的外部一致性是线性一致性线性一致性是这样的:请求会在client发出之后,要么返回了成功的响应,意味着请求在发出和收到响应中间的某一个时刻执行了,并且只执行一次;要么返回了明显的失败表示没有执行成了;要么返回了未知错误,这是一个不可预期的结果,但无论如何也不会执行超过一次。

  • 读写事务来
    Spanner是通过悲观锁和乐观锁结合的方式实现的,在不考虑谓词过滤导致幻读的情况下,Spanner实现的隔离级别就是串行化的级别(具体原理可以参考隔离级别一节)。纯写事务会按照读写事务的流程处理。
  • 快照读事务
    用户可以给提供一个时间戳作为快照的时间戳,基于这个时间戳的快照执行请求。可以想见的是,如果指定一个过去了的时间戳,相应的版本未被回收之前,这是一个非阻塞的事务,因为一切已经都是过去时了,没有并行的rw事务,不需要拿锁。
  • 只读事务
    只读事务是快照读的一个特例,仅仅是没有指定一个快照时间戳上界的快照读事务。对于时间戳来说,由于Spanner对外提供的是线性一致性,所以这里的时间戳就是最近的数据足够新的一个过去时的一个时间点。TODO。

Spanner由于支持了MVCC,所以其可以对只读事务有一个良好的支持,也比较简单地支持SI读。

暂记

[commit-wait目的]

  1. 没有TSO分配时间戳,而且TrueTime时间是一个时间范围,当两个时间有交叠的时候,无法判断哪一个时间在绝对物理时间意义下更早。而由于Spanner的支持快照读的外部一致性: 如果一个事务已经提交了,而另一个事务发起了,另一个事务是看得见已提交事务的影响的。这其实在2PL的实现里是没问题的,直接返回结果就好。但由于Spanner支持无锁的只读事务,没有了锁,又由于无法界定有交叠的两个TrueTime(前一个事务commit时的ts和快照读事务的start ts)的绝对物理时间下的先后顺序,所以必须让两个TrueTime时间戳没有交叠,那做法就是wait就行了,wait之后再返回给客户端,那么客户端再次发起请求的时候其start ts就一定和commit ts的TrueTime没有交叠了。
  2. write是乐观的,需要用于确定先后关系做是否发生并发而冲突了的判断。同1中存在的问题,如果不wait,可能本在绝对物理视角下外部看起来没有交叠的两个事务发生冲突了,这是不合理的。
  3. 同1中存在的问题,commit-wait实现了这样的一致性语义: 在绝对物理时间上看,对于客户端来说,如果一个事务T1完成后事务T2才开始,那么T2的commit时间一定大于T1的commit时间。反之,如果不wait,则有可能有交叠,失去了这样的一致性保证,这和单个TSO提供时钟时是不同的。

[commit时间戳去参与者拿作参考的目的]

  1. 做mvcc快照读的判断,能给复制组一个当前活动事务的时间,用于判定安全快照点。如果不这么做就需要额外方式跟踪活动事务。
  2. 参考点多了,概率上尽可能避免TrueTime异常偏移

关键设计

### 隔离级别 暂记:为什么不考虑谓词过滤的情况下是串行化的级别?证明方式是通过证明任意两个事务不可能存在rw依赖。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值