分布式数据库产业现状如何
分布式数据库产业现状如何
我国数据库产业现状
分布式数据库逐渐成为主流
Hubble数据库的定位
Hubble数据库的诞生
Hubble数据库要解决的问题
本篇将通过以下五个部分带你走进分布式数据库的世界,第一部分:我国分布式数据库的产业现状如何?第二部分:分布式数据库逐渐成为主流;第三部分:分布式数据库解决的问题;第四部分:数据库的定位;第五部分:数据库技术发展的路线图。相信通过以上五个部分能够对分布式数据库有更深入的理解。
数据管理发展阶段
数据管理发展大致分为三个阶段:人工管理阶段、文件管理阶段和数据系统阶段。50年代中期以前,没有专门的数据库管理系统,都是由人工进行管理。但是随着数据量的不断增长,50年代中期到60年代后期,开始基于操作系统中的文件进行数据管理。60年代后期以后开始,硬件成本降低,外部存储容量增大加之内存技术的不断精进,数据库管理系统应运而生,克服了文件系统方式下的分散管理的缺点。
数据库系统发展历程
数据库随底层 IT 架构、数据特征、企业需求等变化发展而不断演进。自1960年首款企业级数据库诞生以来,数据库已有近70年的发展历史,70年间数据库不断地演进,涌现出新的数据模型、新的产品架构、新的负载需求、新的部署方式。每一次数据库产品的迭代实际都是在所处的时代背景下,利用新技术更好地解决新需求。
在进入分布式数据库的世界之前,我们先看下数据库发展的整个历程,主要分为四个阶段:1970年以前为第一个阶段,1980年后至2000年前是第二个阶段,2000年至2015年是第三个阶段,2015年至今是第四个阶段。在70年代以前,如图表所示,纵向和横向详细的介绍了每个阶段的详细信息,纵向的列包括一个发展的背景、数据模型、负载类型、硬件架构、是否开源和上云以及具有代表性的数据库厂商。
每个时代都有一个大的趋势,1970年之前,属于基础技术阶段,像交换分组技术、阿帕网投入运行等等。这是最早期的阶段,1970年之后进入基础协议阶段,包括TCP/IP协议的出现,计算机通信技术以及以太网的发明等。2000年之后随着web2.0包括互联网整体的兴起之后,带来很多更大变革,包括NewSQL、多模、HTAP、数据湖以及云原生的数据库不断的产生,所以2010年之后中国数据库才真的进入了一个快速发展的阶段。
如下图所示,我们可以看到国内外数据库产品迭代的对比,Oracle最早追溯到是1979年,从1979年至今40多年的历史,40多年历史中Oracle一直存在。而国产数据库的发展相对缓慢,1988年我国第一个自主版权数据库管理系统CRDS,这是国产数据库第一个参与阶段。1998年W2.0阶段,这是我国第一个具有自主版权的商业化的客户数据产品管理系统。1999年至2005年,几乎看不到国产数据库在此期间内的重大活动,国外数据库几乎垄断整个市场。
我国数据库产业现状
我国数据库产业发展的现状可以分为以下几个阶段,1980年为技术萌芽阶段,出现了人大金仓、达梦等国产数据库厂商。1990年为国外厂商垄断阶段,包括Oracle、IBM、DB2、Informix等国外数据库厂商在中国几乎完全垄断市场。2000年为国产数据库萌芽阶段,基于 863、973等计划,国产数据库才逐渐发展起来。2010年至今为国产数据库快速发展阶段,随着互联网行业不断地成熟,中国数据库产业快速地发展,PingCAP、OceanBase等新兴厂商也加入其中,这是一个快速发展时期。
全球数据库市场从2017年-2021年几乎是飞速增长,从本地部署模式下的国内关系型数据库市场中可以看到,Oracle数据库仍然占据了很大一部分市场,在金融领域,Oracle更是占据了一半的市场。2021年之后全球数据库厂商市场份额中可以看到,微软占比最多。目前来看,关系数据库依然是主流,关系型数据库占到60% ,非关系型数据库占到 40% 。
根据中国数据库产业图谱所示,国内传统数据库厂商包括达梦、人大金仓等;云厂商包括阿里云、腾讯云、华为云等;还有一些新兴数据库厂商:天云数据、巨杉、PingCAP等;国外的巨头数据库厂商包括Oracle、SQL Server等。国产数据库的发展速度非常快,相信不久的将来国产数据库会在国内外占有一席之地。
分布式数据库逐渐成为主流
分布数据库为什么会成为现阶段的一个主流,根据 IDC 与浪潮联合发布的最新报告, 2020年全球大数据储量为 50ZB,到2025年将达到175ZB。海量数据出现的原因是因为各个行业,包括金融、制造业等等,数据体量不断的增长,传统的集中式数据库很难来支撑这样庞大的数据体量。分布式数据库需求迅猛增长,基于纵向的扩展很难支撑庞大数据的体量,增加 CPU 也好,增加内存也好,增加业务场景也好,性能都是都会受制于它本身单机化的影响。分布数据库的出现解决了上述问题,基于计算机横向扩展的分布式数据库已成为现阶段主流数据库。
像Oracle数据库已经积累了40多年的技术经验,集中式数据库想要超越Oracle数据库几乎是一个走不通的道路。同样映射到汽车行业上也是如此,油车积累了几十年的技术壁垒,在这种壁垒之下很难被超越。只有换一个赛道,比如新能源电车等,这样才可能实现弯道超车。分布式数据库站在新赛道上,与国外传统数据库厂商几乎在同步发展,从2010 年之后分布式数据库与国外数据库呈现出并驾齐驱的状态,分布式数据库会成为主流的原因:一个是集中式数据库无法支撑庞大的数据体量;二是分布式数据库通过在新赛道上实现新的突破。
Hubble数据库的定位
前面我们讲了分布式数据库已经成为主流,接下来我们讲讲分布式数据库Hubble在市场中的定位,我们把数据库划分成以下四个发展阶段,第一个是IOE体系阶段,定义了集中式数据库。第二个是分布式数据库阶段。第三个阶段是HTAP数据库阶段。第四个阶段是AI-Native 数据库阶段。四个发展阶段各有什么特点呢?
第一个阶段是标签面向数据结构的融合,什么是标签面向数据结构融合?数据管理最开始是人工管理,然后发展为系统管理。人工管理包括文件系统管理,很难把数据结构进行融合。数据库的创新实现了数据结构的融合,把数据结构重新在数据库内做对应。第二个阶段是面向物理资源的融合,把多台服务器融合到一起,形成一个面向物理资源的融合,是一个把物理资源更多地用到一起并形成合力的阶段。第三个阶段是面向IO的融合,我们知道HTAP是一个混合数据库,支撑TP与AP的两层交易,TP面向于这种离散型数据的读取,AP是面向分析型集中式的数据读取。第四个阶段是面向服务的融合,数据库不仅仅支撑的是数据操作,它还需要支撑更多的业务。这种业务不仅仅是SQL语句,还需要AI 的算法、图的算法、机器学习的算法等。从数据结构融合、物理资源融合、IO资源融合以及服务融合这四个阶段不断地创新。
Hubble数库定位在哪?定位在HTAP与AI-Native 数据库之间,为什么没有定位到AI-Native数据库阶段?首先到达AI-Native阶段地路还很长,还需要不断地创新,其次我们已经通过了HTAP阶段,正在向AI-Native阶段递进。
Hubble数据库的诞生
为什么有Hubble数据库,我们先从传统数据库的发展开始讲起,第一个是传统关系型数据库RDBMS,第二个是MPP数据库,用于大量数据分析,第三个是NOSQL数据库,第四个是NewSQL。四种类型的数据库各自有各自的优缺点。
关系型数据库的优点包括事物、索引、关联、唯一性、强一致性,但是其扩展能力和可用性有限,数据结构取决于表空间的缺点让其很难实现横向的扩展。MPP数据库的出现修改了关系型数据库的缺点,可以支撑数据的扩展,又把扩展性、事务、索引、关联等做了一些继承。但是没有解决应用级切分。NO SQL数据库扩展性强,数据结构灵活,但是事务、索引、SQL支持差。NewSQL支持SQL、扩展性、实时性和事务,分布式体系需要通过NewSQL来支撑。
我们在研究中发现关系型数据库缺少支撑,我们做数据库的初衷是要解决同时支持在线应用、交易和分析,在Hadoop生态体系里边有批处理、图计算、索引、NO SQL等等这样一个体系,但是它依然缺少一个就是能够同时支撑在线交易和分析场景的数据库。
Hubble数据库要解决的问题
传统数据库存在什么问题,第一要做到水平的扩容与缩容,第二要解决分布事务问题。第三就是容错问题,单点的故障不应该影响整个业务的可用性。第四是数据一致性,如果默认底层是三副本,全部数据之间的同步必定会导致性能下降。所以我们做到了半同步转异步的数据一致性。
第五是上层技术问题,数据的迁移问题。传统的方式是从OLTP生产系统每晚将交易的所有业务数据t +1迁移到OLAP的分析系统,通过预处理将数据迁移到DS数据挖掘中。这是传统数据库里面常见的操作,相当于不断地做数据的迁移。
传统数据库中像Oracle数据库,晚上跑批或者跨库,需要迁移到TD、MPP中。像从TP迁移到HDFS大数据平台里面。还有需要多次跨库迁移的,比如从TP迁到AP再迁到HDFS大数据平台这样几层跨库的操作。这是我们现在面临的问题,跨库和多次跨库的操作。
如何解决数据迁移这些问题?首先我们要解决水平伸缩的问题,解决此问题之前我们参考了有很多积累的NoSQL数据库,比如HBase,Cassandra、MongoDB等已经做了很多积累了,这些积累能够供我们所用。其次我们要解决分布式事务问题,传统的是用两阶段提交2PC的一个模式,还有Google Spanner的2PL、2PC模式,2PL是它是两阶段的锁,两阶段锁机制再加上两阶段事务的机制,两阶段提交的机制以及容错的机制,容错机制就相当于多副本,比如基于Raft协议的机制。还有去中心化的事务冲突检测,我们通过以上几种方式解决所遇到的问题。
解决问题就要达成目标,除了重点支持外还有额外需要支持的,重点支持是我们前面已经提到的几个问题:分布式数据库最先要做到水平扩容/缩容、分布事务、隔离级别、异步schema变更以及容错。
什么是异步schema变更,我们说分布式数据库里面存几十亿到几百亿的记录数据是常见的事情,我们需要一个schema变更的时候可能说将字段修改成了某个字段,或者修改成了某个字段类型,这时候几亿条或几十亿条记录都会做变更。变更是不能够影响业务的,底层几十亿条记录正在变更的时候新的业务数据插入,以及老业务是不能够切断的。所以这种异步的变更是需要支撑的。这种异步变更相当于几十亿条记录底层的不断地变更,上层的操作是不断地执行且业务不能中断,所以在业务变更的时候是有很多问题需要解决。
分布式数据库首先解决本身底层单个服务器故障,它不应该影响上面的业务应用,包括额外支持的能力,如在线事务处理能力,需要能支撑联机的分析。还有一个信息硬件,信息硬件包括一些SSD存储、大内存、GPU以及FPGA等等,这些硬件也是在不断地呈现。
我们之前提到了两个目标,一个是技术目标,一个是数据目标,在数据目标中,这种融合不是真的是把两个库绑到一起简单的融合,真正的融合是要实现真正意义上的HTAP数据库,包括从事务处理、分析处理真正的融合。另外一个是数据处理目标,数据处理目标是把整体做到一个数据库同时支撑两类不同的业务场景。
分布式数据库的主要实现路径
前面讲的是要解决什么问题,接下来讲实现路径是什么?目前国内分布式数据库的实现有三种路径,一是分布式中间件的模式,比如分布式中间件加上一个单体的数据库。比如某分布式数据库,它的实现模式是上层加一个分布式中间件,下层加单体的库或单体的MySQL或PostgreSQL,这样形成一个中间件加单机数据库的模式。二是基于这种分布式共享存储,底层是一个大的分布式存储,上层是单体或者分布式的计算,相当于共享存储加上分布式计算的模式。三是原生的分布式数据库,底层采用分布式架构。三种实现模式中我们最终选择的是第三种,我们是原生的分布式数据库模式,基于底层原生的分布式数据库技术,这是一个真正的未来趋势。
中间件模式的阶段分库分表是可以解决很多问题的且有自己的市场,但是中间件的模式依赖于单体库,包括依赖于一些国外单体的库。这种模式在未来一段时间依然会存在,但是否是过渡阶段需要打一个问号。
人们眼中的数据库
原生分布式数据库是未来的方向,人们对数据库的认知可能是很多台机器,机器中装了数据库和数据、可能是数据库的LOGO、或者是数据库系统的安装界面等。
我们看到的还有数据库管理控制台,包括界面、通过语言调动数据库、监控和ER图,这都是人们眼中常见的数据库界面。
还有能够看到的表直线关系图、安装时的进度等等。
Hubble架构
今天的主题是进入分布式数据库的世界,上述人们眼中常见的数据库并不是真正的数据库世界,真正进入到数据库的世界是进入其结构里面去。通过了解Hubble的架构有助于我们更好的理解和进入到真正的分布式数据库世界。
Hubble数据库架构是四层三列,三列内容完全一样是因为架构体系一样,架构体系实现的是完全去中化架构,每台所连接的部署是一样的,这是去中心化架构的一个基础。分布式最小单元是三副本,三副本最少是三台机器部署。单机部分支持一个副本,但不具备分布式的特性。去中心化架构是我们的优势,三个完全一样的架构体系,访问哪个节点都一样。我们假设第一个列是属于node1,第二个列属于node2,第三个列属于node3,访问这三个节点,一般的做法是上层加一个硬件帮助,要不然加软件服务等,这都属于一种模式。所以在部署的时候,把数据直接传入每个节点中都可以不断提供服务。横向扩展时每个节点都可以对外服务,扩展的时候是无限的。扩展了一个节点,入口服务也会增加一个。这样不存在单点瓶颈问题,分布式数据库最难解决的问题就是你的单点瓶颈。
常用的大数据平台会有一个管理节点,叫master。所有的通讯需要经过master,所以如果分布式数据库也要有一个master的话,master管理里面很容易成为你的产品瓶颈。所以我们在设计这样数据库的时候,就考虑到把瓶颈去掉,所以我们整体该设计的时候就没有有管理节点的概念。每个节点都可以作为一个管理节点,每个节点都可以作为一个处理入口。
横向看分了四层,业务逻辑层(是数据库本身的业务逻辑)、资源管理层、混合计算层、混合存储层。存储层是基于分布式的存储结构。分布式存储结构底层是一个分片,每个分片都会有一个最小单元,每个单元默认为512兆。基于这样的一个512 兆的分片,我们可以不断地处理和复制。一个节点可以管理多个分片,每个分片都会有特定的数据,一个分片可以同步到这三个节点。像之前说的 node1,node2,node3它里边它会有一个分片,有一个主的管理键,主端leader,它的副本可能在node2、node3这样几个节点每个最底层的存储是一个分布式KV存储。
Hubble数据库发展路线
我们从2011 年就开始研究分布式数据库,那时大数据在国内刚刚兴起。我们从运营商为切入点使用了HBase+Solr的架构,实现了百亿数据量的秒内查询效率。
2013年到2014年,我们进入了金融行业,当时的名字叫BDRT,上层加了一个自己的SQL层, 从BDRT开始,我们就开始摒弃HBase+Solr架构,开始自研。从2014年开始我们定位从自研出发。为什么要自研?是因为我们最开始定位的要解决技术问题和数据迁移问题。这两个问题用HBase+Solr架构是很难解决的,所以我们从BDRT阶段就开始完全自研了。
从BDRT之后,我们不断的深入研究技术。2016年底我们重新定义了产品Hubble数据库。在协议上加入了TP协议,基于混合时钟,基于数据分片,基于 Raft共识,实现了Hubble数据库。2019年后一直到现在,支撑Hubble的AI-Native,包括DB4AI 等等。这是我们的整体的发展路径图。
目前我们对标主流数据库一个是对标Oracle,第二个是对标Teradata。Oracle是集中式数据库。我们在并发量小的情况下很难与Oracle对标,因为Oracle在集中式数据库是不走网络的,走一次网络是有网络延时的,在下图中支撑单表3亿记录数据量级我们看到Hubble在1600并发以上能力远远超过了Oracle的能力。
对比Teradata,在同一业务的全量2TB数据场景下同一SQL脚本,用1/4的计算资源,性能提升125%。
接下来我们重点分享分布式数据库的内部结构,一般是JDBC/ODBC 等其他协议,通过协议访问到数据库,最终访问结果。进入数据库大致会经过以下这几阶段。通信协议包括SQL解析、SQL优化、任务计算、任务调度、元数据、事务、数据分片与存储几个阶段,通过这几个阶段了解数据库内部的结构。
通信协议
目前国内主流的协议:MySQL协议、PG协议、Oracle协议等。协议是什么?协议是通信计算机双方必须共同遵从的一组约定。如怎么样建立连接、怎么样互相识别等。只有遵守这个约定,计算机之间才能相互通信交流,这个协议就相当于数据库本身的一个接口。
MySQL协议和PGSQL都是开源的,Oracle协议是闭源的,目前是行业的老大,但是闭源协议很难兼容它。还有其他协议,比如SQLserver、DB2等等,还有自定义协议,因为协议本身是访问数据库所用到的一个连接口,你可以自定义,也可以兼容以前的协议。以前的协议有什么好处?以前的生态可以直接用,比如你加入MySQL协议,加入PG协议,可以直接使用其生态,这样会少走一些弯路。通过综合考虑,Hubble实现的是PG加上MySQL两个协议。PG协议是主推的,PG协议不会存在一些法律风险和其他的一些问题。协议是协议,SQL语句是SQL语句,在SQL语句支持上,我们同时也考虑到传统数据库里面Oracle用的比较多,所以我们也兼容了很多Oracle的函数,方便迁移,包括上面提到 Teradata 函数也做了大量兼容。
SQL解析
SQL解析是数据库的基础,相当于记录操作数据库,数据库底层就是一个SQL语句,左下角是一个标准的SQL语句,这样一个SQL语句如何转换成数据库所能理解的一个语法呢?首先提交、查询之后会进行词法和语法分析,之后做会进行语义分析,再到逻辑计划和物理计划执行优化,最终选择一个最优的物理计划进入到任务调度,这是完整的流程。
我们看一下左下角的SQL语句,语句上方有两个表定义,下面是两个表的关联,这样一个表怎么转换成我们想要的一个关系代数呢?两张表根据Sid做关联,做完关联之后做过滤条件,过滤条件里边有三个过滤条件,一个是包括三个字段的过滤条件,最终要的结果是sname这样一个字段结果。这样我们把SQL语句转成关系代数,我们要最终要解释出来这个SQL的语句它的路径。SQL解析在整个过程之中非常重要。
SQL优化
简单举一个例子,这是一个优化器,它是自顶向下的一个SQL优化器。它有几个简单的关键概念,一个是Memo,一个是Group,一个Group expression。Memo相当于一个存储空间,用于存放优化的数据,Meno的设计是用来存储管理,在工程实现上可以理解为管理模块。Group的管理是真正的优化单元。
根据图中所示的SQL语句,从A、B 两张表里边查询两字段的关联,以及它的过滤条件value大于 10。根据上述五个Group可以推导出来,它有两个等价的模式,这两个等价类是什么?第一个类是两张表,先做Join,再做查询。第二个类是A表先做查询,A表value先做判断后再与B表做关联。优化器是把这两个等价的东西放到优化器里,基于它的代价模型算出来到底要走哪个路径。类似于高德地图,从某地到某地会有多个路径,最终要选择一个最优路径,所以优化器就是要把最优的路径选出来。
元数据管理
1)基础数据结构
之前提到了Hubble是分布式KV存储,下图是一个仓库表,仓库里面存的显示器、鼠标、主机三条记录。三条记录怎么映射到我们整个分布式KV 里边,分布式KV包含一个主键ID,Key下面会有一个层表,它是组件。这就是表结构以及它组件和ID 如何映射到KV结构中的过程。
2)列簇存储
我们在元数据中会添加一个列簇存储,这里面有一个family的概念,定义的表最下面是family f1和family f2。有一个mugshot的这样一个大的字段,一般存大体量的数据,比如里边可以存图片,或者存文件等等,传统关系型数据库会把这些记录全部存起来,我们会单独加一个family列,相当于列簇,是可以单独来存储大数据的。
单独建立fimily存储有什么好处呢?第一,读取这张表的时候,如果不读大字段,这时候大字段是不占IO空间的,相当于可以少读。第二,读取该字段的时候,如单独建一个family列簇,这样大文件就很好读取。它是如何映射到数据里面呢?我们也看图中的一条记录包括ID、first name、last name等整字段。这个字段如何映射到我们整个的结构里面?相当我们看到这是表名,表名是people,相当于表名、组件以及组件对应的ID、ID后边再跟它的family名称,这样它有两个kv,这样做了两个区分后,如果我们读取大字段,相当于会有单独的一个 IO体系来接收,这样省去了大字段存储的麻烦。
3)普通索引
普通索引是最简单的索引,普通索引相当于我们对内容做一个索引,如何将数据映射到我们对应的KV表中,如下图所示:KV表中可以看到Key一栏中包括表名、表的ID以及数据名称,普通索引中value是不存储数值的。
4)唯一索引
唯一索引与普通索引之间的区别就是唯一索引的目的是要保证整个数据的唯一,唯一索value中的值对应的是ID号,保证Key的值具有唯一性。
很多分布式数据库的架构都类似,Hubble数据库和其他分布式数据库的区别在于单独的列簇存储是特有的。理解索引结构对使用其他的数据库非常有帮助。
5)倒排索引
Hubble支持倒排索引,有些数据库不支持倒排索引,这也是我们特有的。内部存储的是JSON 的数据,JSON数据默认的是给value映射,倒排索引就是文件ID对应到关键词的映射转换为关键词到文件ID的映射。
6)涵盖索引
一般的索引是通过索引的字段找到对应数据的主键,根据索引字段找到索引数据主键,根据主键再去找到对应的数值。需要两个步骤获取到需要的数值。涵盖索引中的value是存储数值的,直接找到对应的数值,只需要一个步骤。高并发场景下,少了一个索引步骤相当并发量提升了一倍,通过索引直接定位到需要的数据,对于数据库而言非常有意义。
上面讲的是元数据的管理,元数据管理不仅仅是索引,还有表结构,表结构怎么映射、索引结构、是否有分区等等。很多元素信息都要用底层存储来支撑。如图所示是一张索引清单,这里边有几个概念简单说一下,比如局部索引,一个大表有几十亿条记录,这几十亿条全部建索引,有时候对热数据建索引冷数据就不建索引,这时候局部索引可以定义一个范围,对于新的数据建索引冷数据就不建索引。这样既节省了空间,热数据又保证了整体的性能。函数索引就是给字段加了函数的索引,这里的函数也可以是表达式。所以也叫表达式索引。哈希索引是基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
任务执行流程
从客户端访问一个临时主节点,也叫临时网关。由于Hubble是去中心化的,客户端访问的时候可能落到任何一个节点上,落到哪个节点哪个节点就是临时主节点。
临时主节点主要负责SQL解析、执行计划优化,执行分片计划,最终调度到对应的Hubble Server上,Hubble Server将部分结果合并,包括数据的扫描、分片、分布式存储,最终将结果返回客户端。如右侧图任务执行流程所示,客户端发送查询请求到临时主节点,每个节点都可以作为临时主节点,解析SQL创建执行计划,分发任务后执行并返回数据到客户端。
优化方式
在执行过程中我们从存储、计划的模式、调度的模式以及预先统计的方式几个角度去优化。存储空间可以压缩,像Snappy、gz、lzo、lz4是简单的压缩格式,我们支持这几种格式的压缩同时支持底层数据更大的压缩。我们最高的压缩能够保持1:100,在客户现场可能数据很大,但是在做到内部之后很小。为什么要做到1 :100 的压缩比是因为我们要保证数据读取时尽量减少IO,在大量分析场景下IO是致命的,所以我们把压缩比做到很大。
第一个压缩效率。第二个是底层数据压缩。举个例子:比如最简单的,比如True,False war类型的数据。一个字节是8位,true和false用一个字节来表示也就是8位,我们能够将True,False压缩到 1位,一个字节可以输入8个True,False,然后再进一步压缩。有些值不存在的话就不存,这样能够省去很大开销。
通过第一个存储方式,第二个存储的本身压缩算法,减少了整个数据的存储空间,在读取数据的时候带来了一个高效的IO。列存储可以减少随机读取,提升AP性能。内存计算把数据做的很小,虽然在内存里占一部分空间但可以快速地流动。线程调度,资源占用少,启动灵活,支持更多并发。预先统计可以提前做入库统计,减少数据提取量。
多版本并发控制模式
与大多数事务性数据库系统一样,Hubble实现了多版本并发控制(MVCC)模式。MVCC允许读者获得一个完整的信息视图,即使这些信息正在被修改。如果没有MVCC,对数据项的一致读取需要阻塞(通常使用“读锁”)同时对该数据项的写入,反之亦然。使用MVCC,即使在信息被并发事务修改时,读者也可以获得一致的信息视图。
MVCC的基本原理如图所示。在时间t1时,会话1从行r2读取,并访问行(1)的版本v1。在时间戳t2 时,另一个数据库会话2更新行(2),创建行(3)的版本v2。在t3时,会话1再次读取行(2),但因为会话2还没有提交它的更改,继续从版本v1(4)读取。在会话2提交(5)之后,会话1发出另一个select,现在从行(6)的新版本v2中读取。
Hubble可以限制了部分事务从以前版本读取数据。例如,如果一个读事务在一个写事务开始之后开始,它可能无法读取该行的原始版本,因为它可能与其他已经读取的数据或稍后将在该事务中读取的数据不一致。这可能会导致读事务“阻塞”,直到写事务提交或中止。
事务
事务的操作流程是什么?开启一个事务,我们会在事务上先打一个事务标记,目前有账号1和账号3,先写入账号2同时打一个标记,标记为事务1。再写入账号8标记为事务1,和账号2在不同的分片上。提交事务1之后,把事务1中的账号2和账号8的数据标记去掉了,也就是清理事务意向,这是整个事务流程。
1)事务-读冲突
这时候会有一些冲突,一个是读冲突,一个是写冲突以及死锁等概念,这是分布事务里面的必须要做的一件事情。事务1写入账号2。账号2会标记状态,从这个状态会检查要读取账号2,事务1是写,事务2是读,会检查事务标记。如果是等待,事务2先进入等待状态,会保证读冲突正常进行下去。
2)事务-写冲突
事务中也会有一些写冲突,写冲突操作相对来说会比读的操作会多一些步骤。写入的都是账号2这样一个数据。事务1开启做好标记后写入账号2,账号2后面也会有对应标记。事务2开始之后也会写入账号 2,检查事务1标记,如标记会在等待状态,等待事务1所有的状态清理后,事务2才会进入一个状态。
3)事务内部实现
事物内部的实现,里面标记了步骤123456 ,从1开始后端发的请求设置K1等于V1,K2等于V2,K3等于V3,网关节点收到了这样的请求,K1等于V1,K2等于V2,K3等于V3分别在三个分片上,1是发送请求;2是临时写并创建事务记录;3是临时写了K2和K3,4是提交事务;提交完事务后我们看到5返回客户端了;6是异步清除操作,从预写到提交为什么是先返回给客户再有6,两阶段提交协议,第一阶段提交完之后无需考虑第二阶段直接返回给客户,与其他分布式数据库不同,Hubble在并发事务上有自己的优势。
两阶段提交协议,第一阶段全部写完,第二阶段内部处理,内部处理保证所有事务的一致性。在并发时做两阶段提交,第二阶段提交不需要等待直接返回,我们可以做到异步的第二阶段提交。这是Hubble在并发事务上的优势。
数据分片
数据分片默认大小512兆,可以自主调节。最开始我们是参照HBase的64兆,我们发现HBase底部的region会随着数据量增加带来的开销越来越大,经过大量实验后我们将默认大小改为512兆,默认当一个空间达到1千兆后会做一个切分。在切分上有两个切分原则。第一个切分原则相当于空间切分,比如我们达到512兆就进行切分。第二个切分原则是分片中有一个分片的访问量很大,这种情况也可以触发切分,比如某个分片的压力非常大,超过1万的QPS切分,把压力转移到其他的节点,这是两个切分策略。
要保证整个数据一致性,以及宕掉一个机器的时候不会出现问题,就需要副本了。比如第一个节点挂了之后,它的副本自动会迁移到其他节点上。在写入数据时默认是保证两副本同步写入,第三副本异步写入。同步写入相当于某个节点挂了之后,在另外的节点上都有数据备份,直接对应的迁移过去,原来的数据也会直接支撑服务,这样迁移不会影响数据的一致性。
如果故障副本是Leader,剩余两副本会重新选举,并继续提供正常服务。当出现故障的副本是Follower,而非Leader时。这个分片的服务是不会受到影响,始终是可以正常提供读写服务的,因为Raft组允许Follower出现故障。
数据请求流程
数据的请求流程首先客户端连接负载均衡器,负载均衡器请求定向到可用节点,该节点是连接的入口通道节点。然后网关节点与该分片节点通信后将数据返回给网关节点,最后网关节点将所需的数据返回给客户端。
存储
如下图所示在表1中的账号1表插入一个新账号90并对应到分片的一个流程,这是整体存储的一个流程。