多区域部署允许cockachdb数据库跨越多个地理区域。多区域部署的配置对集群的容错和区域性能有影响。一般来说,我们将一个cockachdb集群配置为多个区域,以实现以下两个目标中的一个或两个:
- 允许集群在其中一个区域的计算资源不可用时继续服务请求。
- 确保地理分布数据库的用户可以享受低延迟的数据库操作。
这两个目标并非完全不兼容,但两者之间存在一些权衡。
多区域概念
CockroachDB的多区域功能实现了cockachdb的一些最独特的体系结构特性。一些底层算法可能具有挑战性。然而,多区域cockachdb的核心概念有助于将大部分内容抽象为简单的概念,如regions、zones和存活目标。
Regions和Zones
Region是一个广泛的地理区域,其中部署了一组cockachdb节点。区域可以是您想要的任何东西,但只有在具有某种网络邻接、不同的工作负载或用户特征或法律需求的区域中定义区域才真正有意义。
数据库中的一个Region是主Region。主Region是数据库中所有表的默认Region。
在Region内,可以定义一个或多个Zone。Zone的定义也是任意的,但通常与Region内的数据中心保持一致(尽管它们也可以很容易地定义为高度冗余数据中心中的机架)。
在其他上下文中,Zones有时称为可用性Zones。这个想法是,一个Zone代表某种单点故障。当一个Zone被定义为数据中心时,我们可以假设在数据中心发生故障时,该分区中的所有节点都将发生故障。定义跨越数据中心的Zone意义不大,除非数据中心有一些共同的故障点(例如,两个数据中心依赖于同一个电站)。
下图以三区全局部署为例,每个区域有三个Zone。
每个Region代表一个广泛的地理区域,我们认为该区域对cockachdb应用程序具有一定的重要性。Region中的每个Zone都由一个城市表示,其中运行着一个或多个CRDB节点。
存活目标
集群中的每个数据库都有一个存活目标,该目标决定了延迟和生存能力之间的权衡。注意,有时我们可能会使用database来引用整个cockachdb部署,但在本例中,我们讨论的是由CREATE database语句定义的数据库。每个数据库都有不同的存活目标:
- Zone故障是默认的存活目标。即使区域中的一个节点发生故障,数据库仍可用于读写。如果您在区域中配置了足够的节点和适当的复制因子,多个Zone故障仍然可以存活。
- 当一个数据库被配置为Region故障,即使在整个Region故障时,该数据库仍然是完全可用的。为了实现这一点,数据必须复制到另一个Region,这在大多数情况下会降低写性能。
下图说明了一个数据库中的Zone故障,该数据库有一个Zone生存目标。有问题的数据范围在美国区域(默认区域)的三个副本中进行维护,该区域中的任何单个Zone(在本例中为纽约区域)发生故障,都允许数据库使用两个副本继续工作。在任何区域发生两次故障都会产生相同的影响,尽管无法获得的数据范围不同。
下图为Region存活目标数据库的Region故障。由于为数据库设置了Region存活目标,复制因子自动增加到5,而不是默认的3,并且副本分布在各个区域。当美国地区出现故障时,其他地区的数据仍然有三份副本,数据库操作可以继续。
确实,在不同的地区有三个副本就足以在Region级别故障中存活下来。但是,cockachdb增加了复制因子,以改进对主要区域内较小(节点或区域级)故障的处理。如果复制因子保持在3,那么主区域内的一个节点或区域发生故障将意味着所有读取都必须到次要区域,这将大大增加延迟。因为节点故障比区域故障更常见,所以我们增加了复制因子,使它们对性能的影响更小。
Region/Zone生存目标是配置多区域部署的最大单一“开关”。Zone存活产生最佳性能,而region存活在大规模中断或网络分区时促进更大的生存能力。在两者之间作出选择时,应考虑以下因素:
- 在大型公共云平台中,整个区域的故障是罕见的,但也不是闻所未闻。
- Region生存意味着Zone生存。默认情况下,Region生存目标保护任何单个区域的损失或任何两个Zone的失败。
就像我们需要至少三个节点才能允许单区域集群的生存一样,我们需要三个Region才能允许Region生存。在只有两个区域的情况下,任何一个区域的故障都将导致某些范围的大多数副本不可用。
本地规则
不管存活目标是什么,我们都可以对表中的分布进行微调,以优化来自特定区域的访问。
数据库中的表可能具有本地规则,以确定其数据将如何跨区域分布:
- 全局表(global table) 将为从任何区域的低延迟读取进行优化。
- 区域表(regional table) 将为从单个区域的低延迟读写进行优化。
- 按行区域表(regional by row table) 将有特定的行优化为低延迟读写区域。表中的不同行可以分配给特定的区域。
对于全局表,表中所有范围的副本将存在于每个区域中。这确保了读时间得到了优化,但为写操作创建了最高的开销,因为所有区域必须协调处理一个写请求。全局表适用于跨所有区域的相对静态查找表。产品表可能是一个相关的例子——产品信息通常跨区域共享,不需要频繁更新;因此,如果每个区域都有产品表的完整副本,则性能将得到优化。缺点是写入产品表需要所有区域的参与,因此相对较慢。
对于区域表,表中所有范围的尽可能多的副本信息位于单个区域中。如果该区域对业务比其他区域重要得多,或者数据与该区域特别相关,那么这是有意义的。例如,如果在国际化的应用程序中,每种语言的错误代码位于单独的表中,那么将它们定位到特定的区域可能是有意义的(当然,这将重新引发关于英语应该驻留在何处的古老争论)。注意,REGIONAL BY TABLE IN PRIMARY REGION是默认配置。
按行区域表定位特定区域中特定行的副本。每一行中的**隐藏列(crdb_region)**决定了该行的位置。该列可以由应用程序直接填充,也可以从其他信息派生。例如,在用户表中,如果国家代码是“USA”、“Canada”或北美或南美的任何国家,我们可以将行分配给美国地区。逐行区域是将数据移动到所需区域附近的一种非常强大的方法。
现在,如果您非常警觉,您可能想知道区域生存能力如何与这些表区域设置相互作用。如果我处于Region生存模式中,我便需要在其他区域中拥有副本,那么这一区域设置是如何运作的呢?答案是cockachdb在两个设置之间折衷。对于处于Region生存模式的区域表,整个表或相关范围的两个投票副本和租赁者将位于该区域,而其他投票副本将位于其他区域。最终的结果是“home”区域在性能上有轻微的优势。
本质上,在一个cockachdb集群中有三种类型的表,按生存能力递减和性能递增的顺序排列:
- GLOBAL
- REGIONAL SURVIVE REGION
- REGIONAL SURVIVE ZONE
它作为两个独立的设置呈现的原因与哪些组合是合理的以及数据库和表级设置如何交互有关。如果您的数据库中有任何SURVIVE ZONE表,您的应用程序可能会在区域故障中中断(除非您非常注意使用哪些表以及何时使用),
因此,在一个DB中混合使用REGIONAL survival ZONE和REGIONAL survival REGION表没有太大意义(如果区域故障仍然会导致停机,为什么还要为一些表付出survival REGION的性能代价呢?)这就是为什么生存目标是一个数据库级别的设置。另一方面,混合使用全局表和区域表是有意义的,所以这是表级设置。
默认情况下,从相关区域以外的区域或按行读取区域表的速度会较慢。但是,使用AS OF SYSTEM TIME可以执行低延迟的“过期”读取。AS OF SYSTEM TIME可以利用位于每个非主要区域中的非投票副本。这些非投票副本不涉及事务提交处理,因此可能略显过时。