订阅
纠错
加入自媒体

首款国产开源数据库TBase核心架构演进

2020-06-09 10:15
IT168
关注

接下来给大家详细分享下TBase是怎么做的,重点分享架构设计思路。

讲分布式事务之前首先讲下Sharding模式存在的问题。这里举个例子,我们现在有AB两个帐户,每个帐户余额是10元,两个帐户总额是20元,我们对这两个帐户之间进行转帐,从B往A转5元,并发量很大的时候,如果是一个一致性保持的比较好的系统,那么无论我们有多少的并发,两个帐户的总额应该总是20元。

在sharding模式下,事务3和事务4存在严重的事务不一致问题。那为什么很多业务系统中用了sharding的模式,却没有这类问题呢。主要的原因是大多数使用以上模式的业务都是互联网公司的业务,互联网公司的开发团队有比较强的开发能力,可以让业务代码处理上面遇到的问题,把数据库作为一个简单的数据容器来处理。但对于一些普通用户或者普通场景的话,就不一定具备互联网公司的资源和技术能力了。在TBase中,我们也是需要处理分布式事务的一致性问题,为业务屏蔽掉事务的相关细节。这里我分享下TBase分布式事务系统的目标。

首先在保证分布式事务完整性的基础上能够提供高性能、低延时、高吞吐的事务能力,并尽量使用低成本的硬件来达成我们的目标。同时,也希望在保证这三者的基础上,我们事务的处理能力能够随着集群的规模近似线性的增加,提供事务处理能力的扩展性,提供包括死锁检测和事务故障恢复等事务保障能力。

在开始介绍TBase事务模型之前,先来看一下现在大家常用的分布式事务模型。

一、分布式的快照隔离

可以简单理解是PostgreSQL使用的MVCC的分布式的实现,这里面主要分几个部分。

在GTM上,要求维护一个开放的事务列表,事务列表指的是当前这个集群里面正在运行的一些事务。举个例子,如果说我当前启动一个新的事务,然后我就会把它加到这个列表里面来。如果这个事务结束了,这个事务列表就会把这个xid从事务列表拿掉。客户端在跑一个SQL的时候,都会要求从GTM上拉取一个事务的快照,所谓的事务快照是将当前这个事务列表里面的一个拷贝,发到我们的DN上做活跃事务的判断。这里有以下3个问题。

问题1:这个活跃事务列表是一个O(N)的长度,也就是说它和当前事务并发的个数是呈正比方式的,有多少个并发的事务在跑,这个事务的列表就有多长。

问题2:刚才也提到我们每个客户端在访问SQL的时候需要从服务器去拉取一个快照到本地去,这样的话也就是说对GTM的网络占用的比例是N的平方,也就是N的平方乘以M,M是SQL的个数。

问题3:刚才也提到了,事务列表是全局资源,不管是事务的启动还是提交,甚至获取快照都需要对这个列表进行加速。这样的话,基本上来讲我们是在系统里面增加了一个全局的大锁,这个大锁就会成为这个系统的一个扩展的瓶颈。

二、基于物理时间的并发控制

基于物理时间有两种方式:

第一种方式是Google spanner中采用的方式,这个分布式系统要求提供一个全球分布式的一个分布式数据库,达到百万级的数据库节点。基于全局时间快照的进行并发控制,它的全局时间快照使用的是GPS和原子钟一起生成。全局时间版本,这个东西有一个6毫秒左右的误差。也就是说它的一个事务在运行的时候,最低延时就是6毫秒。第二个问题是成本比较高,需要专用硬件,每个IDC都需要有自己的原子钟和GPS设备。

第二种方式是CockRoachDB,其实是Google Spanner的变种。主要的区别是它使用的是本地的时间来进行控制,严格意义上讲应该是混合时钟。相比之下成本会比较低廉,并且没有中心节点。但是NTP精度会影响事务的时延。

三、基于逻辑时间的并发控制

现在大家讨论的比较多的是基于逻辑时间的并发控制。

用一个TSO集群提供集群的逻辑时间戳作为版本号。这个事务模型相对来讲就没有之前提到的那几个版本控制的问题。里面会把当前事务里面进行的所有的修改记录都记录下来,在事务提交的时候一次提交,也就是说它是一个O(N)的动作,N指的是我们在这个事务里面修改了所有的记录的集合。而且这个过程中集群会加锁,阻塞后面的写入。

这里重点介绍TBase这一块,TBase的并发控制,全局事务的一个控制其实是结合了最早提到的分布式快照隔离一起做的一个隔离模型。

核心部分是GTS集群,GTS集群和TSO的功能很像,也使用了逻辑时间戳的概念,这个时间戳的基线是我们自己定义的一个开始的点,单向递增。

我们自己内部定义了MVCC机制原理,对于当前事务,记录的gts_min已经提交,而且事务的gts小于记录的gts_max,我们才能看到这条记录。

GTS是从0开始的一个单向递增的逻辑时钟源,通过硬件提供足够的稳定性保证,保证不发生偏斜。同时,GTS本身通过流复制的方式来保证自己的可靠性。性能方面,一般普通24 core的服务器可以达到1200万的QPS,几乎可以满足所有业务场景的需要。

下面分享一下TBase在行存储和列存储这一块的一个选择。

行存储的话,顾名思义,是按行存储。也就是说在磁盘存储的时候,我们像上面的表一样,我们存储的时候是先存储完第一行,然后存储第二行,再存储第三行,再第四行,这样紧密存储。这个好处在于:每次IO的时候,可以把一行记录的所有的列都能够读到这里面去,适合OLTP场景。

另外一个是按列存储,我们把同一列的数据连续存储在一起。比如:蜘蛛侠、超人、火箭浣熊、闪电侠这一列在磁盘上面,第二列是另外一个文件,这种存储的好处在于:每次IO的时候,只会读取同一列的数据,可以大大的提升聚合操作处理的效率,比较适合OLAP的场景。

在分布式场景下,我们不得不考虑另外一个问题,除了选择的行列之外,还要考虑我的数据在集群里面如何存储,也就是怎么把数据分片存在我们的分布式集群里面去,TBase里面叫选择表的分布类型。

第一种是复制表,有的地方叫快表,在集群里面的指定节点上,每个节点都会有数据的完整副本,这样的表特别适合一些变化比较小的小表,对于一些关联插件的加速是比较有用的。

第二种是大家比较常见的是HASH分布,就是把数据打散到不同的存储节点上去,明显的问题是HASH倾斜。

第三种也是比较常见的方式RANGE分布,即按照数据的范围来进行分布。其实在分布式场景中,除了这种我们可以指定具体的算法进行分布的方式之外的,还有就是在数据仓库里面比较常用的随机分布,不用任何算法来进行分散,把数据全部打散到整个集群中去。TBase的分布方式主要有复制表和HASH分布两种。

关于分布式查询的执行方式,在MPP这种架构下每个DN的数据都是不完整的。为了完成一个完整的分布式查询,有一些策略需要选择。如果是一些单点的查询就无所谓,比较难搞的是分布式的JOIN。

这里面的策略主要有两种,一种是所谓的PUSH QUERY,通过把它的查询下推到DN节点上去, SQL在DN上执行,把数据返回给CN。另外一种方式就是PULL DATA,也就是通过把DN节点上的数据拉取到CN上通过CN来完成所有的计算。数据量较大的时候, PUSH QUERY效率会高很多,PULL DATA在一些数据量比较小的时候,效率会比较好。TBase里面两种方式都会有,我们也会选择PUSH QUERY或者PULL DATA,至于选择哪种是根据我们的优化器来选择。

分布式执行在 SQL shipping还是PLAN shipping之前该如何选择?

SQL shipping是指我们在PUSH QUERY的时候是PUSH SQL,DN完成SQL解析和优化执行。这种场模式不适合复杂SQL的执行,但架构相对比较简单,易开发易维护。所谓的PLAN shipping是在CN节点上生成整个执行计划,CN节点再根据我们的统计信息和数据分布来生成计划的分片,再把这个下推到各个DN节点上去,这个时候DN节点就不会进行二次解析,拿到执行计划并返回结果。这种方式优点其实比较明显的,它对SQL的优化能力是比较强的,能够在一些特别复杂条件的时候,效率会比较好。不过缺点比较明显,对于一些数据量不大的场景,执行计划的解析和下发花了很多的时间,导致简单查询的时候,小数据量查询效率不高。在TBase中,我们会根据我们业务的特点和数据的特点来选择两种中的任何一个,也就是说TBase两个都是支持的。

<上一页  1  2  3  4  下一页>  
声明: 本文由入驻维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。

发表评论

0条评论,0人参与

请输入评论内容...

请输入评论/评论长度6~500个字

您提交的评论过于频繁,请输入验证码继续

暂无评论

暂无评论

    人工智能 猎头职位 更多
    扫码关注公众号
    OFweek人工智能网
    获取更多精彩内容
    文章纠错
    x
    *文字标题:
    *纠错内容:
    联系邮箱:
    *验 证 码:

    粤公网安备 44030502002758号