在过去的近40年中,SQL已经成为了关系型数据库(又称为RDBMS)的通用语言。这也就是为什么关系型数据库经常被简单称为SQL数据库的原因。从架构而言,以Oracle、PostgreSQL和MySQL为首的传统SQL数据库,是单体式(monolithic)的。也就是说,它们无法在多个实例之间自动地分配数据和查询。而NewSQL数据库的出现使得SQL具有了可扩展性和高性能。当然,此类数据库仍然具有与生俱来的局限性。
2015年,Docker容器和Kubernetes编排的出现,让我们能够以灵活、可组合的基础架构方式,来创建各种基于微服务的应用。其中,内置的可扩容性、灵活性、以及地理分布特性,是此类云原生架构的核心特点。这也就是人们常说的“分布式SQL”--这一新型的数据库。在应用方面,此类分布式SQL数据库的一个显著特征是:无论其中有多少个节点,整个数据库集群对于应用程序而言,都被其视为一个逻辑的SQL数据库。
数据库的架构
分布式SQL数据库通常具有如下三层体系结构。
1. SQL API
顾名思义,分布式SQL数据库仍然必须提供SQL API服务,以便应用程序可以对关系型数据进行建模,并执行涉及到各种关系信息的查询操作。它保留了SQL数据库典型的数据建模结构,包括:索引、外键约束、JOIN查询、以及多行ACID事务(译者注:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability))。
2.分布式查询执行
由于分布式SQL的查询能够被自动地分配到目标群集的多个节点上,因此,此举有效地避免了单个节点成为查询处理中的瓶颈问题。具体的查询流程为:目标群集中的任一节点都可以接受传入的某个查询。通过在网络中的各节点之间传输数据、协同工作,该节点能够以最小化处理等待时间的方式,仅分担查询请求中的一部分任务。而由其他节点协助完成剩余的部分。最后,该接受请求的原始节点,将汇总所有的查询结果,并发回给客户端应用程序。
3.分布式数据存储
那些包含有索引信息的数据会被自动分布(也称为分片,sharded)到群集的多个节点处。此举确保了单个节点都不会成为高性能和高可用性的瓶颈。此外,数据库集群能够支持高一致性的复制、以及多行(也称为分布式)ACID事务,进而保留了单个逻辑数据库的基本概念。
高度一致性的复制
在数据库的管理概念中,所谓支持强大的SQL API层,其本质上就是要求处于底层的存储层,能够在跨数据库的群集节点上建立强一致性的复制。这就意味着:对于数据库的写入操作,将会在多个节点上被同步提交,以保证出现故障时的数据可用性。而读取操作则是基于最后一次被提交的写入数据,或是出错之前的数据。该属性通常被称为线性一致性(Linearizability,http://www.bailis.org/blog/linearizability-versus-serializability/)。根据著名的CAP原则(https://towardsdatascience.com/cap-theorem-and-distributed-database-management-systems-5c2be977950e,译者注:一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)),分布式SQL数据库具有一致性和分区容错性。
分布式的ACID事务
为了能够支持分布式的ACID事务,分布式数据库的存储层需要在多个节点的多个数据行中进行事务性的协调任务。此处,它们正好用到了两阶段提交(2 Phase Commit,2PC)协议。参照ACID中I(隔离性)的要求,为了能够对并发式的数据访问实现严格的隔离,分布式SQL数据库将可序列化性(Serializability,http://www.bailis.org/blog/linearizability-versus-serializability/)作为最严格的隔离级别,并且通过快照(Snapshot)之类的其他方式来支持较弱的隔离级别。
业务应用的优势
分布式SQL的四个关键优势,如下图所示。
1.让SQL和事务类的开发更具敏捷性
如今,由于SQL仍然是一种轻松实现建模关系和多行操作的数据建模语言,因此为了满足应用开发人员持续对于SQL数据库的操作习惯与需求,即便是Amazon DynamoDB、MongoDB和FaunaDB之类的NoSQL数据库,也开始具备了事务性的操作能力。例如:SQL通过显式(使用BEGIN和END TRANSACTION的语法)和隐式(使用外键和JOIN查询之类的二级索引),来允许多行事务,这比传统的键-值(key-value)型NoSQL要方便得多。
此外,开发人员往往喜欢通过一次性轻松地使用SQL,来对数据(和存储)进行建模。而在业务需求发生变化时,他们只需修改JOIN,便可反映到查询之中。
2.具有本地故障转移与修复的超强弹性
在分布式SQL数据库中,我们使用基于分片(per-shard)的分布式共识复制(consensus replication)等技术,来确保每个分片(而不是每个实例)在出现故障时,仍可保持高可用性。
如此,基础架构一旦出现故障,它始终只会影响到目标数据的某个子集(也就是那些被leader分割开的碎片),而不会影响到整个集群。并且,由于剩余的分片副本能够在几秒钟之内自动地选出新的leader,因此,集群会在出现故障时表现出一定的自我修复能力。
此外,这些发生在后台群集配置上的更改对于应用程序来说是完全透明的,它们可以照常运行,而不会出现任何中断或是性能的骤降。
3.具有按需进行水平写入的可扩展性
《如何在分布式SQL数据库中进行数据分片》一文(https://dzone.com/articles/how-data-sharding-works-in-a-distributed-sql-datab),说明了开发人员通常是如何在分布式SQL数据库中实现自动化数据分片的。无论有新节点的加入,还是现有节点的删除,分片都将会在所有可用节点之间保持自动的平衡状态。
目前,那些需要处理事务的应用程序都具有可扩展能力的微服务。它们在不需要新增基础架构的基础上,完全可以直接依赖于内存中的缓存(无需从数据库中读取请求,而保留对于写入请求的处理)或NoSQL数据库(虽然能够扩展写入操作,但是无法保证ACID)。
4.针对地域分布式数据的低延迟性
正如《构建具有低延迟的云原生、以及地域分布式SQL应用的9种技术》一文(https://dzone.com/articles/9-techniques-to-build-cloud-native-geo-distributed)所强调的那样:分布式SQL数据库可以提供多种技术,来构建地域分布式的应用程序。这些技术不仅有助于对于区域性故障实现自动化容灾,而且还能够在一定程度上通过让数据更接近来自本区域的最终用户,以实现更低的数据延迟性。
原文标题:What Is Distributed SQL? ,作者:Sid Choudhury