1. 引言

键值存储,也称为键值数据库,是一种非关系型数据库。它通过键值对的方式存储数据,每个键都是唯一的,可以快速地通过键访问到对应的值。键值存储在现代应用中非常广泛,如缓存、消息队列、分布式系统等。本文将详细介绍键值存储的设计原理、核心概念、技术实现以及应用场景。

2. 键值存储的基本概念

2.1 键值对

键值存储的核心是键值对,每个键都是唯一的,与之关联的值可以通过键快速访问。键可以是纯文本或哈希值,通常为了性能考虑,键的长度越短越好。值可以是字符串、列表、字典等,通常被视为不透明对象。

2.2 键值存储的特点

  • 高性能:键值存储通过键直接访问值,具有非常高的读写性能。
  • 高可用性:通过数据复制和分布式架构,键值存储可以在节点故障时继续提供服务。
  • 高可扩展性:键值存储可以根据流量自动扩展,支持大数据集。
  • 灵活的数据模型:键值存储不需要预定义数据模式,可以存储任意类型的数据。

3. 单服务器键值存储

在单个服务器上开发键值存储相对简单,通常使用哈希表将键值对存储在内存中。然而,由于内存空间的限制,单个服务器的存储能力有限。为了在单个服务器上存储更多数据,可以采用以下优化策略:

  • 数据压缩:通过压缩算法减少数据的存储空间。
  • 缓存策略:仅在内存中存储频繁使用的数据,其余数据存储在磁盘上。

尽管有这些优化,单个服务器仍然可能很快达到其容量限制,因此需要分布式键值存储来支持更大的数据集。

4. 分布式键值存储

分布式键值存储将键值对分布在多个服务器上,通过分布式架构实现高可用性、高可扩展性和高性能。在设计分布式系统时,了解CAP定理非常重要。

4.1 CAP定理

CAP定理指出,分布式系统不可能同时提供超过以下三个保证中的两个:一致性、可用性和分区容忍。

  • 一致性:所有客户端看到相同的数据,无论他们连接到哪个节点。
  • 可用性:任何请求数据的客户端即使在某些节点宕机时也能获得响应。
  • 分区容忍:系统在网络分区的情况下继续运行。

根据CAP定理,分布式键值存储系统通常分为以下两类:

  • AP系统:支持可用性和分区容忍,同时牺牲一致性。
  • CP系统:支持一致性和分区容忍,同时牺牲可用性。

image

4.2 系统组件

构建键值存储需要考虑以下核心组件和技术:

  • 数据分区:将数据分成更小的分区,分布在多个服务器上。
  • 数据复制:为了实现高可用性和可靠性,数据必须在多个服务器上异步复制。
  • 一致性:通过法定人数共识等机制保证读写操作的一致性。
  • 不一致性解决:通过版本控制和向量时钟等技术解决数据复制中的不一致性。
  • 处理故障:通过故障检测和数据恢复机制处理节点故障。
  • 系统架构图:描述系统的整体架构和各个组件的交互。
  • 写路径:描述写操作的流程。
  • 读路径:描述读操作的流程。

5. 数据分区

对于大型应用程序,将完整数据集放入单个服务器中是不切实际的。实现这一点的最简单方法是将数据分成更小的分区,并在多个服务器中存储它们。分区数据时有两个挑战:

  • 均匀分布数据:在多个服务器之间均匀分布数据。
  • 最小化数据移动:在添加或删除节点时最小化数据移动。

一致性哈希是一种解决这些问题的技术。服务器被放置在一个哈希环上,键被哈希到同一个环上,并存储在遇到的第一个服务器上,按顺时针方向移动。

image

6. 数据复制

为了实现高可用性和可靠性,数据必须在N个服务器上异步复制。这些N个服务器是根据以下逻辑选择的:在键被哈希到哈希环上的一个位置后,按顺时针方向走,选择环上的第一个N个服务器来存储数据副本。

使用虚拟节点,环上的前N个节点不一定由少于N个物理服务器拥有。为了避免这个问题,我们只选择执行时钟逻辑的唯一服务器。为了更好的可靠性,副本被放置在不同的数据中心,并且数据中心通过高速网络连接。

image

7. 一致性

由于数据在多个节点上复制,必须在副本之间同步。Quorum共识可以保证读写操作的一致性。N表示副本的数量,W表示写操作成功的写入法定人数,R表示读取操作成功的读取法定人数。

  • W = 1:写操作只需等待一个副本的确认,操作会很快返回。
  • R = 1:读操作只需等待一个副本的响应,操作会很快返回。
  • W + R > N:强一致性得到保证,因为必须至少有一个重叠节点拥有最新数据以确保一致性。

根据要求,我们可以调整W、R、N的值以实现所需的一致性水平。

8. 一致性模型

在设计键值存储时,一致性模型是另一个重要的考虑因素。一致性模型定义了数据一致性的程度,以及可能存在的一致性模型的广泛范围:

  • 强一致性:任何读取操作返回与最近更新写入数据相对应的值。
  • 最终一致性:后续读取操作可能会返回过时的数据。
  • 因果一致性:特定形式的弱一致性。给定足够的时间,所有更新都是一致的。
  • 线性一致性:这是强一致性的特定形式。

Dynamo和Cassandra采用最终一致性,这是我们推荐的键值存储的一致性模型。最终一致性允许不一致性与版本控制共存。

9. 不一致性解决/版本控制

复制提高了可用性,但也会引起不一致性。版本控制意味着将每次数据修改视为新不可变版本。向量时钟是一种常见的解决此问题的技术。向量时钟是一个与数据项相关联的<服务器,版本>对,可以用来检查一个版本是否在另一个版本之前、之后或与之冲突。

使用向量时钟,可以轻松判断版本X是否是版本Y的祖先(即没有冲突)或版本Y是否与版本X冲突。向量时钟的大小可能会迅速增长,为了解决这个问题,我们为向量长度设置了一个阈值,如果超过该阈值,则删除最旧的对。

10. 处理故障

与任何大型系统一样,故障不仅不可避免,而且很常见。在本节中,我们首先介绍处理故障的一般策略。然后,我们讨论常见的故障处理策略。

10.1 故障检测

在分布式系统中,仅依赖一个服务器的说法是不够的。通常,需要至少两个独立的信息源来标记服务器为宕机。Gossip协议是一种去中心化故障检测方法。每个节点维护一个包含成员ID和心跳计数器的节点成员列表,定期将心跳发送到一组随机节点。如果心跳在预定时间内没有增加,则认为成员离线。

image

10.2 处理临时故障

在严格的法定人数要求中,读取和写入操作可能会被阻止。一种称为“松弛法定人数”的技术用于提高可用性。系统选择前W个健康服务器进行写入,前R个健康服务器进行读取。忽略离线服务器。如果由于网络故障服务器暂时不可用,另一台服务器将处理请求。当离线服务器恢复时,更改将被推送以实现数据一致性。此过程称为隐式交接。

10.3 处理永久故障

如果副本永久不可用怎么办?为了处理这种情况,我们实现了一种称为反熵协议的协议来保持副本同步。反熵涉及在副本之间交换数据并更新每个副本到最新版本。Merkle树用于不一致性检测和最小化数据传输量。

11. 处理数据中心故障

数据中心故障可能由电源故障、网络故障、自然灾害等引起。为了构建能够处理数据中心故障的系统,重要的是在多个数据中心复制数据。如果一个数据中心完全离线,用户仍然可以通过其他数据中心访问数据。

12. 系统架构图

架构的主要特点如下:

  • 客户端通过简单的API:get(key)和put(key, value)与键值存储通信。
  • 协调器是客户端和键值存储之间的代理节点。
  • 节点分布在使用一致性哈希的环上。
  • 系统完全去中心化,因此添加和移动节点可以自动化。
  • 数据在多个节点上复制。
  • 没有单点故障,因为每个节点具有相同的一组职责。

image

13. 写路径

写请求被持久化到提交日志文件中,数据保存在内存缓存中。当内存缓存已满或达到预定义阈值时,数据被刷新到磁盘上的SSTable。SSTable是一个按键排序的列表<key, value>对。

image

14. 读路径

在读取请求指向特定节点后,它首先检查内存缓存中的数据。如果是,则数据返回给客户端。如果数据不在内存中,它将从磁盘检索。Bloom过滤器通常用于解决此问题。当数据不在内存中时的读取路径如下:

  1. 系统首先检查数据是否在内存中。如果不在,请转到步骤2。
  2. 如果数据不在内存中,系统检查Bloom过滤器。
  3. 使用Bloom过滤器来找出可能包含键的SSTables。
  4. SSTables返回数据集的结果。
  5. 数据集的结果返回给客户端。

image

15. 总结

本章涵盖了许多概念和技术。为了刷新您的记忆,以下表格总结了分布式键值存储中使用的特征和相应技术:

目标/问题技术
能够存储大量数据使用一致性哈希在服务器之间分散负载
高可用性读取多数据中心设置
高可用性写入版本控制和向量时钟
数据集分区一致性哈希
增量可扩展性一致性哈希
异构性一致性哈希
可调一致性法定人数共识
处理临时故障松弛法定人数和隐式交接
处理永久故障Merkle树
处理数据中心故障跨数据中心复制

通过以上内容的学习,我们对键值存储的设计原理、核心概念、技术实现以及应用场景有了全面的了解。键值存储在现代应用中具有重要的地位,掌握其设计和实现方法对于构建高性能、高可用性和高可扩展性的系统非常有帮助。

参考资料
ByteByteGo


float64
1 声望0 粉丝