Redis 及其在系统设计中的作用

什么是Redis

Redis 是一个开源的内存数据结构存储系统,可用作数据库、缓存和消息代理。它因其快速的性能、灵活性和易用性而得到广泛应用。

Redis 数据存储类型

Redis 允许开发人员以各种数据结构(例如字符串、位图、位域、哈希、列表、集合、有序集合、地理空间数据、超日志和流)存储、检索和操作数据。

使用 Redis 的优势

所有 Redis 数据都驻留在服务器的主内存中,这与 PostgreSQL、SQL Server 等将大部分数据存储在磁盘上的数据库不同。因此,Redis 可以支持更高数量级的操作和更快的响应时间。因此,它实现了超快的性能,平均读写操作时间不到毫秒,从而支持每秒数百万次的操作。

Redis 提供了一个完整的系统,它为我们提供了两种架构(单片机和分布式)的缓存系统,从而提高了数据检索速度,因为通过内存中的键(例如哈希表)直接访问操作将降低从原始 SQL 数据库读取数据的整体复杂性。

Redis 的工作架构

Redis 架构有多种,具体取决于用例和规模:

1. 单 Redis 实例

这是最直接的 Redis 部署方式。它要求用户设置并运行小型实例,以帮助他们扩展服务并加速其发展。然而,它也有其自身的缺点,因为如果正在运行的实例崩溃或不可用,所有对 Redis 的调用都会失败。因此,系统的整体性能和速度会下降。

单 Redis 实例

2. Redis HA(高可用性)

另一种常见的设置是主部署加上一个始终与副本保持同步的辅助部署。辅助实例在我们的部署中可以是一个或多个实例,这有助于扩展从 Redis 的读取,并在主实例丢失的情况下提供故障转移。

Redis HA(辅助实例故障转移)

3. Redis Sentinel

Sentinel 对应于分布式系统。它的设计理念是,一个哨兵进程集群协同工作,协调状态,从而为 Redis 系统提供持续的可用性。哨兵进程的职责如下:

  • 监控:确保主实例和辅助实例按预期运行。
  • 通知:将 Redis 实例中发生的事件通知所有系统管理员。
  • 故障期间管理:如果主实例长时间不可用,并且有足够多的节点确认故障,哨兵节点可以在故障期间启动一个进程。

Redis 哨兵

  1. Redis 集群/Redis 集群主从模型:Redis 的终极架构

Redis 集群是 Redis 的终极架构。它允许 Redis 进行水平扩展。

在 Redis 集群中,我们决定将存储的数据分散到多台机器上,这称为分片。因此,集群中的每个 Redis 实例都被视为整个数据的一个分片。

Redis 集群使用算法分片。为了找到给定键对应的分片,我们会对键进行哈希运算,并将结果除以分片数量。然后,使用确定性哈希函数(即给定键始终映射到同一个分片),我们可以推断出将来读取特定键时该键的位置。

系统设计中的 Redis 集群架构

为了处理系统中分片的进一步添加(重新分片),Redis 集群使用哈希槽 (Hashslot),所有数据都映射到该哈希槽。因此,当我们添加新的分片时,我们只需将哈希槽从一个分片移动到另一个分片,从而简化了向集群添加新主实例的过程。这样做的好处是,无需停机,并且性能影响最小。我们来看下面的示例:

假设哈希槽的数量为 10K。

实例 1 包含从 0 到 5000 的哈希槽,

实例 2 包含从 5001 到 10000 的哈希槽。

现在,假设我们需要添加另一个实例,那么哈希槽的分布如下:

实例 1 包含从 0 到 3333 的哈希槽。

实例 2 包含从 3334 到 6667 的哈希槽。

实例 3 包含从 6668 到 10000 的哈希槽。

Redis 集群中的 gossiping 是什么?

为了确定整个集群的健康状况,Redis 集群使用 gossiping。在下面的示例中,我们有 3 个主实例和 3 个辅助节点。所有这些节点都会不断确定哪些节点当前可用于处理请求。假设有足够多的分片一致认为实例 1 没有响应,它们就可以将实例 1 的辅助节点提升为主节点,以保持集群的健康。一般来说,为了实现最强健和容错的网络,主节点数量必须为奇数,并且每个节点有两个副本。

Redis 持久化模型的类型

Redis 提供了两种主要的持久化选项来将数据保存到磁盘:RDB 和 AOF。这两种选项各有优缺点,具体使用哪种取决于应用程序的具体需求。以下列出了几种持久化选项:

1. RDB(实时数据库)持久化模型:

RDB 是 Redis 数据集的即时快照,以二进制文件的形式存储。RDB 文件包含数据集在特定时间点的表示形式,可用于在服务器崩溃或重启时恢复数据集。由于 RDB 采用二进制格式存储数据,因此在磁盘空间利用率和性能方面非常高效。

RDB 可以配置为定期保存数据,或者根据某些条件(例如最小写入操作次数)保存数据。然而,RDB 的缺点是,如果服务器在按计划创建 RDB 快照之前崩溃,则可能导致数据丢失。

RDB 中的快照

快照是 Redis 持久化过程中的一个过程,它会在内存中创建整个数据集的时间点快照,并将其以二进制格式保存到磁盘。此快照可用于在服务器崩溃或重启时恢复数据集。Redis 通过其 RDB 持久化机制支持快照。

快照的工作原理如下:

  • Redis 从父进程派生出一个子进程。
  • 子进程在内存中创建数据集当前状态的副本。
  • 子进程将数据集副本写入临时 RDB 文件。
  • 子进程将临时文件重命名为最终的 RDB 文件名,并覆盖所有现有的 RDB 文件。
  • 子进程终止,Redis 继续处理请求。

Redis 可以配置为定期自动执行快照,或根据某些条件(例如最小写入操作次数或自上次快照以来经过的最短时间)执行快照。如果我们正在进行繁重的工作并更改大量键,那么每分钟将生成一个快照;如果更改相对较少,则每 5 分钟生成一个快照;如果更改更少,则每 15 分钟生成一个快照。

RDB(实时数据库)的优势

  • RDB 文件非常适合备份,因为它是 Redis 数据非常紧凑的单文件时间点表示。它使我们能够在发生灾难时轻松恢复数据集的不同版本。
  • 它非常适合灾难恢复,因为它是一个可以传输到远程数据中心的单个紧凑文件。

RDB(实时数据库)的劣势

现在让我们比较一下 Redis DB 的劣势:

  • RDB 并非最佳选择。
  • 如果我们需要最大限度地降低 Redis 停止工作时数据丢失的可能性,
  • 我们可以配置生成 RDB 的不同保存点。但是,我们通常每五分钟或更长时间就会创建一个 RDB 快照,因此,如果 Redis 由于任何原因而未正确关闭而停止工作,我们应该准备好丢失最新几分钟的数据。

2. AOF(仅追加文件)持久化模型

AOF 将所有写入操作以人类可读的格式记录到一个文件中。该文件包含自上次保存以来对数据集执行的所有写入操作的记录,以便在发生崩溃时重建数据集。AOF 比 RDB 具有更好的持久性,因为它将每个写入操作都记录到磁盘。

AOF 可以配置为定期保存数据,或根据某些条件(例如最小写入操作次数)保存数据。但是,由于 AOF 会将每个写入操作都记录到磁盘,因此会导致性能下降和磁盘空间占用增加。

由于快照的持久性较差,因此仅追加文件是 Redis 的另一种完全持久化策略。

可以通过以下方式在配置文件中启用 AOF:

复制代码
appendonly yes

AOF 的工作原理?

  • Redis 会从父进程 fork 一个子进程。
  • 子进程会在内存中创建数据集当前状态的副本。
  • 子进程将数据集的副本写入临时文件中的新 AOF 文件。
  • 父进程将所有新的更改累积到内存缓冲区中(但同时,它会将新的更改写入旧的仅追加文件,因此如果重写失败,我们是安全的)。
  • 当子进程完成文件重写后,父进程会收到信号,并将内存缓冲区中的更改追加到子进程生成的文件末尾。
  • 然后,Redis 会自动将旧文件重命名为新文件,并开始将新数据追加到新文件中。

AOF 的优势

  • Redis 的 AOF 日志更加持久,因为我们可以采用不同的 fsync 策略,例如完全不 fsync、每秒 fsync 或每次查询时 fsync。
  • 它是一个仅追加的日志,因此不会出现寻道,也不会在断电时出现损坏问题。
  • 如果日志由于磁盘已满或其他原因突然结束,Redis 的检查工具可以自动修复任何写入一半的命令。

AOF 的缺点

现在让我们比较一下 AOF 的缺点:

  • 对于相同的数据集,这些文件通常比等效的 RDB 文件更大。
  • 根据具体的 fsync 策略,它可能比 RDB 慢。
  • AOF 可以提高数据一致性,但不能保证数据完全一致。数据丢失的可能性很小,但考虑到 RDB 速度更快,丢失数据的可能性比 RDB 模式要小。

选择哪个------实时数据库 (RDB) 还是追加文件 (AOF)?

通常的思路是,如果我们想要获得与 PostgreSQL 等普通数据库相当的数据安全性,我们应该同时使用这两种持久化方法。如果我们非常重视数据,但又能忍受灾难发生时几分钟的数据丢失,那么我们可以只使用 RDB。

3. 无持久化模型

Redis 还提供了完全禁用持久化的选项,在这种情况下,数据仅存储在内存中。当 Redis 用作缓存时,此选项非常有用,因为数据丢失后可以重新生成。

4. 混合 (RDB+AOF) 持久化模型

Redis 提供了同时使用 RDB 和 AOF 持久化的选项,这被称为混合持久化。此选项兼具 RDB 和 AOF 的优点,因为 AOF 日志用于在重启后重放写入操作,而 RDB 快照用于在特定时间点恢复数据集。

Redis 中的可用性、一致性和分区

以下是 Redis 如何处理可用性、一致性和分区的简要概述:

  • 可用性:Redis 使用主从复制模型来确保高可用性。这意味着有一个"主"节点接受所有写入操作,还有多个"从"节点实时从主节点复制数据。如果主节点发生故障,可以将其中一个从节点提升为新的主节点。
  • 一致性:Redis 为单键操作提供强一致性保证,这意味着如果将值写入某个键,集群中的任何节点都可以立即读取该值。但是,Redis 不为多键操作提供事务一致性,这意味着某些节点可能看到与其他节点不同的数据视图。
  • 分区:Redis 支持分片,允许将数据集分区到多个节点。Redis 使用基于哈希的分区方案,其中每个键根据其哈希值分配给特定节点。Redis 还提供了一种在集群中添加或删除节点时重新分配数据的机制。

我们可以使用 Redis 来替代原始数据库吗?

基于以上讨论,Redis 似乎是原始数据库的更好选择,因为它提供了更快的检索速度。即便如此,Redis 也不会被用作系统中数据库的主要选项。

Redis 应该始终作为提升整体系统性能的第二支撑,因为根据 CAP 定理,Redis 既不具备一致性,也不具备高可用性。

这是因为,如果服务器崩溃,我们将丢失内存中的所有数据。崩溃时丢失这些数据是可以接受的,但对于某些其他应用来说,在服务器重启后立即重新加载 Redis 数据就变得非常重要。

结论

总的来说,Redis 是一个强大的系统设计工具,但它可能并不适合所有用例。在决定是否在特定应用程序中使用 Redis 时,务必仔细考虑其局限性。

相关推荐
冰^8 分钟前
MySQL VS SQL Server:优缺点全解析
数据库·数据仓库·redis·sql·mysql·json·数据库开发
电商数据girl19 分钟前
产品经理对于电商接口的梳理||电商接口文档梳理与接入
大数据·数据库·python·自动化·产品经理
zru_960236 分钟前
Docker 部署 Redis:快速搭建高效缓存服务
redis·缓存·docker
axinawang1 小时前
springboot整合redis实现缓存
spring boot·redis·缓存
Spring小子1 小时前
黑马点评商户查询缓存--缓存更新策略
java·数据库·redis·后端
溜溜刘@♞3 小时前
数据库之mysql优化
数据库·mysql
for623 小时前
本地缓存大杀器-Caffeine
缓存·caffeine·本地缓存
uwvwko3 小时前
ctfhow——web入门214~218(时间盲注开始)
前端·数据库·mysql·ctf
柯3493 小时前
Redis的过期删除策略和内存淘汰策略
数据库·redis·lfu·lru
Tiger_shl4 小时前
【Python语言基础】24、并发编程
java·数据库·python