Aerospike:入门与实战——架构

234 阅读32分钟

由于你刚开始使用 Aerospike,本章不会详细解释数据库的构建方式。然而,了解 Aerospike 的一些关键工作原理有助于理解为什么要以特定方式使用它,以及如何充分利用其功能。

本章将重点讨论三个主要主题:横向扩展(scale out)、纵向扩展(scale up),以及在分布式系统中如何实现具有强一致性的事务管理。

横向扩展

为了在性能延迟和吞吐量上实现线性扩展,Aerospike 必须在多台标准计算机(也称节点)上进行横向扩展。为此,Aerospike 的核心设计中包含了几项基本原则。这些基础支柱影响数据库的各个方面。横向扩展架构的关键目标是维护数据在数据分区和节点之间的均匀分布。结合支持动态增加和移除节点的弹性能力,这种架构确保系统避免热点问题(即节点或网络连接过载),并在实现线性扩展的同时提供卓越的性能(高吞吐量和极低的延迟)。

无共享数据库集群

Aerospike 是一种无共享(shared-nothing)数据库,这意味着集群中的每个节点之间没有任何共享资源。数据库集群由一组标准服务器节点组成,每个节点拥有 CPU、内存(RAM)、旋转磁盘(HDD)以及可选的闪存存储单元(SSD)。这些节点通过标准的 TCP/IP 网络连接在一起。

数据库的几个基本特性使其成为无共享系统:

  • 每个节点都与其他节点相同
    这在硬件能力和软件方面都是如此。Aerospike 没有主节点,因此没有单点故障。
  • 数据到节点的映射存在于每个节点上
    这意味着从智能客户端直接到达数据的路径仅需一次跳跃,无需中间步骤。
  • 数据分区通过分布式哈希表完成
    Aerospike 对每个键使用极其随机的加密哈希,以确保数据在集群中均匀分布。
  • 实时优先处理长时间任务和短时间任务
    数据库会动态且智能地处理长时间任务(如节点数量变化时的数据再平衡)和短时间、低延迟任务(如事务)之间的相互影响,从而保障短时间任务的 SLA(服务级别协议)。
  • 集群管理是动态的
    可以在不中断事务的情况下添加或移除节点。数据再平衡是动态完成的,维护操作(如滚动升级)在不中断服务的情况下进行。

以上所有原则的基本思路是确保集群在动态节点进出时无需操作干预,数据在集群节点之间均匀分布,并且系统在随着客户端和服务器节点增加时能提供高性能和线性扩展性。

如图 5-1 所示,Aerospike 应用架构具有两个层次,它们与客户端的两个层次进行通信。这些层次包括:

  • 应用层
    需要数据库的客户端应用程序。
  • 客户端层
    嵌入应用程序内的 Aerospike API 库实现。
  • Aerospike 的分发层
    集群内通信。
  • Aerospike 的数据层
    存储接口(包括内存存储和 SSD 等持久性存储)。

image.png

数据分布

Aerospike 的一个关键特性在于它能够通过确定性地均匀分布数据来解决大规模数据集的问题,从而最小化数据迁移。

注意
Aerospike 使用 RIPEMD-160 算法的摘要来对分区进行哈希划分。该摘要是通过对键应用 RIPEMD 算法生成的 20 字节哈希值。该算法在防止哈希冲突方面非常强大。在摘要空间(即分区空间)中,键的分布总是均匀的,即使哈希有偏差,其摘要也不会偏斜。

分区是数据分割的主要单位。对每个键的随机加密哈希使数据均匀分布在各节点上,如图 5-2 所示。哈希将数据划分为 4,096 个分区,之后将这些分区映射到集群中的节点。分区分配算法的目标包括:

  • 确定性
    分布式系统中的每个节点都可以独立计算出相同的分区映射。
  • 均匀分布数据
    将主分区和副本分区均匀地分布在集群中的所有节点上。
  • 最小化数据迁移
    在集群发生变化时(例如添加或移除节点),需要移动的数据量越少越好。

Aerospike 使用的算法可以在节点之间自动创建均匀的分区平衡,同时尽量减少数据迁移。

image.png

图 5-2a 展示了一个具有五个节点、复制因子为 3 的集群中数据分配的分区映射。仅显示与复制因子相等数量的列来表示数据的映射位置,即示例中的前三列。

映射中的最后两列并非数据存储的位置,因为数据仅被复制三次。相反,接下来的列存储的是继承列表中其他节点的位置信息,以便当存有数据的节点发生故障时数据可以迁移到这些节点。

图 5-2b 展示了当一个节点掉线或与其的网络连接丢失时分区 2 中的数据情况。在本例中,节点 N5 掉线。由于分区映射已经存储了下一个位置的信息,分区数据会被迁移到映射右侧列中列出的下一个节点,即节点 N3。

需要注意的是,这也会导致下一列向左移动,因此,如果节点 N3 也掉线,节点 N1 将成为接收分区 2 数据的下一个节点。

图 5-2c 展示了节点 N5 恢复上线时的情况。数据分区再次被映射回节点 N5,其余两列则向右滑动,恢复为该分区的继承列表中的节点。

由于分区数量固定为 4,096,且节点的 ID 是已知的,因此分区映射是可计算的。当节点被添加到集群或从集群中移除时,每个集群中的节点都知道其他所有节点的 ID。因此,集群中的每个节点可以计算出分区映射,并因此知道每个数据分区的位置,而无需与其他节点进行通信。

这其中涉及更多复杂性。在较大的集群中,节点之间的分区数量较少,因此可能需要牺牲一些数据迁移最小化来实现更均匀的数据负载分布。此外,机架感知(Rack Awareness)也引入了另一个复杂因素。如有需要,可以查阅 Aerospike 发布的文档或学术论文以获取更多详细信息。

集群自管理

Aerospike 的集群管理子系统负责自我管理所有的分区、映射和数据迁移操作。它确保所有节点对当前集群成员达成共识。

网络故障和节点加入或离开等事件会触发集群成员变化,这些变化既可能是计划内的,也可能是计划外的。例如随机出现的网络中断、计划内的容量增加以及硬件/软件升级。

集群管理涉及的三个主要组成部分是:

  • 心跳子系统
    维护邻接列表(将在本章后文中描述)并存储最新的心跳交换信息,以跟踪节点的加入和移除。
  • 集群子系统
    维护继承列表。
  • 交换子系统
    负责交换分区数据并执行分区平衡操作。

集群管理子系统的具体目标包括:

  • 在集群的所有节点上达成关于当前集群成员的一致视图。
  • 自动检测新节点的加入/离开并无缝地重新配置集群。
  • 检测网络故障并对网络不稳定具有韧性。
  • 最小化检测和适应集群成员变化的时间。

集群视图

每个 Aerospike 节点都会自动分配一个唯一的节点标识符,该标识符是节点 ID 或 MAC 地址与监听端口的函数。集群视图由 <cluster_key, succession_list> 元组定义,其中:

  • cluster_key 是一个随机生成的 8 字节值,用于标识集群视图的实例。
  • succession_list 是一个按顺序排列的唯一集群节点标识符列表。

集群键能够唯一标识当前的集群成员状态,并在集群视图发生变化时更新。这使得 Aerospike 节点可以区分具有相同成员节点集合的不同集群视图。

每次集群视图的变化都会显著影响操作延迟及整个系统的性能。因此,系统需要快速检测节点的到达或离开事件,以实现高效的共识机制来处理集群视图的变化。

然而,在节点并未掉线(例如,仅是网络连接不稳定)的情况下进行数据迁移将非常低效。因此,在确定节点已掉线之前不进行操作至关重要。

节点的到达或离开通过节点间定期交换的心跳消息来检测。集群中的每个节点都维护一个邻接列表,即最近向该节点发送心跳消息的其他节点的列表。对于离开集群的节点,通过在可配置的超时间隔内未接收到心跳消息来检测;超时后该节点将从邻接列表中移除。

检测机制的主要目标是:

  • 避免因偶发和短暂的网络故障而宣布节点已离开。
  • 防止行为异常的节点频繁地加入或离开集群。节点可能由于系统资源瓶颈(如 CPU、网络、存储设备等)而出现异常行为。

替代方法如副本写操作也可以作为心跳消息的次要替代。只要在超时间隔内接收到主或次心跳消息,集群视图将保持不变。

系统会自动预测潜在的节点故障。集群中的每个节点通过计算从其他邻接节点接收到的消息丢失的平均值来评估其健康状况。

行为异常的节点通常有较高的平均消息丢失率。如果一个不健康的节点已在集群中,将会将其移出集群;如果该节点尚未加入集群,则不会考虑其加入,直到其平均消息丢失率恢复到可容忍的范围。

集群视图变化

邻接列表的变化会触发 Aerospike 集群算法的运行,以确定新的集群视图。Aerospike 致力于尽量减少单个故障事件对集群的影响,以降低集群过渡的次数。

例如,一个故障网络交换机可能导致部分集群成员无法访问。当网络恢复后,这些节点需要重新加入集群。为尽量减少集群过渡——这在时间和资源上都相当昂贵——节点仅在固定的、可配置的集群过渡间隔的开始时决定集群更改。

其思想是避免对心跳子系统检测到的节点到达和离开事件反应过快,而是将一批相邻的节点事件处理为单次集群视图更改。Aerospike 的集群管理机制允许一次性添加或删除多个节点,而不会导致停机。

智能客户端

数据库不会独立存在。整个栈需要共同运作,以使端到端系统实现可扩展性。智能客户端层消化了管理集群的复杂性。在这里有一些需要解决的挑战,其中一些如下:

  • 发现机制
    客户端使用一个或多个种子节点,这些节点会告知客户端有关每个邻近节点的信息,直到客户端了解集群中每个节点的角色和存在状态。分区映射(见图 5-2)显示了分区和节点之间的关系,客户端可以交换并缓存该映射。通过此分区映射,客户端始终能够直接访问数据,无需中间路由节点。

  • 信息共享
    每个客户端进程在内存中存储分区映射。为了保持信息的更新,客户端进程定期向服务器节点查询更新。它通过将本地存储的版本与服务器的最新版本进行比对,来确定是否需要更新。如果有更新,它会请求完整的分区映射。

  • 集群节点处理
    在初始化时,客户端为每个集群节点创建一个内存结构并存储其分区映射。此外,它还为该节点维护一个连接池。

    当节点被认为已掉线时,分区映射、内存结构和连接池都会被清除。建立和清除这些结构是一个代价昂贵的操作。如果基础网络不稳定且反复发生这种情况,可能会降低系统整体性能。因此,需要一种复杂的方法来识别集群节点的健康状况。Aerospike 提供了以下两种机制以帮助实现此目的:

    • 健康评分
      短暂的网络问题或其他问题可能会使一个节点看似已掉线,而实际上该节点是正常的。客户端会跟踪在特定节点上遇到的数据库操作失败次数。仅当失败计数(即“幸福系数”)超过特定阈值时,客户端才会移除该集群节点。任何成功的操作都会将该节点的失败计数重置为 0。此方案默认在客户端库中实现。
    • 集群协商
      不稳定的网络通常很难处理,单向网络故障(A 看到 B,但 B 看不到 A)尤其棘手。在一些情况下,集群节点彼此可见,但客户端可能无法直接看到某些集群节点(例如 X)。在这种情况下,客户端会查询集群中的所有已知节点,看是否有节点在其邻居列表中包含 X。如果有节点报告 X 在其邻居列表中,客户端不会采取任何行动。如果 X 不在任何客户端可见节点的邻居列表中,客户端将等待一个阈值时间,然后删除引用该节点的数据结构。

多年来,这些自动化方案已被证明能显著提升系统的稳定性。

向上扩展

向多个节点扩展是所有分布式系统的共同特征。Aerospike 技术同样专注于向上扩展,以充分利用每个节点内的网络、存储和处理容量。

在本节中,您将了解混合内存架构(Hybrid Memory Architecture,HMA),它能够使每个节点上的闪存存储支持读写几十TB数据,并实现亚毫秒延迟。此外,您还将了解利用多核处理器帮助 Aerospike 实现单节点每秒数百万次事务处理的系统级技术,同时保持亚毫秒级延迟。

Aerospike 的有效节点扩展能力以及对闪存存储的使用意味着:

  • 在较少的节点上实现更高的吞吐量。
  • 更好的可用性,因为随着集群中节点数量的增加,节点故障的概率通常也会增加。
  • 较低的总拥有成本,因为在闪存设备中实时存储和访问数据的成本低于直接存储和访问内存中的数据。
  • 更简化的操作负担。管理一个20节点的集群要比管理一个200节点的集群容易得多,对运营人员来说是巨大优势。

混合内存架构

大多数数据库将数据和索引一起存储在磁盘上。而内存数据库则将数据和索引一起存储在内存中。为充分利用每个计算节点,Aerospike 大量使用 SSD(闪存存储设备)来存储数据。该数据库实现了专用算法,以便在 SSD 上以亚毫秒延迟访问数据。而索引则被独立存储在内存(RAM 或持久内存 PMEM)中。这是受专利保护的混合内存架构™(Hybrid Memory Architecture™,HMA)的核心(见图 5-3)。

Aerospike 的数据访问实现基于其专有文件系统层,因此绕过了操作系统的文件系统层。与大多数数据库不同,Aerospike 在读取数据时不使用页面缓存,从而消除了图 5-3 中显示的另一层。常驻内存的索引指向闪存盘上实际的数据项位置,从而实现毫秒级内读写。

image.png

直接在 SSD 上写入数据并不可行,因为这会导致磨损均衡问题:如果对某些区域频繁写入,会加速其损坏。为了解决这一问题,Aerospike 实现了一种日志结构文件系统,配合大块写入以及写时复制(Copy-on-Write)机制,使得写入操作在内存缓冲区中收集,然后批量刷新到闪存存储。这使得 Aerospike 在处理高性能读负载时,即使遇到大量写负载,依然能够高效地运作。

以下是 SSD 策略的总结:

  • 直接访问 SSD 设备:不通过操作系统的文件系统层。
  • 高度并行化:设计用于充分利用多 SSD 节点。
  • 大块写入 SSD:减少 SSD 单元的磨损,延长硬件寿命。
  • 优化的 SSD 读写性能:实现最佳的读写性能。
  • 持续且无中断的碎片整理:防止磁盘空间耗尽。

这些策略最终实现了在节点上可以根据 SSD 数量而非仅限于内存量来存储更多数据。这意味着,在一个大型 Aerospike 集群中,节点数通常比其他完全基于内存的系统少一个数量级。例如,Aerospike 只需要 20 个节点即可完成一个传统内存事务数据库需要 200 个节点完成的任务。

多核处理器

要实际实现这一点,Aerospike 需要在每个节点上处理 10 倍的事务量,这需要充分利用多核处理器和多 CPU 节点。

为此,Aerospike 采用了多种策略:

  • 多线程处理
  • 高效的 C 代码实现
  • CPU 固定(例如,与英特尔合作进行 NUMA 固定)
  • 线程绑定到特定的网络队列(例如,ADQ【应用设备队列】与 CPU 线程绑定,以优化特定的英特尔硬件卡)
  • 使用并行网络队列,避免在特定 CPU 上产生瓶颈
  • 运行在网络监听线程中,避免线程上下文切换的开销

所有这些策略结合起来,使得 Aerospike 单节点可以每秒处理数百万次事务。

如图 5-4 中的基准测试所示,这些策略可使单节点每秒处理多达 800 万次事务,若使用英特尔 ADQ 等网络硬件优化,单节点可达 1500 万次事务。实际上,单节点可能不需要处理这么多事务,但知道这一潜力存在仍然有用。

image.png

充分利用 CPU 能力是 Aerospike 实现超高吞吐量、低延迟负载的策略之一,这使得其能够在小规模集群上实现非常高的扩展性。

内存碎片管理

Aerospike 原生处理所有内存分配,不依赖于编程语言或运行时系统。Aerospike 将索引紧凑地存放在 RAM 中。在数据规模超过 100 GB 且事务速率极高的情况下,内存碎片化是一个重大挑战。Aerospike 使用特定的内存分配库(jemalloc)以及通过按命名空间分组对象等策略来优化长期的对象创建、访问、修改和删除模式,并最大限度地减少碎片化。

数据结构设计

对于索引和需要并发访问的全局结构等数据结构,Aerospike 将所有关键数据结构置于单线程分区中,每个分区都有独立的锁,从而减少了分区间的争用。对于嵌套的数据结构(如索引树),访问时无需在每一级都获取多个锁。相反,每个树元素都有引用计数及其独立的锁,这使得在不持有多个锁的情况下,可以安全并发地读取、写入和删除索引。

这些数据结构经过精心设计,确保频繁访问的数据具有良好的局部性,尽量落入单一缓存行内,从而减少缓存未命中(即应用请求数据时数据不在缓存中)和数据延迟(等待数据被检索的时间)。例如,在 Aerospike 中,索引项的大小恰好为 64 字节,与缓存行大小相同。

在 Aerospike 这样的生产系统中,功能性、系统监控以及故障排除功能需要内置并优化。这些信息存储在线程本地数据结构中,可以在查询时被提取和聚合。

调度与优先级管理

除了基本的键值存储(KVS)操作外,Aerospike 还支持批量查询、扫描和二级索引查询。扫描通常是遍历整个数据集的慢速后台作业。批量查询和二级索引查询返回匹配的数据子集,因此根据特定的用例具有不同的选择性。平衡吞吐量和公平性是一项挑战,尤其是在各种不同的工作负载下。

为此,Aerospike 遵循了三大原则:

  • 按作业类型划分
    每种作业类型分配自己的线程池,并在跨线程池中进行优先级排序。同类型作业在其专属线程池中也有内部优先级。
  • 基于工作量的单位
    基本的工作单位包括查找、I/O 和验证每条记录所需的工作量。每个作业由多个工作单位组成,定义了其工作量。
  • 受控负载生成
    线程池包含一个负载生成器,用于控制工作生成的速度,池中的线程则实际执行这些工作。

Aerospike 使用协作调度,工人线程在完成 X 个工作单位后为其他工人线程让出 CPU。这些工人具有 CPU 核心和分区亲和性,避免了并行工人访问特定数据时产生的数据争用。

在 Aerospike 中,某些基本作业类型的并发工作负载通常按先来先服务原则运行,以实现低延迟响应。此外,系统还需要能够在扫描和查询等长期工作负载中取得进展,这些任务的进度有时由用户设置和/或应用程序消费结果集的能力所引导。如图 5-5 所示,在这种情况下,系统动态适应并切换到轮询调度模式。这意味着多个并行运行的任务会根据其进展动态暂停并重新调度。

image.png

并行处理

Aerospike 的统一数据分区机制使得系统资源能够以平衡且高效的方式进行并行处理。许多 Aerospike 节点配置了多个 SSD 存储设备。除了将数据均匀分布在各节点之间,Aerospike 还可以将数据随机分配到这些存储设备中,从而在小规模集群上提供极高的并行性。

这使得即便在少量节点上,也能实现更高水平的并行处理。图 5-6 展示了一个包含四个节点且每个节点配有五个 SSD 的小型示例系统。

image.png

注意

这个简单示例说明了一个拥有 100 个节点的集群,如果每个节点配有 16 个存储设备,就能够实现 1600 路并行执行,从而驱动每秒数百万次的高吞吐量单条记录写入工作负载。

在使用多线程的多核处理器架构、具有并行网络队列的 HMA 配置中,单个节点的理论存储上限可达 256 TiB。大多数实际实现的单节点存储容量在 100 TB 左右,因此在相同的 100 节点集群中,数据库总存储容量可以达到 10 PB,并且能够以极高的吞吐率进行处理,读写延迟在毫秒以下。

分布式事务一致性

Aerospike 利用其横向和纵向扩展能力的高性能来实现具有强一致性的事务算法。请注意,截至本文撰写时,Aerospike 支持带有复制的单记录事务的一致性(对多记录事务的支持将在未来版本中引入)。这种高性能水平使 Aerospike 能够使用其他系统在相同基础设施上无法实现的策略。

本节将介绍 Aerospike 集群中如何保证事务一致性,以及当组件在地理上分离时如何实现事务。

事务中的强一致性

分布式数据库的 CAP 定理指出,虽然分布式数据库有三个重要方面:一致性、可用性和分区容错性,但其中一个方面必须有所牺牲,以确保其他两个方面的高水平表现。选择的两个方面决定了数据库的功能。分区容错性对于在集群中分布数据和工作负载是必需的,因此通常选择 AP(强调可用性)或 CP(强调数据一致性)。

Aerospike 可以配置为 AP 模式,优先保证可用性而非一致性。在正常运行的 Aerospike 系统中,即使在 AP 模式下,也不太可能违反一致性,除非发生以下两种情况:

  • 集群分裂为两个或多个子集群并继续读取和写入数据。
  • 集群同时丢失的节点或机架数等于或超过复制因子,并继续进行读写操作。

成员清单(Roster)

Aerospike 与其他分布式数据库的一个关键区别在于,Aerospike 不像其他数据库那样使用法定人数(quorum)。唯一的法定人数是一种简单的写入所有副本并读取一个副本的机制,这是由于 Aerospike 的读写性能极高。而不是依赖法定人数,Aerospike 使用一种基于成员清单(roster)的强一致性方案。

当配置为强一致性模式时,Aerospike 将成员清单定义为预期存在的节点集。当所有成员清单中的节点都存在,且所有分区都处于正确的计算位置时,集群处于稳定状态,并提供最佳性能。

正如前面所述,分区使用随机分配算法在集群中的节点之间分配。为了实现数据冗余,每个分区的副本数由可配置的复制因子决定。

这些分区副本之一被称为清单主节点(roster-master),其余的是清单副本节点(roster-replica):

  • 清单主节点(roster-master) :存储特定数据分区主副本的节点。
  • 清单副本节点(roster-replica) :存储特定数据分区次要副本的节点。

注意:即使节点与集群的其他部分断开连接,清单和分区映射仍存在于所有节点上。这意味着每个节点都知道每个分区的位置,即使节点间的通信被切断。

在成员清单中,还存在“大多数”和“超大多数”的概念:

  • 大多数(Majority) :成员清单中节点总数的一半以上。
  • 超大多数(Supermajority) :成员清单中节点总数减去复制因子以上的数量。

例如,在一个包含 10 个节点且复制因子为 3 的集群中,大多数需要 6 个或更多节点,而超大多数需要 8、9 或 10 个节点。

脑裂情况(Split-Brain Conditions)

当集群中节点之间的网络连接中断时,就会形成两个功能性子集群,能够在一定程度上继续工作。这种情况称为“脑裂”。通常,提供强一致性的系统需要至少三个副本。因此,当集群分裂时,如果一个子集群拥有该数据项的多数副本(例如三分之二),则可以允许写入操作。Aerospike 进一步优化了这一点,通常只存储两个副本,但在必要时采用自适应方案动态添加更多写入副本,从而在大多数情况下优化性能。

注意:即使是一个两副本系统仍然需要至少三个节点才能保持可用性。单个节点永远不会同时拥有同一分区的主副本和副本。Aerospike 的复制方案在网络故障期间提供了与传统基于法定人数的系统使用三个副本相当的可用性水平。

在 CP 模式下,若满足以下条件之一,则分区可用于读写:

  1. 子集群包含该分区的清单主节点和所有清单副本节点。
  2. 子集群包含清单中节点总数的一半以上,且拥有该分区的清单主节点或清单副本节点。
  3. 子集群包含清单中节点总数的一半,并且包含该分区的清单主节点。
  4. 子集群包含清单中节点总数的超大多数。

注意:某些节点在计算大多数和超大多数条件时会被排除:

  • 重新加入集群但数据丢失的节点(例如,某些存储设备为空)。
  • 未正常关闭且已启用的节点。

成员清单示例

假设复制因子设置为 2,则系统中的每个分区将有一个清单主节点和一个清单副本节点。

从一个由 5 个节点组成的小型集群开始,假设某个分区的数据的清单主节点在节点 5 上,清单副本节点在节点 4 上。在这种情况下,成员清单是完整的,数据分区可完全用于读写。

如果节点 4 和节点 5 的网络通信中断,它们将与集群的其他部分隔离,形成两个子集群。在这种情况下,由于一个子集群中包含该分区的清单主节点和清单副本,而另一个子集群中没有该数据的副本,因此只有较小的子集群仍可用于该分区的读写。

image.png

现在,假设只有节点 5 断开连接或停机,这可能是由于滚动升级造成的。这会将清单主节点与集群的其他部分隔离开,但该分区的副本仍然存在。由于清单主节点位于较小的子集群中,而副本位于大多数子集群中,规则规定该数据分区在较小的子集群(即图 5-7c 中的节点 5)不可用。

暂时地,清单副本会被提升为主节点(alt-master),并按照分区映射中的继承列表在另一个节点上创建第二个副本(alt-replica)。在图 5-7c 的示例中,数据在节点 3 上得到复制。由于每个节点都拥有清单和分区映射,所有节点都可以计算出新的数据位置。这允许写入保持一致性和持久性,且该分区仍然可以用于读写。在任何两集群的脑裂情况下,数据分区将在其中一个子集群中 100% 可用,而不会在两个子集群中同时可用。

如果这是一个滚动升级的情况,节点 5 在升级完成后将重新激活并重新加入集群。接下来,节点 4 将被停机。节点 5 包含它停机前的所有数据,而节点 3 包含节点 5 停机期间对数据进行的所有更改,因此能够提供数据的完整视图以满足任何请求。读取操作可能会略微变慢,因为它需要检查两个节点以确保包含最新更改,但通常不会中断读取或写入,保证 100% 的可用性。有关滚动升级的更多信息,请参阅 Aerospike 文档。

在图 5-7d 中展示了一种分区完全不可用的可能脑裂情况。在此情况下,主节点和副本节点分别被隔离在不同的子集群中。这是 CAP 定理的一个实例。为了保持强一致性,在这种情况下需要牺牲可用性。

写操作

在 Aerospike 中,写入操作始终采用写入所有副本的机制,这意味着如果数据库的复制因子是 2,那么它将始终写入 2 份数据。如果复制因子是 3,则会写入 3 份数据。

图 5-8 展示了在 3 副本系统(复制因子设置为 3)中的写操作流程:

  1. 客户端启动对该分区数据的主节点的写入。
  2. 主节点将数据写入本地。
  3. 主节点并行地将数据更改复制到两个副本。
  4. 副本节点将数据写入本地,然后向主节点反馈数据复制成功。
  5. 主节点提交事务,并向所有副本发送提交通知。此“已复制通知”消息无需等待副本响应,因此非常快速。
  6. 主节点向客户端报告写入成功。

image.png

CAP 定理通常被认为包含两种一致性类型:强一致性或最终一致性,但实际上还有一种略低于强一致性类型的形式:顺序一致性,也称为会话一致性。对于读取操作,Aerospike 支持线性化一致性和顺序一致性。而对于写入操作,Aerospike 始终保持强一致性,不容忍任何数据丢失。

机架感知

机架感知是 Aerospike 企业版的一个功能,意味着分布式应用可以识别数据中心(或云端的区域和可用区)中的哪些节点位于同一机架上。由于 Aerospike 支持机架感知,它不会将同一分区的主副本和副本存储在同一个机架上。这确保了即使整个机架失效,数据库也能够在其他机架上继续正常运行。

在读取操作上,机架感知带来了显著的性能优势。如果数据存在于多个机架中,您可以像访问本地数据一样从单个机架读取数据。然而,对于写入操作,系统必须总是访问多个分区副本,并在机架感知集群中访问多个机架。

不过,由于已知完整的数据副本是可用的,因此在某些情况下,即使机架之间的通信中断,Aerospike 仍可以在保证可用性和一致性的同时进行读取和写入操作。这种能力在机架地理分布(如图 5-9 所示)上尤其关键。

image.png

在某些类型的使用场景中,比如银行间的资金转账操作,单一数据库需要覆盖多个地理上分离的地点。在这种情况下,权衡之处是写入延迟会显著提高,但数据保持一致且可靠,这在这种用例中更加重要。

图5-9所示的示例是一个三副本系统,分布在美国大陆的三个机架上。每个站点都拥有数据的完整副本。机架感知机制允许本地客户端应用程序以极低的延迟(小于1毫秒)访问本地数据。写入操作则会耗时较长,因为需要将数据写入到所有三个机架中,受到网络延迟和光速限制等因素的影响,通常会导致100至300毫秒的延迟。

该配置的结果是一个完全同步的active/active系统。如果整个机架宕机,或与其的连接中断,导致分区脑裂,其他两个机架仍可在保证可用性和强一致性的情况下继续运行,不会引发任何冲突。

当一个机架下线或重新加入时,系统无需任何操作员干预即可确保数据库的平稳运行,这些都已被系统自动处理。对您而言,这意味着极高的系统正常运行时间,唯一的代价是较高的写入延迟。

根据您配置地理分布式数据库的方式,您可以选择以部分数据一致性为代价来降低写入延迟,建立异步active-active系统。数据中心间复制(XDR)是Aerospike企业版的另一项功能,能够透明且异步地在不同的Aerospike集群之间复制数据。企业通常利用XDR将基于Aerospike的边缘系统数据复制到集中式的Aerospike系统中。XDR还能支持企业在危机(如自然灾害导致整个集群宕机)期间保持持续运营。

如需了解更多选项的信息,请参考Aerospike文档。

总结

Aerospike的架构比一本简单的入门书所涵盖的内容要复杂得多。为了不让您淹没在细节中,本章节提供了一些基础知识以供拓展。对这些核心概念的理解有助于您在使用数据库时从一开始就充分发挥其功能。

接下来,我们将深入探讨在Aerospike中进行数据建模的方法。