一个键值存储的设计


一个键值存储的设计

了解功能需求、非功能需求以及键值存储的API设计。

需求

我们列出设计键值存储以克服传统数据库问题的需求。

功能需求

功能需求如下:

  • 可配置的服务: 有些应用程序可能会倾向于以更高的可用性为代价来换取强一致性。我们需要提供可配置的服务,以便不同的应用程序可以使用一系列一致性模型。我们需要严格控制可用性、一致性、成本效益和性能之间的权衡。
  • 始终可写: 应用程序应始终具有写入键值存储的能力。如果用户想要强一致性,则由于CAP定理的影响,这个要求可能并不总是能够满足。
  • 硬件异构性: 系统不应该有区别明显的节点。每个节点应该在功能上能够执行任何任务。尽管服务器可以是异构的,但较新的硬件可能比旧的硬件更有能力。

非功能需求

非功能需求如下:

  • 可扩展性: 键值存储应该运行在数万台分布在全球的服务器上。增量可扩展性是非常可取的。我们应该根据需要添加或删除服务器,并在最小或没有服务中断的情况下进行。此外,我们的系统应该能够处理大量键值存储用户。
  • 可用性: 我们需要提供连续的服务,因此可用性非常重要。这个属性是可配置的。因此,如果用户想要强一致性,我们的可用性就会较低,反之亦然。
  • 容错性: 键值存储应该在服务器或其组件出现故障的情况下不间断地运行。

警告

问题

为什么我们需要在多个服务器上运行键值存储?

答案

基于单节点的哈希表可能因以下一个或多个原因而不足:无论我们得到多大的服务器,这个服务器都无法满足数据存储和查询要求;

这个超级服务器的故障将导致所有人的服务停机。

因此,键值存储应该使用许多服务器来存储和检索数据。

假设

为了使我们的设计简单,我们假设以下内容:

  • 托管服务的数据中心是受信任的(非敌对的)。
  • 所有所需的身份验证和授权已经完成。
  • 用户请求和响应是通过 HTTPS 中继的。

API设计

与普通哈希表一样,键值存储提供了两个主要功能,即 getput

让我们看一下API设计。

get函数

获取值的 API 调用应该如下所示:

get(key)

我们根据参数 key 返回关联的值。

当数据被复制时,它会定位与特定键相关联的对象副本,该键对终端用户隐藏。

如果存储配置为较弱的数据一致性模型,则系统会执行此操作。

例如,在最终一致性下,可能会针对一个键返回多个值。

参数描述
key它是我们要获取valuekey

put函数

将值放入系统的 API 调用应该如下所示:

put(key, value)

它存储与key关联的value。系统会自动确定数据应放置在哪里。

此外,系统通常会保留有关存储对象的元数据。

这样的元数据可以包括对象的版本。

参数描述
key它是我们要存储valuekey
value它是要存储在key上的对象。

相关信息

问题

我们通常为数据完整性检查保留值的哈希(有时为值+关联键),此类哈希应在任何数据压缩或加密之后取还是之前取?

答案

正确的答案可能取决于具体的应用程序。

但我们可以在任何压缩或加密之前或之后使用哈希。

但我们需要始终对putget操作进行一致的处理。

数据类型

键通常是键值存储中的主键,而值可以是任意的二进制数据。

提示

注意: Dynamo 使用MD5哈希在键上生成一个128位的标识符。这些标识符帮助系统确定哪个服务器节点将负责这个特定的键.

在下一课中,我们将学习如何设计我们的键值存储。

首先,我们将专注于向我们的系统添加可伸缩性、复制和数据版本控制。

然后,我们将确保功能需求并使我们的系统具备容错性。

我们首先满足一些非功能需求,因为实现我们的功能需求取决于所选择的可扩展性方法。

相关信息

注意: 本章基于 Dynamo,它是键值存储领域的一个有影响力的工作。