【编者按】TiDB 是国内 PingCAP 团队开发的一个分布式 SQL 数据库。其灵感来自于 Google 的 F1,TiDB 支持包括传统 RDBMS 和 NoSQL 的特性。在国内ITOM 管理平台OneAPM 举办的技术公开课中,TiDB的高级工程师刘奇从HBase特性、TiDB的优势和系统架构等方面进行了详细阐述。以下为演讲整理:

HBase简介

众所周知,在SQL方面处于顶级的有两个公司,一个是Oracle,他们已经积累了大量的经验,另一个是谷歌,谷歌 F1在2012年发布了一篇论文,个人认为它是全球最优秀的SQL OLTP数据库。

1978年左右,数据库刚刚发展时出现了SQL RDBMS。2000年左右,国内开始流行互联网,互联网对Oracle数据库也产生较大的冲击。现在,传统的数据库大部分是集中在传统领域,互联网方面用得比较多的是MySQL,其次HBase等 NoSQL 也吸引了大量的用户。

为什么会出现NoSQL?最开始所有人都用SQL Database,那时比较高端有Oracle,开源的还有MySQL、PostgreSQL。可是随着业务的迅速发展,数据库成为了瓶颈,于是促使了NoSQL的诞生,NoSQL将Scale放在第一位。如果业务快速发展,扩容会成为亟待解决的首要问题。这时,大多数人会选择放弃事务一致性。什么是一致性?比如使用微信时,如果我加你为好友,这是一个双向关系,对应到数据库中至少是两个操作,第一是在好友列表里把你加进来,第二个是你的好友列表里把我加进去。如果这两个列表的数据库放在不同的机器上,就需要保证一致性。否则可能会出现我是你的好友,但你的好友中却找不到我的这种情况。但这中间可能会出现多种情况,比如我把你加为好友,然后修改数据的时候Crush掉了,这个时候传统方案是会引入一个消息队列,有的还需要做一些补偿,这些问题在NoSQL里处理起来相对麻烦。

国内最大的HBase使用者是小米公司,有几个HBase的Committer,所以经过一些修改后可以支持分布式事务,于是能够解决之前的问题。为什么在面临诸多选择时,小米会选择HBase呢?就目前情况来说,主要还是技术选型和人才储备上的考虑。MongoDB大家应该不陌生,但用到一定程度后,总会出现各种问题,甚至有文章呼吁大家放弃MongoDB。但所有数据库都不是“十全十美”的,没有最好,选择最适合的尤为重要。

很多时候产品都有其特性,在满足其特性或者规格的情况下,使用起来可能非常顺手,否则十之八九都遇到各种麻烦。比如小米使用HBase就非常顺手,但其他的公司则不一定。道理很简单,如果不熟悉其使用场景,也不知道在相应场景下配什么参数,所以会出现各种各样的问题。

图片描述

事实上,HBase有非常好的特性,目前在小米公司可以每秒跑一百万OPS,最近Pinterest公布他们的HBase每秒可以跑三百万个OPS,这个数量级可以远超很多互联网公司。HBase在读写一致性方面非常出色,有很好的自动Scale的能力,通过Block Cache和Bloom Filters可以很好的解决查询问题,是否在磁盘上也可以通过Bloom Filters来判定。

另一方面,Oracle把一部分逻辑会放在CPU/硬件里,对应的HBase也会把一部分逻辑下推到对应的RegionServer 上。对于一个分布系统来说,如果需要查询一个条件,可以直接把这个简单调节推到对应的RegionServer上执行。再比如求和运算,现在有一百亿数据,甚至一千亿条数据,分布在10个节点上,最快的求和方法是让所有节点同时运算,将这个条件下推得到所有对应数据的和,最后收集到10个数据的和即可。其实还可以继续往下推,这是比较复杂的数据库优化技术,实际情况还会更复杂。这在 HBase 里面依赖 Coprocessor 来实现。

大家应该对MVCC比较熟悉,也就是多版本,它的优点在于可以多次读取而不会block。然后还有一个很好的特性,假设你用的Database,MVCC在你没有做compaction之前可以回到任何时间的数据。现在云服务上也可以每隔半小时做一次快照,实际上如果使用MVCC回到任意一秒的话,可以完全不需要快照。

TiDB的优势

下面再介绍一下我们的产品 TiDB,Ti是元素周期表里的元素。大家如果了解我们团队的程序员,就知道他们都比较 Geek,取名字要么在希腊神话里选一个神的名字,或者在数学里找一个希腊字母, 但是看了一圈,好坑都已经被占上了。于是,我们在化学元素周期表里找了一个金属作为项目名称,对于Database而言,它必须是高速稳定的,刚好钛金属有很强的防腐蚀性,所以选择了钛(Ti)。

图片描述

因为TiDB的目标是谷歌F1,所以自然会满足以上特性。首先是可以满足分布式一致,也就是说对于应用来说,不用关心后面分成多少个机器,事务的一致性是必须保证的,比如我们之前提到的A关注B,两个互相加好友或者转帐,可以直接利用一条SQL搞定,而无需担心中间过程。另外一个特性是兼容MySQL协议,国内大概有70% 的互联网公司都在使用MySQL,为了考虑大家的迁移成本,我们会兼容MySQL协议。同时,由于已经很多APP在MySQL上运行,为我们提供了充足的测试样本。TiDB的测试有五百多万个,每次提交一行代码时,后面大概有6个机器并行地跑Test,五百多万Test所需时间大约是十分钟。为了照顾各种引擎爱好者,我们还支持了LevelDB 、RocksDB、LMDB、BoltDB等。TiDB主要是采用 Go 语言开发的,其代码简单、易于理解,而且性能非常高。

系统架构

图片描述

任何用MySQL协议写的程序都可以直接使用TiDB,其中间是MySQL协议相关的内容,再往下是SQL Layer。其次是事务KV层,这正是F1和Spanner构造得最为精密的地方。最底层的构造是从KV开始,在KV基础上架一个分布式的KV层用于支持事务,然后再让SQL语句直接映射到KV层上。

图片描述

接下来,向大家介绍 现阶段 TiDB 使用的分布式事务是如何在HBase上实现的,早期版本中,我们参考的是 Google 的 Percolator 的模型。首先假设有一个Client,先为其分配一个 Timestamp,在Google论文中叫做Time Oracle,用来分配时间戳。分配之后可以做读写操作,根据时间戳进行快照读。最后提交之前要先Prepare,Prepare的时候会检测是否冲突,最后提交时会得到Commit,如果整个过程没有任何冲突就可以提交。

图片描述

上图代表了一个实例,最初帐户情况是Bob有10美金,而Joe有5美金。前面的数字代表其版本,当前是第6个版本,指向的是第5个版本,为10美金,Joe是2美金。

图片描述

假设Bob要转4美金给Joe。第一步,要先转出去4美金,10美金变成6美金,由于被扣掉4美金,然后会标注一下自己是主锁。

图片描述

Joe当前是第7个版本,因为他得到了4美金,所以余额变成了6美金,同时标记自己指向另外一个主锁Bob。

图片描述

到第八个版本时,主锁会指向现在的7,这时可以把主锁删掉。如果访问的时候发现主锁被删除,那么主锁冲突已不存在,可以进行提交。同时,它会把自己的锁删掉,中间还有一些其它的清理过程。

图片描述

整个事务模型中会有单点,从Time Oracle分配一个时间戳,单点决定了整个系统的性能。Google论文里有一个对应描述,可以跑到两百万每秒。因为事务开始和结束的时候都需要取一个Timestamp,所以他们最快读写事务的速度是一百万每秒,他们已经在论文中实现。实际上,现在有更好的方式可以提高速度,如HLC和一些Time Oracle的改进算法。

图片描述

关于Spanner,我们重点参考对象是谷歌Spanner和F1。由于Spanner高度依赖于时钟,所以谷歌有一套原子钟和GPS时钟,GPS信号可以给出地理位置和时间。为什么需要原子钟呢?由于GPS时钟特别容易受到干扰,比如天气恶劣时GPS时钟就不能运行,而原子钟仍然适用。

图片描述

上图是谷歌F1的一些信息,其中单独标记了谷歌F1的这篇论文,大家有兴趣的话不妨细读一番,目前整个TiDB所做的都是在实现这篇论文。假设有一千亿数据,你现在要给某一列加索引时,在传统数据库上应该如何操作?比如说在分布式环境下,你用MySQL给一列添加一个索引,这几乎很难实现,而且还必须保证index的一致性。更多细节请参考论文。

图片描述

TiDB是如何从SQL迁移到KV上的呢?由基础知识可知,传统的 RDBMS数据库底下一般是一个B-Tree。对于分布式关系型数据库,站在更上层一点看,比如谷歌的F1,数据库底层都是KV层,都在KV层逻辑下操作。如果有一个User Table,在TiDB里假设你的Table的结构是由uid、name和email构成。在TiDB里有一个隐藏列叫做RowID,所有的操作包括行锁都是锁的RowID。假设RowID是1,uid是XX,Name是Bob,Email是bob@Email.com,这都属于元信息。即便你的Column name很长,但最后在数据库里存储的是原信息。在TiDB中, 每一列都有唯一的UID。

假设Table的ID是1,uid的 ID 是2,name的ID是3,email的ID是4。在数据库中存储为一个KV结构,然后对TableID、RowID 、ColumnID进行重新编码,直接将这个表的一行切成4个KV。这时候如果进行select,Email等于某一个值的话,于是可以直接取出来相应的值,速度非常快。

兼容MySQL

TiDB对MySQL协议有很好的兼容性。有一些比较知名的MySQL应用和管理工具,比如WordPress、PhpMyAdmin, MySQL Workbench,都可以直接基于TiDB运行。而且数据可以无限扩展,不再是单机数据库。其次,TiDB还兼容各种ORM,比如XORM、Beego ORM等,能够支持很多MySQL的应用。每一次代码更新,这些ORM Test会自动运行一次,从而保证与MySQL的兼容性,虽然还有一些比较细微的特性暂时没有支持。现在已经支持异步的 Schema 变更,对于 DDL 操作,不会阻塞线上的业务。

关于社区

目前 TiDB 完全开源在Github上面。开源和开放的概念是两回事,很多大公司,所谓的开源只是把代码上传一下,国内比较知名的案例也挺多的,大家知道很多项目都已经放弃了维护。但是我们是打算完全以一个开放的心态来做整个事情,全部的代码,全部的讨论, Code Review,Bug Tracking,Roadmap 都是开源的,毕竟通用的分布式 OLTP 关系型数据库是一个非常前沿而且极端重要的领域,未来是云上的 DBaaS 的重要组成部分,但是在这块目前整个技术社区,即使全球来看都没有一个太成熟开源解决方案,TiDB也目前也处于早期,从架构上来看,我们将 SQL 层和 KV 层做了很彻底的分离,这也是我们希望更多开发者能根据自己的需要更方便的进行定制,我们也想得很清楚,依靠某一家公司,或者某几个人的力量是不够的,我们 PingCAP 只是将这一把火点起来,将框架搭好,制定好透明和公平的规则,吸引更多的合作公司和独立开发者,一起将 TiDB 做成中国第一个世界顶级的开源项目,实现共赢。

好的项目可以由社区进行推动,就比如HBase,HBase不属于任何一个公司,但是社区一直推动它进步。目前我们在GitHub状态是有3200+的Star,有32个Contributors,算是开了一个好头,非常感谢大家,希望大家都能参与进来。


(作者:OneAPM工程师 责编/仲浩)

Logo

开源、云原生的融合云平台

更多推荐