我们行走的地球的地貌通常变化很慢。每年可以用厘米或英寸来衡量。但是数字环境,尤其是分布式数据库环境,正在以很快的速度变化。在我们最近关于下一个技术周期的博客中,你可以读到更多关于这个行业正在发生的巨大变化的信息。
在我们理解这些变化对分布式数据库环境的影响之前,我们必须定义术语“分布式数据库”的含义。这就是本文的目的。
定义分布式数据库
正如没有ANSI、ISO或IETF或W3C对NoSQL数据库的定义一样,对于什么是“分布式数据库”,也没有标准、协议或共识。
因此,我花了一些时间,根据我对业内几个数据库开发人员的经验,编写了自己的分布式数据库定义。我相信你自己的经历可能会引导你用完全正交的方式来定义这样的本体。另外,我承认这更像是外行为博客量身定做的实用观点,而不是计算机科学教授对学术论文的建议。有了这个免责声明和警告,让我们开始吧。
和集群分布
首先,让我们模糊地接受“数据库”这个概念——尽管它可能对许多人意味着许多事情——并把重点放在“分布式”这个词上。
在我看来,要实现分布式,需要在网络上的多个系统中运行数据库服务器。
现在,如果你听说过ScyllaDB的Avi Kivity,他会争辩说,一个现代的多核和多CPU节点已经形成了自己的网络,但我们今天不会探索这条道路。
当这个行业开始的时候,你有一个巨大的节点,通常是一个大型主机,运行你的数据库。或者,到20世纪80年代,它可以在你的台式电脑上运行。但被认为是“一回事”。
为了便于讨论,我们将一个节点定义为一个单一的计算整体——无论该节点是从一个更大的物理服务器上分割出来的虚拟实例,还是运行完整的物理服务器数据库,您通常都可以在本地找到它。
我们将集群定义为包含一个或多个节点。
因此,分布式数据库需要在N个节点的集群上运行,N > 1。
但是现在您有了一个跨多个节点运行的数据库引擎,您将如何处理您的数据呢?你尽可能平均地分配它们吗?这就是所谓的碎片化。还是在每个节点上都保留一份完整的副本?这叫复制,完全复制。
还有就是服务器之间的物理距离,因为据我所知,数据库需要遵循光速。因此,如果需要快速保持数据库同步,就需要将集群本地化——在同一个数据中心。它是一个分布式数据库,但这仅仅是开始。
如果想为分布在某个地理区域的用户提供接近用户的数据,可以有多个本地集群——一个在美洲,一个在欧洲,一个在亚洲。这将本地用户延迟保持在较低水平。
但是现在,您可以让不同的本地集群通过某种同步或更新机制相互通信。例如,这就是DNS或Active Directory的工作方式。每个系统独立工作,不同系统之间的更新存在传播延迟。
然而,对于一些生产用例,这可能还不够好。所以,如果你对“光速”传播延迟的容忍度更高,使用所谓的最终一致性,或许就能让星团本身遍布全球。一些服务器可能在美国,另一些在欧洲或亚洲。但是,它们都被认为是同一个逻辑集群。
角色、高可用性和故障转移策略
接下来,您将扮演数据库中节点的角色。是都是对等节点,每个节点都可以完全写入,还是其中任何一个节点被指定为leader或master节点,而其他节点被指定为只读副本?
在过去,通常将副本作为“热备盘”,仅在主服务器出现故障时使用它们——这仍然是许多系统的成功模式。但是热备份没有承载任何负载。它懒懒地坐在那里哼着歌,以防万一。
这就是为什么许多人更喜欢点对点无领导拓扑,在这种拓扑中,每个人都可以分担负载。而且没有单点故障,也不需要在故障转移期间花费时间打嗝。
在这些所谓的主动-主动场景中,如何保持系统同步更复杂——这是一件更困难的事情——但如果你能解决它,你就已经消除了数据库中的任何单点故障。
此外,即使您有一个分布式数据库,也不意味着您的客户机知道拓扑结构。因此,人们可以实现一个负载平衡器来管理您的分布式数据库,或者他们可以通过让智能客户端知道您的数据库是如何分段的并将查询路由到正确的节点来实现客户端负载平衡。
数据复制和碎片化
现在让我们来看看这些复制和碎片化策略。如我所说,您可以使每个节点成为整个数据库的完整副本。例如,您可以在三个不同的服务器上有三个完整的数据集,或者您可以在多个服务器上分布不同的数据块,并在每个服务器上对它们进行不同的切片,这样即使是两个或更多的数据也更难丢失,并且集群中的服务器也不会死亡。
示例1:基本数据分段。请注意,在这种情况下,尽管数据被分段以实现不同节点之间的负载平衡,但它并不提供高可用性,因为没有复制分段。
示例2:数据复制的主拷贝方法,其中一个节点用于写入数据,然后数据可以传播到其他只读节点。这提供了一定程度的高可用性,当主节点离线时,副本可以接管群集。但是,它不能正确地平衡您的工作负载,因为所有的写入都必须在主服务器上处理,所以对于写入繁重的工作负载来说,它可能不切实际。
示例3:这里,所有数据都在主动-主动无领导拓扑中进行切片和复制。每个节点都可以接受读写操作,因此在管理工作负载方面是平等的。同样,由于复制,一些群集的任何丢失都不会导致数据丢失。
一致性水平
一致性级别决定了在允许读取或写入完成之前需要同步多少拷贝。假设您的数据以三种方式复制,并且您希望确保这三种方式始终完全同步。您需要完整事务的强一致性保证。这些在SQL RDBMS中很常见,您可以使用具有ACID保证的强一致性。
这与您希望确保节点被更新是完全不同的。相信他,他会在后台把这个更新告诉两个伙伴。你可以继续你的一天。这就是所谓的最终一致性。这意味着数据库可以更快、更宽松地处理查询,在某些情况下,您可能会发现数据变得不一致。
您甚至可以设置它,以便每个事务都可以有自己可调整的一致性,这允许您为特定的用例定制一致性保证。
示例:在这个ScyllaDB示例中,您可以将复制因子设置为3,但是将读取操作的一致性级别设置为1。这意味着您需要的只是来自存储数据的第一个节点的响应来满足客户端;不需要等三份都报回来。但是,如果希望确保所有三个副本具有相同的存储结果,可以将查询更改为CL = 3;这将允许您发现可以通过运行反熵修复操作来修复的潜在数据不一致。
手动切片和自动切片
接下来,对于水平可伸缩性,您的系统如何决定如何跨节点分割数据?起初,这始终是一个手动过程,管理起来很困难,也很成问题。因此,分布式数据库实现了一种算法来自动将数据分割到节点中。虽然现在这种情况比较普遍,但是还是有一些分布式数据库没有解决,特别是如何自动切片或者让自动切片成为一个你开箱即用不了的高级功能。
拓扑感知
最后——这对高可用性很重要——分布式数据库需要知道它们自己的物理部署。假设您有一个本地集群,但都在数据中心的同一个机架上。然后,不知何故,权力被消灭了。哦亲爱的!你的整个系统都坏了。
因此,机架感知意味着您的数据库可以尝试确保集群中的每台服务器都在自己的机架上——或者至少,它们尽可能均匀地分布在可用的机架上。
跨可用区域或地区的数据中心认知也是如此。您希望确保没有一个数据中心灾难意味着您丢失了部分或全部数据库。