黄东旭解析 TiDB 的核心优势
565
2017-03-29
内容来源:http://mp.weixin.qq.com/s?__biz=MzI3NDIxNTQyOQ==&mid=2247484657&idx=2&sn=12f7249f8a9d0745248b4ff8d292b64e&chksm=eb16239bdc61aa8d1cb6ae81e18d5c5c3b84ef1da7cb8aa088f81f971ed5868af31e6a6e89ff#rd
在今日的“Think in Cloud 2017”上,我司联合创始人兼 CTO 黄东旭发表了《Cloud+TiDB:NewSQL 的云化之路》主题演讲。现奉上最新出炉的演讲实录~~ enjoy!
很高兴来到 TIC 介绍一些我们的东西,今天我会讲一些我们 PingCAP 与 UCloud 在数据库方面的一些合作。
今天我的主题叫 NewSQL 的云化之路,先简单介绍一下我自己。我基本上之前都在互联网公司,做的事情也是 Infrastructure 相关的,所以一直到现在还在一线做技术,个人擅长在分布式存储,比如 TiDB 这样的项目。
现在我们在这个大环境下,云计算也越来越普及。刚刚分享的专家说得非常好,互联网的业务就是各种变。我觉得这也是非常正常的,业务形态多种多样。包括最近这几年接入的终端也五花八门。过去十几年主要是 WEB 为代表的 PC 互联网,现在有越来越多的移动设备的接入,未来可能物联网(IOT)的兴起,使得接入互联网的终端也会越来越多。同时存储的成本持续地降低,容量也越来越大,这几个条件加上来以后,就会产生海量数据的大环境。
现在大家做应用都想着,反正存储成本这么低,我先全存下来,万一以后 AI 火了我还需要这个数据去做计算。这就催生了一个问题:数据库怎么做弹性的伸缩,或者说在一个大数据的环境下,我们关系型数据到底应该怎么样去做,未来的数据库应该是什么样子的。
第一,数据库理论基本上是跟计算机操作系统同一个时代就出来(上世纪七十年代开始,IBM 的关系型数据库理论就发表出来了),甲骨文称霸了这个行业几十年。到了现在关系型数据库仍然是多数业务的核心。
第二,对开发效率的无止境的苛求。这个也很好理解,大家总是想着我并不是一个做数据库的专家,我也并不是一个基础架构的专家,我只关心我的业务,就是说我怎么去快速地写出我的业务,这是放在第一位的,而不要老是关心我这个数据库机器的容量到底是怎么样的,我的这个机器 IO 的吞吐应该是什么样的,我该怎么去做数据库容灾、怎么做数据库扩容。其实现在我们花了大量的时间(不管是 DBA 也好还是业务的架构师也好),都在想怎么去解决这些 IaaS 层面上就应该帮你解决的事情。
第三,扩展性。其实我认为在新一代的技术软件(甚至云时代)中,扩展是现在所有的基础软件都要考虑的第一要素。当现在这个时代大家去说基础软件,你不是一个可扩展的,或者说你并不是一个分布式系统,你还是一个单机的系统,那基本上意味着你是没有办法跟上你业务的快速发展,迟早被淘汰。
所以新时代的基础软件是要有可扩展性。到现在这个环境下大家知道,包括像互联网发展得这么快,今天你的数据可能一台机器能存下,但是明年、后年呢?这个数据基本上是翻滚着往上翻。所以说到现在为止,数据库的扩展性问题其实是没有什么方案去解决的,这也是我们做 TiDB 的初衷。
现场如果大家都是程序员,或者在公司里面写过业务的话,都会有听见你的开发人员或者说业务人员抱怨 MySQL:我的数据量或者并发量大到一定程度的情况下,我到底应该怎么办?然后去跟架构师说,你这个业务应该去做分表了,要用中间件了。
业务这边其实也不管,我就说我这个业务已经使用了 MySQL,我也没法改代码,写代码的这个人已经早就离职了。还有就是 Sharding key 怎么选,如果是大家做过 MySQL 的中间件方案的话,基本都会对这个记忆犹新。就是一旦你的业务层用了 MySQL 超过单机的限制了以后,你的业务层的侵入性是非常大的。基本上所有的你的请求都要带一个 Sharding key 这样非常讨厌的东西。同时传统的基于中间件的这种数据库的扩展方案,很多像 JOIN 这样一些稍微复杂一点的查询,你就没法做了,或者多个纬度的索引也没法做。比如说我的业务明明是一个很简单的关联表的查询,但是现在你一旦做了分表和中间件做分片了以后就没法做了。
以上几点都是大家在业务之中,过去 10 年都是见怪不怪,大家都被虐到默认就认为不应该有什么新的办法或者说不应该有其他什么方案去完美地解决这个问题,我只能把数据库的扩展性问题绕开。所以我们就在想,到底关系型数据库方案进入到下一个时代应该是一个什么样子的。
在 2012 年底,Google 发表了一篇论文 Spanner。其实大家如果熟悉数据库圈或者说对 Google 的基础软件架构比较了解的话,可能有听说过。包括 Google 两个月前,Google Cloud Spanner 第一次登录 Google 的云平台,成为了世界上第一个经过海量数据验证的分布式关系型数据库,在 Google Cloud 上去给大家提供服务。
杨总刚才也介绍了一下,其实 TiDB 这个项目就是 Google 内部用的新一代分布式关系型数据库系统的开源实现。
TiDB 与在 Google 内部做项目可能不太一样,因为我们本身是一个社区的项目,或者说本身是我们去做的这么一个开源的 MySQL 协议的数据库,MySQL 协议是放在第一位。虽然整个 TiDB 项目没有一行 MySQL 的代码(因为整个全部重写的),但是在业务层看上去,你就可以认为是一个单机 MySQL,兼容性极高,同时你也几乎不需要去做任何的 work around,你该写事务就写事务,你该用复杂查询就用复杂查询,我不需要再对我的业务方做任何的妥协,这么一个理想中的数据库,至少我在做这个项目的时候初心就是大家不要再去关心数据库的容量问题了,你就认为你有一个无穷大的 MySQL,这样你写起业务来就会好用很多。整个背后的数据库的理论模型是 Google 的这个模型。
上图是 TiDB 跟传统的 MySQL 分布式解决方案的一些对比,如果你是使用传统的 MySQL 的中间件或者说分库分表的方案遇到问题,那恭喜你,你现在有一个新的东西可以选了。
如果你用 MySQL 的中间件的话,你不能做跨分片的分布事务,而 TiDB 是支持的。弹性的水平伸缩,比如说我现在的数据库集群大概是三台,我要扩到五台怎么办?这在传统的 MySQL DBA 的中间件领域里面,基本上是一个 DBA 的恶梦。我之前是在豌豆荚(一个快速成长的互联网公司),曾经有一段时间维护他们的 MySQL 的集群,从 16 个分片要去做一次扩容,扩到 32 个节点,DBA 整整提前演练了一个月,上线上了一个礼拜,而且基本上都是大半夜上线,大家可想而知多么痛苦。然而 TiDB 的水平扩展,完全不需要人来扩展,你就直接加机器就好了。
另外传统的数据库中间件并没有办法去做复杂查询,就是你可以认为数据库的中间件只是简单地做了一层路由,比如说一个用户的请求过来,我根据一些特征把这个请求转发到底层的某个 MySQL 的实例上,这就做到了分区的或者说路由的作用。
但是在 TiDB 这边,我们是完整地重写了整个优化器、解析器、执行器等等,把它变成了一个高性能的分布式计算框架,这个其实并不是所有的中间件都能做到的,这个说得太谦虚了,其实是目前没有别的中间件能做到。这就是为什么在很多的复杂查询场景下,我们能比 MySQL 的优化器,或者说在一些复杂查询的性能上,比 MySQL 快 10 倍、100 倍、1000 倍这样的量级,就是因为 TiDB 是从头开始设计的。
然后跨数据中心高可用。这个其实是 Google 的 Spanner 系统天生具备的一个非常强的特性,在 Google 内部从来也没有听说过 Google 因为某个数据中心掉电了、机房的机架掉电了,导致某某业务不可用了(很少很少),基本上从来没有听说过。因为 Google 的 Spanner 在技术层面上对数据的分布还有高可用性做了非常多的工作,包括利用了一些算法,比如 Paxos 来保证数据在不同的数据中心之间的强一致性,这里也有一些非常复杂、非常前沿的计算机科学的一些进展,然后我们在 Raft 之上实现了完全无人工介入的高可用。
我们的一个线上的客户非常有意思,前几天他的一台服务器,跑着一个 TiDB 的数据库集群,其中有一台服务器的磁盘坏了。在过去这个机器物理发生了故障,对于 DBA 来说他马上就得去处理,因为这块儿分片的数据可能就没法用了。但是对方在用 TiDB 的集群的 DBA,愣是过了三天才发现我这台机器好像坏了,因为他的业务层完全没有受到任何影响。所以 TiDB 还是一个能让 DBA 晚上能睡好觉的好东西。当然业务层的兼容就不用说了,基本上连复杂查询都支持了,那基本上 90% 以上的 MySQL 的语句都是支持的。
简单来说 TiDB 就是一个 unlimited 的 MySQL,它虽然是完全彻底的分布式的方案,但是在用户的理解中,你可以认为它就是一个 MySQL,只是无穷大。
今天的主题其实是 Cloud,刚才王总这边也介绍了 Cloud-native,我就不赘述了。其实我们的目标就是做一个 Cloud-native 的数据库,因为我个人是相信未来一切的东西都会跑在云上(不管是公有云还是私有云),在云端是一切基础软件最后的归宿。
我们在这边跟云整合上做了很多的工作,我们其实选择了 Kubernetes 作为上云的一个载体,晚些我会简单介绍一下在 UCloud 这边我们上云的一个技术的详细方案。Kubernetes 其实可以认为是一个数据中心的操作系统,是在 Google 发表的一个开源项目,是作为 Google 内部的 Borg 一个后继吧,目前来说在 GitHub 上是一个非常火的 DCOS 的项目,它是自动的集群调度跟服务编排的一个框架。
但是其实如果你想,当你有了这么一个 DCOS 的时候,你的应用层整个会被分裂成四个阵营,大家仔细想想我在后端所有跑的业务都能被归类成这四个分类中的一种:
阵营一:Stateless Applications。我的业务本身无状态,比如我的 webApp;比如说,我的 API Gateway 本身是无状态的,你只需要任意启容器,它其实对于调度器来说是非常好调度和管理的。
阵营二:Single point stateful applications。单点的有状态的服务。比如说单节点的 MySQL,因为数据、数据库是有状态的,但是它并不是一个分布式的数据库,所以它是一个单点的 application。
阵营三:Static distributed applicaytions。静态的分布式应用,这个也很好理解。比如说类似于集群的分布式的配置管理服务(比如说ETCD这样的项目)。
阵营四:Clustered applications。对于 DCOS 来说最难搞的是集群应用,比如说像数据库集群,这个其实是一个非常困难的东西。
其实在 Kubernetes 里面,对于这种单点单状态的服务的话,可以使用类似于像 Static configration 和 StatefulSet 这种机制来做。对于静态的分布式应用的话,也是可以用 StatefulSet 来做。
我今天比较强调的是 Clustered 的 App。比如说我们是一个关系型的分布式数据库,又带有状态。因为数据库嘛本身会带有状态。第二个就是他又是一个集群。这种时候说对于容器来说就是非常难以调度的,因为它带有领域知识,并不是说我的这边节点宕机,它随便找一台机器把我的进程启起来就完了。比如说我这台宕机以后,我需要通知我的集群让这个节点下线,或者说我这个数据要做一个迁移,这种情况我们选择的技术是 CoreOS 出品的一个叫 Operator 的东西。
Operator 的概念其实也非常简单,就是把我们的系统的运维领域知识放到我们的软件里面,让 Kubernetes 做集群调动的时候,然后他因为不知道我们的这个数据库或者说这些状态应该怎么去搞,所以中间通过一个叫 Operator 的桥梁把它连接起来。然后 Operator 这个东西其实是我们跟 CoreOS 做的一些研发工作。
TiDB 的 Operator 其实就是基于 CoreOS 的 Operator 方案去做的。Kubernetes 本身提供了一个叫做 Third Party Resource 服务,我们相当于去实现了它。在 Operator 里面它可以在整个 Kubernetes 集群上创建新的 TiDB 集群,滚动更新等复杂工作。所以我们的数据库能够在云上做到什么体验呢?
你根本不用去关心这个数据库的版本升级、运维这种各种各样的问题,全部都在业务层完全无感知的状态下去做,滚动更新、调度、扩容、缩容都是通过这个 Operator 机制来做。
为什么我们选择 Operator 呢?首先我们要选择的话肯定要选对 Kubernetes 依赖和侵入性小的方案。因为 Operator 这个方案对于像调度器或者是 Kubernetes 本身的依赖并不是太重,我们可以通过一些很简单的 hack 就把它移植到 Mesos 或者 Docker swarm,也就是说大量的代码可以复用。
另一方面现在目前来说 Kubernetes 提供的带状态服务调度方案,不管是 PV 还是 StatefulSet,都没有很好的解决问题,毕竟数据库的调度并不是 Kubernetes 擅长的。
在 TiDB 上云的过程中,本质上来说 UCloud 提供了 IaaS 层,我们在上面划出了一大块计算资源,把它交给 Kubernetes,Kubernetes 这边通过 Operator 对不同的用户在前面创建 UCloud 的 ULB,同时隔离不同用户集群之间的物理资源,比如说自动的创建集群、销毁集群、扩容、缩容这样的工作,其实都是由 Kubernetes 和 Operator 一起去协作的。
在 UCloud 上面,对于 TiDB 来说,可以直接的快速创建、扩展甚至是收缩。其实大家在用 MySQL 的时候,基本上很少见过有哪个方案能够去做平滑的缩容,这在过去对 DBA 来说是一个巨大的难题。但是这个需求又是存在的,比如说像一些电商,对于电商的场景来说,我可能一个 618 或者是双 11 大促,数据库就撑不住了。我的吞吐要扩展 10 倍,但是数据库层面上我大促结束了以后还要缩回来,这个时候对于 DBA 来说考验就太大了。
第二,TiDB 是跟 MySQL 有一个协议层是完全兼容的,比如说你的业务层现在用的是 MySQL 无所谓,但是预计三个月以后这个数据量可能就快撑不住了,这个时候可以直接简单的把 TiDB 作为 MySQL 的 Slave 挂上去,实时的做到数据同步,到你的业务快不行的时候,你的业务层一行代码都不用改,直接改个 IP,把主从给切换一下就上线了,完全解决了你的扩展性和数据量或者是一致性高可用的问题。
TiDB 对 MySQL 标准的官方备份格式完全兼容,这个也是我们选择了拥抱 MySQ L社区的必备工作。
上图是一些 benchmark。其实这个数字不重要,重要的是下面这个图:
TiDB 做到了一个事情,我在跑 benchmark 的过程中通过简单的添加机器,添加物理节点,系统的吞吐做到了线性的提升。这在单机的不管是 MySQL 还是 *** 都是没有办法做到的。
Demo Time
这是 TiDB 在 UCloud 接口上的水平伸缩特性演示视频。
大家可以看到,这个是我们在 UCloud 上面的产品界面,我现在创建了一个集群,三个副本。现在 UCloud 在调用我们的接口来去创建集群。我们集群建立好了,便会自动启动 TiDB 的默认监控。
我们看一下现在的 TiDB 的执行情况,是一个新的集群,因为 TiDB 里面我们会把很多集群的状态暴露给用户,包括 QPS、TPS、各种语句类型等等。现在连接一下数据库体验一下,注意我们直接用 MySQL 的命令行客户端去连接到数据库上。所以你在业务层根本不用改代码。这是我在测试机器上放了一个 MySQL 的备份文件,存放了一些数据,这里创建了一张表,直接用 MySQL 的客户端,大概几万条数据,导进去很快。现在是三个节点的 TiDB 的集群,然后可以试着执行一些任务,大家可以想象我在敲键盘,一万条数据的一张表,当然你可以写一些复杂的程序。
为了表明我们是一个纯正的分布式 SQL 数据库,开始写一些比较复杂的语句。现在是三个节点的集群,我发现我的业务快不够了,数据量快存在不下了,这个时候我要扩容,大家看到红色的是 3,表示现在存储节点只有 3 个物理机,我修改一下规模,我想扩到 5 台,这个时候会发生什么?什么都不会发生,因为你什么都不用改,业务也在没有感知的情况下,容量在这边 105 G,容量和吞吐就上去了。
所以,下一代的关系型数据库是什么样?就是这样的。
当然对于一个分布式数据库来说,有适合场景,也有不适合的场景。其实对于任何东西都是这样的。
首先,比如当你的业务写入量特别大的时候,我们的数据库是支持自生 ID 的,自生 ID 是单机数据库历史残留下来的一个糟粕一样的东西,当你的并发吞吐特别大的时候,自生 ID 会成为你整个系统的瓶颈。
第二,不适合秒杀。我们的数据库,秒杀你可以在前面做 cache、可以做队列,但是所有的流量打到数据库层面上,并不是很好的设计。
比较适合的场景是:
第一,如果你的 MySQL 的容量出现了单机瓶颈,或者说你的业务遇到了瓶颈,急需扩容的时候。
第二,你的读写的分布相对平均,比如说像很多电商、社交、游戏这样的海量且离散数据的读取和写入。
第三,你有并发事务的要求,我需要做 transaction,同时绝大多数的跨行事务冲突率并不高。反面的极端场景就是秒杀,秒杀冲突就非常高,因为大家都要去修改同一个商品的库存。
第四,当你有比较实时的复杂性的查询需求,这个时候用 TiDB 也是一个比较好的方案。
简单总结一下,大家可以认为 TiDB 就是一个 100% 的分布式 MySQL 和 80% 的分布式的分析型数据库,融合在一起。让大家不用为很多数据库上面的事情去烦恼,这是我们做这个项目的初心。谢谢大家!
延展阅读
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。