Spanner系列 --- 事务处理模型 -- 03

2018-01-08 13:33:21来源:http://blog.163.com/li_hx/blog/static/1839914132018079484831作者:那海蓝蓝的博客人点击

分享

4.2.3
写操作一致性的实现原理


Spanner
的写事务的分布式实现,依据的是什么机制?这个问题,其实是一个难题。




Spanner
的论文里,如图
6
所示,“
Read-Write Transaction
”的并发访问控制技术使用的是悲观机制,并且论文里说“
Reads within read-write transactions use wound-wait to avoid deadlocks
”,这两个明确在说,
Spanner
是采用基于封锁并发访问控制机制来实现事务的一致性所以才需要使用“伤停等待”算法来解决死锁问题
。这就会让我们联想到
2PL
,联想到单机数据库如
Informix

Oracle

MySQL/InnoDB
都使用了
2PL

SS2PL
算法来解决事务的一致性问题。那么,
Spanner
是否也使用了
SS2PL
算法呢?




Spanner
的论文里,还有如下表述:



Like Bigtable,
writes that occur in a transaction are buffered at the client until commit
. As a result, reads in a transaction do not see the effects of the transaction’s writes. This design works well in Spanner because a read returns the timestamps of any data read, and uncommitted writes have not yet been assigned timestamps.



这段话,看起来又是别有洞天:写操作缓冲在客户端,直到提交。这样的方式,是乐观机制的行为,偏偏
Spanner
的论文把自己描述为悲观机制,这是一个值得注意的地方。之后,又有下文:



When a client has completed all reads and buffered all writes, it begins
two-phase commit
. The client chooses a coordinator group and sends a commit message to each participant’s leader with the identity of the coordinator and any buffered writes.



这段话,表明
Spanner
事务提交,跨节点使用了
2PC
,提交信息发给所有参与本事务的节点中的
leader
角色,并指明哪个
leader
是协调者。


之后,参与者获取写锁,如果获取到写锁,则选择一个“单调递增”的、比历史给出的时间戳更大的时间戳值赋值作为两阶段提交的第一阶段的时间戳值。如下:



A non-coordinator-participant leader first acquires
write locks
. It then chooses a prepare timestamp that must be larger than any timestamps it has assigned to previous transactions (to preserve monotonicity), and logs a prepare record through Paxos.



再之后,协调者开始获取写锁,记录提交日志,同步到自己的
Paxos
组内,并作提交等待
,目的是让提交时间度过一个网络延迟的事务提交安全期,以获得一个安全的事务提交的时间戳值:



The coordinator leader also first acquires
write locks
,
but skips the prepare phase. ……Before allowing any coordinator replica to apply the commit record,
the coordinator leader waits until TT.after(s)



而安全的提交时间戳值,
Spanner
是由主副本(
leader replica
)简单地按照递增的顺序指定的。当然,这之外还需要一个约束:在切换主副本(
leader replica
)所在的
leader
时,保证跨主备切换下的时间戳也是递增的。此约束在论文中表述为“单调不变性(
monotonicity invariant
)”。这是确保时间戳单调递增。


当获得安全的提交时间戳值后,协调着开始两阶断提交的第二阶段,通知参与者发起提交,参与者提交并记录提交日志并复制日志给同组的副本,最后通知客户端事务成功与否。



再之后,才进行锁的释放工作。这意味着并发访问控制机制是
SS2PL


All participants apply at the same timestamp and then release locks.



对于“
Read-Write Transaction
”事务中的读操作,论文描述:



The client issues reads to the leader replica of the appropriate group, which acquires
read locks
and then reads the most recent data.



客户端对于一个
Paxos
组,向该组内领导者副本即主副本发起读操作,获取读锁。这点很重要,一是在“
Read-Write Transaction
”事务中的读操作,与基于快照的读操作和只读操作读取的副本主体是不同的,二是读操作也加锁。这也是分布式系统中全局一致性的一个体现,读写事务只能在主副本发起才能保证一致性。



总结
Spanner
的读写事务处理机制,我们可以看到:



1.
第一,在读写事务中,Spanner
混用了乐观和悲观机制,把两者结合起来:



a)
先是乐观策略,但乐观阶段中夹杂了读锁而悲观了。



b)
提交阶段采取悲观策略,时间戳是提交时间戳而不是事务启动时间戳,这使得并发的读操作只需要和读写事务的提交点比较即可:



i.
读在提交点之前:自由读取,不存在读写冲突。



ii.
读在提交点之后:如是并发写事务的提交点,存在读写冲突,提交点推迟,线性把事务排了队,解决了读写冲突。



c)
提交时刻,写操作加锁,使得并发事务排序,实现了序列化保证了ACID
中的C



2.
第二,在悲观机制中,使用了SS2PL
,统一释放乐观策略阶段施加的读锁,释放SS2PL
过程中施加的写锁。



3.
第三,Spanner
采取两阶段提交解决了跨节点的数据一致性问题,此两阶段融合在了悲观机制中的SS2PL
算法过程中。



4.
第四,提交阶段,给写事务赋予一个时间点,是通过图9
中的方式保证,这样TrueTime
发生作用,致使外部一致性得到保证。


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台