引言畅想一下,未来的服务都跑在云端,任何的服务资源都可以像水电煤一样按需选购从IaaS层的容器/虚拟机,到PaaS层的数据库,缓存和计算单元,再到SaaS层的不同类型的应用,我们只需要根据自身业务特点进行资源选配,再也不用担心应用服务支撑不住高速的业务增长,因为在云上一切都是弹性伸缩的,下面我们就来聊聊关于云数据库是一种全新的数据库技术?接下来我们就一起去了解一下吧!

云数据库是一种全新的数据库技术(云时代数据库的核心特点)

云数据库是一种全新的数据库技术

引言

最近几年,随着云计算相关技术的发展,各种不同类型的云层出不穷,服务越来越多不同类型的企业业务,传统企业也渐渐开始探索上云的道路。在云上,作为业务最核心的数据库,相比之前的传统方案会有哪些变化呢?在正式聊云时代的数据库特点之前,我们需要了解一下目前云时代架构发生的变化。

畅想一下,未来的服务都跑在云端,任何的服务资源都可以像水电煤一样按需选购。从IaaS层的容器/虚拟机,到PaaS层的数据库,缓存和计算单元,再到SaaS层的不同类型的应用,我们只需要根据自身业务特点进行资源选配,再也不用担心应用服务支撑不住高速的业务增长,因为在云上一切都是弹性伸缩的。

有了可靠的基础软件架构,我们就可以把更多精力放到新业务的探索,新模式的创新,就有可能产生更多不一样的新场景,从而催生更强大能力的云端服务,这是一件多么cool的事情。

当然,理想要一步一步实现,未来的基础软件栈到底会怎样呢?社区在这方面正在进行积极地探索,其中最有代表性的就是基于容器(以Docker为代表)的虚拟化技术和微服务(microservice)。

在云时代,一切都应该是可伸缩的,使用 k8s(Kubernetes)在保证资源平衡的前提下,通过Docker部署我们依托于容器的微服务模块,我们不用关心服务到底跑在哪里,只需要关心我们需要多少服务资源。Docker提供了极大的便利性,一次构建,到处运行,我们可以很好地解决开发、测试和上线的环境一致性问题。(如果不能很好地保证测试和实际上线环境的一致性,则很有可能需要花费远超过开发的时间去发现和修复问题。)

k8s 更是在 Docker 构建的基础上增加了更多的云特性,包括Docker的升级,高可用和弹性伸缩等等。 关于Docker/k8s相关的讨论已经很多了,因为时间关系,关于具体的细节就不再展开。我们只需要了解,有了它,可以很轻松地解决服务的安装和部署。

下面再聊聊微服务,微服务将一个服务拆分成相对独立的更小的子服务单元,不同的子服务单元之间通过统一的接口 (HTTP/RPC等)进行数据交互。

相比于传统的解决方案,这种架构有很多的优点。

  1. 更好的开发效率和可维护性。微服务将一个单独的服务进行更细力度的拆分,每一个子服务单元专注于更小的功能模块,可以更好地根据业务建立对应的数据模型,降低复杂度,使得开发变得更轻松,维护和部署变得更加友好。

  2. 更好的可扩展性。每个不同的子服务单元相互独立,彼此之间没有任何依赖,所以可以根据业务的具体需要,灵活地部署多个子服务单元进行水平扩展。

  3. 更强的容错性。当其中一个子服务出现故障的时候,可以通过辅助的负载均衡工具,自动路由到其他的子服务,不会影响整体服务的可用性。

当然,微服务也不是一个银弹,相对来说,这种方案会使整体系统的设计更加复杂,同时也加大了网络的延迟,对整个系统测试的复杂度也会更高。

Docker提供的隔离型和可移植性,与微服务是一种天然的契合,微服务将整个软件进行拆分和解耦,而通过Docker/k8s可以很自然地做到独立的部署,高可用和容错性,似乎一切都可以完美地运转起来。但是真的是这样么?我们是不是忽略了什么?

是的,我们在讨论前面的问题的时候忽略了一个很重要的东西:状态。

从整个技术发展的角度来看,微服务是一个非常有意义的探索。每个人都期望着每个微服务的子服务都是无状态的,这样我可以自由地启停和伸缩,没有任何的心智负担,但是现实的业务情况是什么样的呢?

比如一个电商网站,用户正在下单购买一件商品,此时平台是通过订单子服务的A应用来提供服务的,突然,因为机器故障,订单子服务的A应用不可用了,改由订单子服务的B应用提供服务,那么它是必须要知道刚才用户的订单信息的,否则正在访问自己订单页面的用户会发现自己的订单信息突然不见了。

虽然我们尽量想把子服务设计成无状态的,但是很多时候状态都是不可避免的,我们不得不通过存储层保存状态,业界最主要的还是各种数据库,包括RDBMS和NoSQL,比如使用MySQL、MongoDB、HBase、Cassandra等,特别是有些场景还要考虑数据一致性问题的时候,更加重了对存储层的依赖。

由此可见,云计算时代系统的架构发生了巨大的变化,这一方面为用户提供了更优秀的特性,另一方面也对云计算的组件提出了更高的要求。数据库作为云计算最基础的组件之一,也需要适应这种架构的变化。(这里我们主要关注 SQL 数据库,云时代的数据库以下简称云数据库。)

那么云数据库主要有一些什么样的特点呢?我认为主要有以下几点。

弹性伸缩

传统的数据库方案,常见的会选用Oracle, MySQL,PostgreSQL。在云时代,数据量的规模有爆发性的增长,传统的数据库很容易遇到单机的存储瓶颈,不得不选用一些集群方案,常见的比如 Oracle RAC、 MySQL Sharding等,而这些集群方案或多或少都有一些不令人满意的地方。

比如说,Oracle RAC通过共享存储的硬件方案解决集群问题,这种方式基本上只能通过停机换用更大的共享内存硬件来解决扩容问题,RAC节点过多会带来更多的并发问题,同样也会带来更高的成本。

以MySQL Sharding为代表的数据分片方案,很多时候不得不提前对数据量进行规划,把扩容作为很重要的一个计划来做,从DBA到运维到测试到开发人员,很早之前就要做相关的准备工作,真正扩容的时候,为了保证数据安全,经常会选择停服务来保证没有新的数据写入,新的分片数据同步后还要做数据的一致性校验。

当然业界大公司有足够雄厚的技术实力,可以采用更复杂的方案,将扩容停机时间尽量缩短(但是很难缩减到0),但是对于大部分中小互联网公司和传统企业,依然无法避免较长时间的停服务。

在云时代,理想中所有的资源都是根据用户业务需求按需分配的,服务器资源,应用容器资源,当然也包括数据库资源。添加或者减少新的数据库资源,完全就像日常吃饭那样稀疏平常,甚至用户基本感知不到。

比如作为一个电商用户,在双11促销活动之前,可以通过增加数据库节点的方式,扩大更多的资源池,用来部署相应的容器服务,当活动结束之后,再将多余的资源移除去支持其他的服务,这样可以极大地提高资源的利用率,同样可以弹性地支撑各种峰值业务。

高可用

传统的MySQL方案,数据复制的时候默认采用异步的方式,对于一个写入的请求,主库写入成功后就会返回成功信息给客户端,但是这个时候数据可能还没有同步给从库,一旦主库这个时候挂掉了,启动从库的时候就会有丢失数据的风险。

当然,也有人会选择半同步的复制方式,这种方式在正常情况下是同步的,但是在遇到数据压力比较大的时候,依然会退化为异步的方式,所以本质上来说,同样有丢失数据的风险。其他也有一些多主的同步方案,比如在应用层做数据同步,但是这种方式一是需要应用层的配合,二是在对网络超时的处理非常复杂,增加心智负担。

在云时代,因为所有的数据库资源都是分布式存储的,每个数据库节点出现问题都是很正常的事情,所以就必须有一种可以实现数据一致性的数据复制方式来保证服务的高可用,业界给出的答案就是:Paxos/Raft(关于Paxos和Raft的实现细节我们不在这里展开)。

PingCAP在做的TiDB就是选择了Raft协议,Raft协议看起来更像是一个多副本的自适应的主从复制协议,对于每次写请求,Raft都会保证大多数写成功才会返回客户端,即使Raft Group的Leader挂掉了,在一个有限的时间范围内,会很快地选出一个新的Leader出来,继续提供服务。

同样,对于一个3副本的Raft Group,只要2个写入成功,就可以保证成功,而大多数情况下,最先写入成功的往往是与Leader网络情况最好的那个副本,所以这种Majority写的方式,可以很自然地选择速度最快的副本进行数据同步复制。另外,Raft协议本身支持Config Change,增加一个新的节点,可以很容易地做副本数据分布的变更,而不需要停止任何服务。

同样,在云时代,数据库的DDL操作也会是一个非常有趣的事情。以一个常见的Add Column操作为例,在表规模已经很大的情况下,在传统的实现方案中,比较有参考意义的是,通过一些工具,创建类似表级别的触发器,将原表的数据同步到一个新的临时表中,当数据追平的时候,再进行一个锁表操作,将临时表命名为原表,这样一个Add Column操作就完成了。

但是在云时代,分布式的数据存储方式决定了这种方案很难实现,因为每个数据库节点很难保证Schema状态变更的一致性,而且当数据规模增长到几十亿,几百亿甚至更多的时候,很短的阻塞时间都有可能会导致很大的负载压力变化,所以DDL操作必须是保证无阻塞的在线操作。值得欣慰的是,Google的F1给我们提供了很好的实现参考,TiDB即是根据F1的启发进行的研发,感兴趣的同学可以看下相关的内容。

易用透明

我们可以将云数据库想象成一个提供无限大容量的数据库,传统数据库遇到单机数据存储瓶颈的问题将不复存在。已有的程序基本上不怎么需要修改已有的代码,就可以很自然地接入到云数据库中来获得无限Scale的能力。增减数据库节点,或者节点的故障恢复,对于应用层来说完全透明。另外,云数据库的监控、运维、部署、备份等等操作都可以在云端通过高效的自动化工具来自动完成,极大地降低了运维成本。

多租户

云数据库本身应该是可以弹性伸缩的,所以很自然的,从资源利用率的角度来考虑,多个不同用户的数据库服务底层会跑在一个共享的云数据库中。因此多租户技术会成为云数据库的标配。但是这里面就有一个不得不面对的问题,如何做到不同用户的隔离性?

用户数据隔离是相对比较容易的,比如还是以电商用户(这里说的是电商企业,不是顾客客户)为例,每个用户都有一个唯一的ID,这样在云数据库的底层存储中,可以保证每个用户数据都带有自己ID前缀,用户登陆进来的时候可以根据这个前缀规则,获取他对应的数据,同时他看不到其他用户的数据。

在一个真实的多租户环境下面,纯粹的数据隔离往往是不够的,你还需要做到资源公平性的隔离。比如有的用户写一个SQL,这个SQL没有做优化,主要做的事情是一个全表描扫,这个表的数据量特别特别大,这样他会吃掉很多的CPU、Memory、IO等资源,导致其他用户很轻量级的SQL操作都可能会变得很慢,影响到其他用户实际的体验。

那么针对这种情况怎么做隔离?与此类似的还有,网络带宽怎么做隔离?大家都是跑在一个云数据库上面的,如果一个用户存放的数据特别大,他把带宽都吃掉了,别人就显得非常慢了。

还有一种情况,如果我本身作为一个租户,内部又怎么做隔离,大家知道 MySQL可以建很多Database,不同的Database给不同的团队来用,那么他们之间内部隔离又怎么做,这个问题就进一步更加复杂了。

目前来讲没有特别好的方法,在一个分布式的环境下面去做很好的隔离,有两个方向可以考虑:

第一种是最简单也是有效的方法,制定一些规则,把某些用户特别大的数据库表迁移到独享的服务器节点上面,这样就不会影响其他用户的服务,但是这里面就涉及到定制化的事情了,本身理念其实与云数据库并不相符。

第二种就是依靠统计信息,做资源隔离和调度,但是这里面对技术的要求就比较高了。因为云数据库是分布式的,所以一般的统计都要横跨很多的机器,因为网络原因,不可能做到完全准确的统计,所有统计都是有延迟的。

比如说对于某个用户,现在统计到的流量是1个G,他可能突然就有一次峰值的网络访问,可能下一次统计消耗的流量是5个G(这里面只是举例说明问题),如果你给他流量限制是1个G,中间统计的间隔是多少比较合适,如果间隔比较小,那么这个对整个系统的压力就比较大,可能影响正常的用户SQL访问,另外本身这个流量限制的系统也是很复杂的系统。

调度算法一直是整个分布式系统领域很困难的一个问题,如何做到隔离性和公平调度也是未来云数据库非常有挑战的一个事情。

低成本

低成本应该是云时代基础设施最明显的特点。首先,云数据库的高可用和容错能力,使得我们不再需要昂贵的硬件设备,只需要普通的X86服务器就可以提供服务。然后,受益于Docker的虚拟化技术,使得不同类型的应用容器可以跑在同一个物理机上,这样可以极大地提高资源的利用率。

其次,多租户的支持,使得不同的用户可以共用一套底层的数据库存储系统,在数据库层面再一次提高了资源的利用效率。再次,云数据库的自动化运维工具,降低了整个核心数据库的运维成本。最后,云数据库资源是按需分配的,用户完全可以根据自身的业务特点,选购合适的服务资源。

高吞吐

云数据库虽然可以做到弹性扩容,但是本身是分布式存储的,虽然可以通过Batch Write、Pipeline和Router Cache等方式加快访问SQL请求的数据,但是相对传统单机的数据库来说,在数据访问链路上至少也要多走一次网络,所以大部分并发量不大的小数据量请求,都会比单机延迟要高一些。

也就是说,当没有足够高的并发SQL访问的话,其实不能完全体现云数据库的性能优势,所以这也是我们在选用云数据库的时候需要认识到的问题,云数据库更多的是追求高吞吐,而不是低延迟。

当并发大到一定规模,云数据库高吞吐特性就显现出来了,即使在很高的并发下,依然可以维持相当稳定的延迟,而不会像单机数据库那样,延迟线性增长。当然,延迟的问题,在合理的架构设计方案下,可以通过缓存的方式得到极大的缓解。

数据安全

云数据库的物理服务器分布在多个机房,这就为跨数据库中心的数据安全提供了最基础的硬件支持。谈到金融业务,大家耳熟能详的可能就是两地三中心,比如北京有两个机房,上海有一个。未来一切服务都跑在云上,金融类的业务当然也不例外。相比其他业务,金融类业务对数据安全要求就要高得多。

当然,每个公司内部都有核心的业务,所以如果上云的话,也会有同样的强烈需要。这样,对云数据库来说,数据的一致性、分布式事务、跨数据中心的数据安全等更高端的需求有可能会日益强烈。常见的数据备份也有可能会被其他新的模式所取代或者弱化,比如基于Paxos/Raft的多副本方案,本身就保证了会有多份备份。

自动负载平衡

对于云数据库来说,负载平衡是一个很重要的问题,它直接决定了整个云数据库系统性能的好坏,如果一个数据库节点的数据访问过热的话,就需要考虑把数据迁移到其他的数据库节点来分担负载,不然就很容易出现性能瓶颈。整个负载平衡是一个动态的过程,调度算法需要保证资源配比的最大平衡,还有保证数据迁移的过程对系统整体的负载影响最小。这在未来也是云数据库需要解决的一个核心问题。

小结

从目前已有的SQL数据库实现方案来看,NewSQL应该是最贴近于云数据库理念的实现。NewSQL本身具有SQL、ACID和Scale的能力,天然就具备了云数据库的一些特点。但是,从NewSQL到云数据库,依然有很多需要挑战的难题,比如多租户、性能等。

上面提到的一些云数据库的特点,也是PingCAP目前在着力实现的部分,TiDB 作为国内第一个NewSQL的开源项目,在与社区的共同努力下,我们在上月底刚刚发布了beta版本,欢迎各位上Github了解我们。

随着整个社区技术水平的发展和云时代新的业务需求的驱动,除了PingCAP 的TiDB,相信会有更多的团队在这方面进行探索, 期待早日看到云数据库成熟的那一天。

本文首发于InfoQ垂直号:「细说云计算」(ID:CloudNote)

,