TIDB 对于Percolator 在分布式事务提交方面优化 Async Commit

2021-07-20 00:00:00 事务 节点 时间 获取 提交



Percolator 是谷歌在2010发表的论文«Large-scale Incremental Processing Using Distributed Transactions and Notifications» 介绍的分布式事务协议。TIDB 很多的理论都是基于 GOOGLE的一些白皮书的. 分布式事务TIDB 也是借鉴了 google 的 percolator的论文并进行了改进,提高了性能.


首先我们先对percolator的一些概念进行理解,然后在看TIDB 对于这些理论改进的部分.

1  获取TSO 用时间戳作为 start_ts

1   事务在提交需要缓存在client端, percolator 的事务提交分为 perwrite 和 commited


2 事务开启会获取TSO 事务号, TSO 是通过时间戳标识的,事务开启时获取的时间戳是 start_ts 


3  Perwrite  过程

3.1   获取TSO 用时间戳作为 start_ts

3.2   选择一个写入点为主节点, 其他的复制节点为从节点

3.3   在获得start_ts后进行判断,要插入的key是否有冲突, 如时间有一致的, 在          这样的情况下, perwrite 事务直接abort 

3.4    时间戳被记录到数据ROW中

3.5    WRITE 操作进行锁定,此时这个时间只能属于这个操作


4    Commit  过程

4.1   获取TSO 作为commit_ts 

4.2   对数据进行commit 主节点的操作

4.3   操作成功,将结果返回给client

4.4   异步进行 commit  secondary的操作


以上是分布式percolator 的整体单事务工作的流程.  这里有一个位置是需要等待的,就是我们的 get TSO .


TIDB 在如下的操作中更改了一些部分提高了性能




那么我们看看TIDB 是如何利用自己的本身的情况来优化percolator 模型的,下面是一个对比的列表


TIDB 中改变的是


1  在 Perwrite 后就可以确认数据可以进行commit 

2  在perwrite 后会可以获得commit_ts


这样修改后,网络交互会少一个程序. 主要的特点

1  基于TIKV 存储所有数据,而不是在客户端存储缓存的方式

2  perwrite 完成后就可以确认数据可以commit了


那么问题是如何能确认perwrite 完成了


1   采用percolator的方式则数据的状态以primary key 负责,查到secondary key 可以通过指针来指向 primary key,查询键值的状态


2  commits 的时间可以在perwrite 确认后在进行commits的获取


但为了提高整体系统性能,减少交互,则需要解决上面的两个问题


1   在perwrite就要进行确认,KEY 所以TIDB 在这里进行改动,在主节点中记录了secondary key 的, 这样可以无论通过那个KEY 都可以去找到其他的key,这样做的另一个隐藏的需求就是在提高性能的时候, 记录的键的数量不要太大,这里TIDB 控制到 256个KEY address, 整体字节数在 4096个字节内. 


这里TIDB 优化的目的为减少网络交互,而过大的事务在网络交互中本身会将优化后的优势消减,所以大事务这里TIDB 并不会使用这样的方式来进行commit


2  commits  ,上面说了commits 获取与perwrite有关, 而我们获得每个事务的commits 的工作可以通过 Max TS (PD placement driver)  MAX TS 为当前PD 分配时间戳的大值,commits =  MAX TS + 1  保证事务commits 是顺序的递增的.


总结:  Async Commit 提交的方法针对提交primary key 耗时的操作,针对某些场景也是有无法奏效的情况.  如 你的I/0 已经是瓶颈了,那么通过软件的方式来优化就是徒劳的, 同时对于big transaction  以及 big key 来说, 问题的优化点已经不在提高 primary 提交的效率了,而是把大事务拆小的优化,让提交的事务尽量小使用 async commit的方法提高数据提交的效率.



注:分布式数据库的理论和单体数据库的理论差异比较大, 还需要用更多的时间领会其中设计者的心思的精妙.

相关文章