Fork me on GitHub
代码改变世界

[翻译] Cassandra 分布式结构化存储系统

2022-04-08 23:42  沉睡的木木夕  阅读(729)  评论(0编辑  收藏  举报

Cassandra 分布式结构化存储系统

摘要

Cassandra 是一个分布式存储系统,用于管理分布在许多商品服务器上的大量结构化数据,同时提供无单点故障(no single point of failure)的高可用服务。Cassandra 的目标是在数百个节点(可能分布在不同的数据中心)的基础设施上运行。在这种规模下,大大小小的组件都会连续出现故障。在面对这些故障时,Cassandra 管理持久状态的方式推动了依赖于此服务的软件系统的可靠性和可伸缩性。虽然在许多方面 Cassandra 很像一个数据库,并在许多设计和实现策略上有很多共同之处,但 Cassandra 不支持一个完整的关系数据模型;相反,它为客户提供了一个简单的数据模型,支持对数据布局和格式的动态控制。Cassandra系 统的设计是为了在廉价的硬件上运行,在不牺牲读效率的情况下有高的写吞吐量。

1.概述

Facebook 运营着最大的社交网络平台,在高峰时期,它通过位于世界各地许多数据中心的数万台服务器为数亿用户提供服务。Facebook 平台在性能、可靠性和效率方面都有严格的运营要求,为了支持平台的持续增长,平台需要具有高度的可扩展性。处理由数千个组件组成的基础设施中的故障是我们的标准操作模式;在任何给定的时间,总是有少量但数量可观的服务器和网络组件出现故障。因此,软件系统需要以一种将失败视为规范而不是异常的方式来构建。为了满足上述可靠性和可扩展性的需求,Facebook 研发了Cassandra。

Cassandra 综合使用了一些著名的技术来实现可伸缩性和可用性。Cassandra 旨在满足收件箱搜索问题(InBox Search Problem)的存储需求。收件箱搜索是一个功能,用户可以搜索他们的 Facebook 收件箱。在 Facebook,这意味着系统需要处理非常高的写吞吐量,每天数十亿的写操作,并随着用户数量的增加而扩展。由于用户是由地理分布的数据中心服务的,因此能够跨数据中心复制数据是降低搜索延迟的关键。收件箱搜索在2008年6月推出,大约有1亿用户,今天我们有超过2.5亿用户,到目前为止 Cassandra 一直都能支撑。Cassandra 现在被部署为多个服务的后端存储系统。

本论文的结构如下:第2节是相关的工作,其中一些工作对我们的设计有很大的影响。第3节更详细地介绍了数据模型。第4节将介绍客户端API的概述。第5节介绍了系统设计和使 Cassandra 工作的分布式算法。第6节详细介绍了使用 Cassandra 工作和改进性能的经验。在第6.1节中,我们描述了 Facebook 平台中的一个应用程序是如何使用 Cassandra 的。最后第7节总结了关于 Cassandra 的未来工作。

2.相关工作

分布式数据的性能、可用性和持久性已经在文件系统和数据库领域得到了广泛的研究。与P2P存储系统相比,P2P存储系统只支持平面命名空间(flat namespaces),而分布式文件系统通常支持分层命名空间(hierarchical namespaces)。像 Ficus 和 Coda 这样的系统会以牺牲一致性为代价来复制文件以实现高可用性。通常使用专门的冲突解决程序来管理更新冲突。Farsite 是一个不使用任何集中式服务器的分布式文件系统。Farsite 使用复制实现了高可用性和可扩展性。Google 文件系统 (GFS) 是另一个分布式文件系统,用于托管 Google 内部应用程序的状态。 GFS 使用简单的设计,使用单个主服务器来托管整个元数据,并将数据分成块并存储在块服务器中。然而,GFS 主服务器现在使用 Chubby 抽象来实现容错。Bayou 是一个分布式的关系数据库系统,允许断开连接的操作,并提供最终的数据一致性。在这些系统中,Bayou、Coda 和 Ficus 允许断开连接的操作,并对网络分区和中断等问题具有弹性。这些系统的冲突解决程序各不相同。例如,Coda 和 Ficus 执行系统级冲突解决,而 Bayou 允许应用程序级解决。然而,所有这些都保证了最终的一致性。与这些系统类似,Dynamo 允许在网络分区期间继续进行读取和写入操作,并使用不同的冲突解决机制解决更新冲突,如一些客户端驱动。传统的复制关系数据库系统关注的是保证复制数据的强一致性问题。尽管强一致性为应用程序编写者提供了一种方便的编程模型,但这些系统在可扩展性和可用性方面受到限制[10]。这些系统无法处理网络分区,因为它们通常提供强大的一致性保证(CAP理论)。

Dynamo 是亚马逊用来存储和检索用户购物车的存储系统。Dynamo 基于 Gossip 的成员资格算法(membership algorithm)可帮助每个节点维护有关每个其他节点的信息。 Dynamo 可以定义为一个结构化的覆盖,最多具有一跳请求路由。Dynamo 使用矢量时钟方案检测更新的冲突,但更倾向于客户端冲突解决机制。Dynamo 中的写入操作还需要执行读取以管理向量时间戳。在系统需要处理非常高的写入吞吐量的环境中,这可能会受到很大限制。Bigtable 提供结构和数据分布,但依赖于分布式文件系统的持久性。

3.数据模型

Cassandra 中的表是由键索引的分布式多维映射。值是高度结构化的对象。表中的行键(row key)是一个没有大小限制的字符串,尽管通常有 16 到 36 个字节长。无论读取或写入多少列,单个行键下的每个操作在每个副本上都是原子的。列被分组到一个集合中,这个集合被称为列族(column families),这与 Bigtable 系统中发生的情况非常相似。 Cassandra 公开了两种列族,简单列族和超列族。可以将超列族视作是列族中的一个列族。

此外,应用程序可以指定超列族或简单列族中列的排序顺序。系统允许按时间或名称对列进行排序。收件箱搜索等应用程序利用列的时间排序,其中结果始终按时间排序顺序显示。使用规约 column_family:column 访问列族中的任何列,使用 column_family:super_column:column 访问列族中属于 super 类型的任何列。6.1 节给出了超列族抽象能力的一个很好的例子。通常应用程序使用一个专用的 Cassandra 集群并将它们作为其服务的一部分进行管理。尽管系统支持多个表的概念,但所有部署的架构中只有一个表。

4.API

Cassandra API 由以下三种简单的方法组成:

  • insert(table, key, rowMutation)
  • get(table, key, columnName)
  • delete(table, key, columnName)

columnName 可以引用列族中的特定列、列族、超列族或超列族中的列族。

5.系统架构

需要在生产环境中运行的存储系统的架构很复杂。系统除了实际的数据持久化组件外,还需要具备以下特点;用于负载平衡、成员资格和故障检测、故障恢复、副本同步、过载处理、状态转移、并发和作业调度、请求编组(request marshalling)、请求路由、系统监控和警报以及配置管理的可扩展且强大的解决方案。描述每个解决方案的细节超出了本文的范围,因此我们将重点介绍 Cassandra 中使用的核心分布式系统技术:分区、复制、成员资格、故障处理和扩展。所有这些模块都是以同步工作的方式处理读取/写请求。通常,对键的读/写请求会被路由到 Cassandra 集群中的任何节点。然后该节点确定该特定键的副本。对于写入,系统将请求路由到副本并等待一定数量的副本确认写入完成(waits for a quorum of replicas to acknowledge the completion of the writes)。对于读取,根据客户端要求的一致性保证,系统要么将请求路由到最近的副本,要么将请求路由到所有副本并等待法定人数(a quorum of)的响应。

译者注:关于 Quorum 相关知识点,可以详见《分布式系统模式-Quorum》

5.1 分区(Partitioning)

Cassandra 的关键设计特性之一是增量扩展的能力。这需要能够在集群中的一组节点(即存储主机)上动态划分数据。Cassandra 使用一致性哈希在集群中对数据进行分区,但使用了一个保持顺序的哈希函数。在一致性哈希中,哈希函数的输出范围被视为一个固定的圆形空间或“环”(即最大的哈希值环绕到最小的哈希值)。在这段空间中,系统中的每个节点都是一个带符号的随机值,表示它在环上的位置。通过对数据项的键进行哈希处理以产生其在环上的位置,然后将由键标识的每个数据项分配给一个节点,然后顺时针遍历环以找到位置大于该项位置的第一个节点。此节点被视为此键的协调器。应用程序指定此键,Cassandra 使用它来路由请求。因此,每个节点都负责环中它与其在环上的前任节点之间的区域。一致性哈希的主要优点是节点的断开或连接仅影响其直接邻居,而其他节点不受影响。一致性哈希算法提出了一些挑战。首先,环上每个节点的随机位置分配导致数据和负载分布不均匀。其次,基本算法忽略了节点性能的异质性。通常有两种方法来解决这个问题:一种是将节点分配到圆中的多个位置(如在 Dynamo 中),第二种是分析环上的负载信息,让负载较轻的节点在环上移动,以减轻负载较重的节点。Cassandra 选择后者,因为它使设计和实现非常容易处理,并有助于对负载平衡做出非常确定的选择。

译者注:关于一致性哈希算法的细节可以详见:https://kb.cnblogs.com/page/42734/

5.2 复制(Replication)

Cassandra 使用复制来实现高可用性和持久性。每个数据项在N台主机上复制,其中N是“每个实例”配置的复制因子。每个键k都分配给一个协调节点(在上一节中描述)。协调器负责在其范围内的数据项的复制。此外,除了本地存储其范围内的每个键,协调器还在环中的 N-1 个节点上复制这些键。Cassandra 为客户提供了各种数据复制方式的选项。Cassandra 提供了各种复制策略,例如“机架非感知(Rack Unaware)”、“机架感知(Rack Aware)”(在数据中心内)和“数据中心感知(Datacenter Aware)”。副本是根据应用程序选择的复制策略选择的。如果某个应用程序选择"Rack Unaware"复制策略,则通过选择环上协调器的 N-1 个后继节点来选择非协调器副本。对于"Rack Aware"和"Datacenter Aware"策略,算法稍微复杂一些。Cassandra 系统使用一个叫做 Zookeeper 的系统在它的节点中选举一个 leader。加入集群的所有节点都会与 leader 交互,leader 告诉他们是哪些范围的副本,领导者尽力维护不变量,即没有节点负责环中超过 N-1 个范围。有关节点负责范围的元数据在每个节点都会本地缓存,并在 Zookeeper 内部以容错方式缓存;这样,即使节点崩溃了,但是由于知道它负责的范围可以迅速进行恢复。我们借用 Dynamo 的说法,并将负责给定范围的节点视为该范围的“偏好列表”。

如第 5.1 节所述,每个节点都知道系统中的每个其他节点,因此知道它们负责的范围。Cassandra 通过放宽 5.2 节中描述的仲裁要求(quorum requirements),在存在节点故障和网络分区的情况下提供持久性保证。数据中心会由于停电、冷却故障、网络故障和自然灾害等发生故障。Cassandra 的配置使得每一行都可以跨多个数据中心进行复制。本质上,键的偏好列表是这样构造的:即存储节点分布在多个数据中心。这些数据中心通过高速网络链路连接(high speed network links)。这种跨多个数据中心进行复制的方案使我们能够处理整个数据中心的故障而不会出现任何中断。

译者注:Leader 选举是通过 Zookeeper 完成的,关于选举相关知识点,可以详见《分布式系统模式-Leader-Followers》

5.3 成员资格(Membership)

Cassandra 中的集群成员资格基于 Scuttlebutt,这是一种非常有效的基于 Gossip 的反熵机制。 Scuttlebutt 的显着特点是它具有非常高效的 CPU 利用率以及 gossip 通道的高利用率。在 Cassandra 系统内,Gossip 不仅用于成员资格,还用于传播其他系统相关的控制状态。

译者注:关于 Gossip 协议可详见《分布式系统模式-Gossip 协议》

5.3.1 故障检测(Failure Detection)

故障检测是一种机制,通过这种机制,节点可以在本地确定系统中其他任何节点是否正常运行。在 Cassandra 中,故障检测还用于避免在各种操作期间试图与不可达节点通信。Cassandra 使用Phiφ积累故障检测(Phi φ Accrual Failure Detection)的修改版本。 Accrual Failure Detection 的方法是,故障检测模块不会发出一个布尔值来说明节点是否启动或关闭。相反,故障检测模块会发出一个表示每个受监控节点的猜想级别(suspicion level)的值。 该值定义为 φ。基本思想是在一个动态调整的尺度上表达 φ 的值,以反映受监控节点的网络和负载状况。φ 具有以下含义:给定某个阈值 φ,并假设我们决定在 φ = 1 时猜想是节点A,那么我们将犯错的可能性(即该决定在未来会因接收到心跳延迟)约为10%φ = 2 的可能性约为1%φ = 3 的可能性约为0.1%,以此类推。系统中的每个节点都维护着一个滑动窗口,该窗口是来自集群中其他节点的 gossip 消息的到达时间间隔。 确定这些到达间隔时间的分布并计算 φ。 尽管原始论文表明该分布近似于高斯分布(Gaussian distribution),但由于 gossip 通道的性质及其对延迟的影响,我们发现指数分布(Exponential distribution)是一个更好的近似值。据我们所知,我们在基于 Gossip 的环境中实施的 Accrual Failure Detection 是同类中的第一个。 Accrual Failure Detector 在准确性和速度方面都非常出色,并且它们还可以很好地适应网络条件和服务器负载条件。

5.4 引导启动(Bootstrapping)

当一个节点第一次启动时,它会为其在环中的位置选择一个随机令牌。 为了容错,映射被持久化到本地磁盘和 Zookeeper 中。然后令牌信息在集群中传播。这就是我们知道所有节点及其在环中各自位置的方式。这使任何节点都可以将键请求路由到集群中的正确节点。在 bootstrap 案例中,当一个节点需要加入集群时,它会读取其配置文件,该配置文件包含集群内一些联系点的列表(list of a few contact points)。我们称这些初始接触点为集群的种子(Seeds)。种子也可以来自像 Zookeeper 这样的配置服务。在 Facebook 的环境中,节点中断(由于故障和维护任务)通常是暂时的,但可能会持续较长时间。故障可能有多种形式,例如磁盘故障、CPU 故障等。节点中断很少表示永久中断,因此不应导致重新平衡分区分配或修复无法访问的副本。同样,手动错误可能会导致意外启动新的 Cassandra 节点。为此,每条消息都包含每个 Cassandra 实例的集群名称。如果配置中的手动错误导致节点尝试加入错误的 Cassandra 实例,它可能会根据集群名称进行阻止。由于这些原因,使用显式机制来发起从一个 Cassandra 实例中添加和删除节点的这种方法是合适的。管理员使用命令行工具或浏览器连接到 Cassandra 节点并发出成员资格更改以加入或离开集群。

5.5 集群扩容(Scaling the Cluster)

当一个新节点被添加到系统中时,它会被分配一个令牌,这样它就可以减轻一个负载很重的节点。这导致新节点会承担一个其他节点以前负责的范围(分流)。操作员使用命令行实用程序或 Cassandra Web 仪表板从系统中的任何其他节点启动 Cassandra 引导算法。 放弃数据的节点使用内核-内核复制技术将数据流到新节点。 操作经验表明,数据可以从单个节点以 40 MB/秒的速率传输。 我们正在努力通过让多个副本参与引导传输来改进这一点,从而使工作并行化,类似于 Bittorrent。

5.6 本地持久化(Local Persistence)

Cassandra 系统依赖本地文件系统进行数据持久化。数据在磁盘上使用一种格式表示,该格式有助于高效数据检索。典型的写入操作包括实现持久性和可恢复性的写入提交日志以及更新内存中的数据结构。只有在成功写入提交日志后才会写入内存数据结构。我们在每台机器上都有一个专门用于提交日志的磁盘,因为所有写入到提交日志的操作都是顺序的,所以我们可以最大限度地提高磁盘吞吐量。当内存中的数据结构超过某个阈值(根据数据大小和对象数量计算得出)时,它会将自身转储到磁盘。这种写入是在机器配备的许多普通磁盘中的一个磁盘上执行的。所有写入都是按顺序写入磁盘的,并且还会根据行键生成索引以进行有效查找。这些索引也与数据文件一起保存。随着时间的推移,磁盘上可能存在许多这样的文件,并且合并过程在后台运行以将不同的文件整理到一个文件中。这个过程与 Bigtable 系统中发生的压缩过程非常相似。

典型的读取操作首先查询内存中的数据结构,然后再查看磁盘上的文件。这些文件按时间最新到最旧的顺序查看。当发生磁盘查找时,我们可能会在磁盘上的多个文件中查找一个键。为了防止找到不存在该键的文件,布隆过滤器,汇总文件中的键,也存储在每个数据文件中,并保存在内存中。首先使用这个布隆过滤器(bloom filter)来检查正在查找的键是否确实存在于给定的文件中。列族中的一个键可以有很多列。需要一些特殊的索引来检索离键较远的列。为了防止扫描磁盘上的每一列,我们维护列索引,这允许我们跳转到磁盘上的正确块以进行列检索(译者注:就类似于b+树的索引映射磁盘过程)。当给定键的列被序列化并写入磁盘时,我们在每 256K 的块边界处生成索引。这个边界是可配置的,但我们发现 256K 在我们的生产工作负载中工作得很好。

5.7 实现细节

单机上的 Cassandra 进程主要由以下几个抽象部分组成:分区模块、集群成员和故障检测模块以及存储引擎模块。这些模块都依赖于一个事件驱动基层(event driven substrate ),其中消息处理管道(message processing pipeline)和任务管道(task pipeline)沿着 SEDA(分阶段的事件驱动架构,stage event driver architecture) 结构模型被分割为多个阶段。这些模块中的每一个都是使用 Java 从头开始实现的。集群成员和故障检测模块,建立在使用非阻塞I/O的网络层之上。所有系统控制消息依赖于基于 UDP 的消息,而应用程序相关的复制消息和请求路由依赖于 TCP。请求路由模块是使用特定的状态机来实现的。当读/写请求到达集群中的任何节点时,状态机会通过以下状态变换:(i)识别拥有密钥数据的节点(ii)将请求路由到节点并等待响应到达(iii)如果回复没有在配置的超时值内到达,则请求失败并返回给客户端(iv)根据时间戳计算出最近的响应(v)如果任何副本没有最新的数据块,则安排对该副本的数据进行修复。为了说明,这里不谈故障场景。系统可以配置是执行同步写入还是异步写入。对于某些需要高吞吐量的系统,我们依赖异步复制。这里的写操作远远超过系统的读操作。在同步情况下,我们在将结果返回给客户端之前等待一定数量(a quorum of)的响应。

在任何有日志记录的系统中,都需要存在一种清洗(purging)提交日志条目的机制。在 Cassandra 中,我们使用滚动提交日志,在旧的提交日志超过特定的、可配置的阈值大小后,新的提交日志被滚出。我们发现,在 128MB 大小之后滚动提交日志在我们的生产工作负载中似乎工作得很好。(译者注:这里其实指的是日志分段与压缩。整个过程的写入都是顺序写的)每个提交日志都有一个 header 头,它基本上是一个位向量,它的大小是固定的,通常超过特定系统将处理的列族的数量。在我们的实现中,我们有一个内存数据结构和一个每个列族生成的数据文件。每次将特定列族的内存数据结构转储到磁盘时,我们都会在提交日志中设置它的位,说明这列族已成功保存到磁盘。这表明该信息已被提交。这些位向量是每个提交日志的,并且也在内存中维护。每次滚动提交日志时,它的位向量和在滚动之前滚动的所有提交日志的位向量都会被检查。如果认为所有数据都已成功持久化到磁盘,那么这些提交日志将被删除。对提交日志的写入操作可以是正常模式,也可以是快速同步模式。在快速同步模式下,对提交日志的写入被缓冲。这意味着机器崩溃时可能会丢失数据。在这种模式下,我们还以缓冲的方式将内存中的数据结构转储到磁盘。传统数据库并非旨在处理特别高的写入吞吐量。Cassandra 将所有对磁盘的写变为顺序写,从而最大限度地提高磁盘写吞吐量。由于转储到磁盘的文件永远不会发生变化,因此在读取它们时不需要获取锁。对于读/写操作,Cassandra 的服务器实例实际上是无锁的。因此,我们不需要处理或处理基于 B-Tree 的数据库实现中存在的并发问题。

Cassandra 系统根据主键对所有数据进行索引。磁盘上的数据文件被分解成一系列块。每个块最多包含128个键,并由一个块索引分隔。块索引捕获块内键的相对偏移量及其数据的大小。当内存中的数据结构转储到磁盘时,会生成一个块索引,并将它们的偏移量作为索引写入磁盘。该索引也保存在内存中以便快速访问。典型的读操作总是首先在内存数据结构中查找数据。如果数据被找到,则将其返回给应用程序,因为内存中的数据结构包含任何键的最新数据。如果未找到,则我们以相反的时间顺序对磁盘上的所有数据文件执行磁盘 I/O。因为我们总是在寻找最新的数据,所以我们首先查看最新的文件,如果找到数据就返回。随着时间的推移,磁盘上的数据文件数量会增加。我们执行压缩过程,非常类似于 Bigtable 系统,它将多个文件合并为一个;本质上是对一堆已排序的数据文件进行合并排序。系统将始终压缩在大小方面彼此接近的文件,即永远不会出现将 100GB 文件与小于 50GB 的文件压缩的情况。定期运行一个主要的压缩过程,将所有相关的数据文件压缩成一个大文件。此压缩过程是磁盘 I/O 密集型操作。可以进行许多优化以不影响即将到来的读取请求。

关于日志分段相关只是可以详见《分布式系统模式-日志分段》

关于日志压缩的主要过程可以阅读《设计数据密集型应用》,这里给出译者相关的了解内容,传送门:日志结构的合并树

6.实践经验

在设计、实施和维护 Cassandra 的过程中,我们获得了很多有用的经验并吸取了很多教训。一个非常基本的教训是,在不了解应用程序使用的影响的情况下,不要添加任何新功能。 大多数有问题的场景不仅仅源于节点崩溃和网络分区。我们在这里只分享一些有趣的场景。

  • 在启动收件箱搜索应用程序之前,我们必须为超过1亿用户索引 7TB 的收件箱数据,然后存储在我们的 MySQL 基础设施中,并将其加载到 Cassandra 系统中。整个过程涉及到对 MySQL 数据文件运行 Map/Reduce 作业,对它们进行索引,然后将反向索引存储在 Cassandra 中。M/R 过程实际上表现为 Cassandra 的客户端。我们为 M/R 进程公开了一些后台通道,以聚合每个用户的反向索引并将序列化数据发送到 Cassandra 实例,以避免序列化/反序列化开销。这样,Cassandra 实例只会受到网络带宽的限制。
  • 多数应用程序只需要对每个副本的每个键进行原子操作。然而,也有一些应用程序要求进行事务处理,主要是为了维护二级索引。大多数具有多年使用 RDBMS 开发经验的开发人员发现这是一个非常有用的特性。我们正在研究一种机制来公开这种原子操作。
  • 我们尝试了各种故障检测器的实现,例如 [15] 和 [5] 中描述的那些。我们的经验是,随着集群大小的增加,检测故障的时间会增加到超过可接受的限度。在一个包含 100 个节点的集群中的特定实验中,检测故障节点所需的时间大约为两分钟。这在我们的环境中实际上是行不通的。采用权责发生故障检测器,PHI值略保守,设置为5,上述实验中检测故障的平均时间约为15秒。
  • 监测不应被视为理所当然。Cassandra 系统与分布式性能监控工具 Ganglia 很好地集成在一起。我们向 Ganglia 公开了各种系统级指标,这有助于我们了解系统在生产工作负载下的行为。磁盘没有明显的原因出现故障。引导算法有一些钩子可以在磁盘故障时修复节点。然而,这是一个管理操作。
  • 尽管 Cassandra 是一个完全去中心化的系统,但我们已经了解到,一定程度的协调对于使某些分布式功能的实现易于处理至关重要。例如 Cassandra 与 Zookeeper 集成,可用于大规模分布式系统中的各种协调任务。我们打算将 Zookeeper 抽象用于一些实际上不会妨碍使用 Cassandra 作为存储引擎的应用程序的关键特性。

6.1 Facebook 收件箱搜索

对于收件箱搜索,我们为邮件的发件人和收件人之间交换的所有邮件维护每个用户索引。现在启用了两种搜索功能:(a) 词条搜索;(b)交互,给定一个人的名字,返回用户可能从那个人那里发送或接收过的所有消息。该模式由两个列族组成。对于查询(a),用户id是键,组成消息的单词成为超列族(super column)。包含该单词的消息的各个消息标识符成为超列族中的列族。对于查询(b),用户id是键,收件人id是超级列。对于这些每个超列族,单独的消息标识符是列。为了加快搜索速度,Cassandra 提供了一些用于智能缓存数据的钩子。 例如,当用户单击搜索栏时,会向 Cassandra 集群发送一条异步消息,以使用该用户的索引来填充缓冲区缓存。这样,当执行实际搜索查询时,搜索结果很可能已经在内存中(译者注:这是利用缓存局部性原理优化)。该系统目前在一个 150 个节点的集群上存储了大约 50+TB 的数据,该集群分布在东海岸和西海岸的数据中心之间。我们展示了一些用于读取性能的生产测量数据:

延迟状态(Latency Stat) 交互搜索 词条搜索
Min 7.69ms 7.78ms
Median 15.69ms 18.27ms
Max 26.13ms 44.41ms

7.总结

我们已经构建、实现和操作了一个存储系统-提供可伸缩性、高性能和广泛的应用。我们已经通过经验证明,Cassandra 可以在提供低延迟的同时支持非常高的更新吞吐量。未来的工作包括增加压缩、支持跨键原子性和二级索引支持。

原文连接

Cassandra - A Decentralized Structured Storage System