将Redis作为复杂应用程序的主要数据库

首先,我们将了解Redis是什么以及它的用途,以及为什么它适用于现代复杂的微服务应用程序。我们将讨论Redis如何通过其模块支持存储多种数据格式以供不同用途。接下来,我们将看到Redis作为内存数据库如何持久化数据并从数据丢失中恢复。我们还将谈论Redis如何使用Redis on Flash优化内存存储成本。

然后,我们将看到Redis扩展和在多个地理区域复制的非常有趣的使用案例。最后,由于运行微服务的最流行平台之一是Kubernetes,而在Kubernetes中运行有状态应用程序略显具有挑战性,我们将看到如何轻松在Kubernetes上运行Redis。

什么是Redis?

Redis实际上代表着远程字典服务器,是一个内存数据库。许多人将其用作其他数据库顶部的缓存以提高应用程序性能。然而,许多人不知道的是,Redis是一个完全成熟的主数据库,可用于存储和持久化多种数据格式以供复杂的应用程序使用。

复杂社交媒体应用示例

让我们看看微服务应用程序的一个常见设置。假设我们有一个复杂的社交媒体应用程序,拥有数百万用户。并且假设我们的微服务应用程序使用像 MySQL 这样的关系数据库来存储数据。此外,由于我们每天收集大量数据,我们还拥有一个Elasticsearch 数据库用于快速过滤和搜索数据。

现在,用户之间彼此相连,因此我们需要一个图数据库来表示这些连接。此外,我们的应用程序有大量用户每天共享的媒体内容,为此,我们有一个文档数据库。最后,为了提高应用程序性能,我们有一个缓存服务,可以缓存来自其他数据库的数据,并使其更快地可用。

现在,很明显这是一个相当复杂的设置。让我们看看这个设置面临的挑战:

1. 部署和维护

所有这些数据服务都需要部署、运行和维护。这意味着你的团队需要对如何操作所有这些数据服务有一定的了解。

2. 扩展和基础设施要求

为了实现高可用性和更好的性能,你可能希望扩展你的服务。每个数据服务的扩展方式不同,基础设施要求也不同,这可能是一个额外的挑战。因此,总的来说,使用多个数据服务来支持你的应用程序增加了维护整个应用程序设置的工作量。

3. 云成本

当然,作为一个更简单的选择,你可以使用云提供商提供的托管数据服务,而不是自己运行和管理服务。但这可能会非常昂贵,因为在云平台上,你需要为每个托管数据服务单独付费。

4. 开发复杂性

On the development side, your application code also gets pretty complex because you need to talk to multiple data services. For each service, you would need a separate connector and logic. This makes testing your applications also quite challenging.

5. 更高的延迟

The more number of services that talk to each other, the higher the latency. Even though each service may be fast on its own, each connection step between the services or each network hop will add some latency to your application.

为何 Redis 简化了这种复杂性

与 Redis 这样的多模式数据库相比,你解决了大部分这些挑战:

  1. 单一数据服务 你只运行和维护一个数据服务。因此,你的应用程序也只需要与单个数据存储交互,这意味着该数据服务仅有一个编程接口。
  2. 减少延迟。通过访问单个数据端点并消除多个内部网络跳跃,延迟将会减少。
  3. 一个中存储多种数据类型 拥有一个像 Redis 这样的数据库,可以让你存储不同类型的数据(即一个数据库中包含多种类型的数据库)同时充当缓存,解决了这些挑战。

Redis 如何支持多种数据格式

那么,让我们看看 Redis 是如何实际工作的。首先,Redis 如何支持单个数据库中的多种数据格式?

Redis 核心和模块

它的工作方式是你有一个Redis核心,它是一个支持存储多种数据类型的键值存储。然后,你可以通过所谓的模块扩展该核心,用于不同目的的数据类型,这是你的应用程序所需要的。例如:

  • RedisSearch用于搜索功能(类似于Elasticsearch)
  • RedisGraph用于图形数据存储

这种方式的一个很好的地方是它是模块化的。这些不同类型的数据库功能不像许多其他多模式数据库那样紧密集成在一个数据库中,而是,你可以精确选择你的应用程序所需的数据服务功能,然后基本上添加那个模块。

内置缓存

当然,当将Redis用作主数据库时,你不需要额外的缓存,因为Redis已经自动提供了这个功能。这意味着,在你的应用程序中再次减少了复杂性,因为你不需要实现管理、填充和使缓存失效的逻辑。

高性能和更快的测试

最后,作为一种内存数据库,Redis 非常快速且高性能,这当然会使应用程序本身更快。此外,它还能使运行应用程序测试变得更快,因为 Redis 不像其他数据库那样需要模式。因此,在运行测试之前,它不需要时间来初始化数据库、构建模式等等。您可以每次都从空的 Redis 数据库开始,并根据需要为测试生成数据。快速的测试确实可以提高您的开发效率。

Redis 中的数据持久性

我们了解了 Redis 的工作原理及其所有优势。但是在这一点上,您可能会想知道:内存数据库如何持久化数据因为如果 Redis 进程或 Redis 运行的服务器失败,内存中的所有数据都会丢失,对吧?如果数据丢失了,我该如何恢复它?因此,基本上,我如何确信我的数据是安全的?

备份数据的最简单方式是通过复制 Redis。因此,如果 Redis 主实例宕机,副本仍将运行且具有所有数据。如果您有复制的 Redis,则副本将具有数据。但是,当然,如果所有 Redis 实例都宕机,您将丢失数据,因为将不再有副本存在。

我们需要真正的持久性

快照(RDB)

Redis有多种机制来持久化数据并确保数据安全。第一个是快照,你可以根据时间、请求数等进行配置。您的数据快照将存储在磁盘上,如果整个Redis数据库消失,您可以使用它来恢复数据。但请注意,您将会丢失最后几分钟的数据,因为通常每五分钟或每小时进行一次快照,具体取决于您的需求。

AOF(Append Only File)

作为另一种选择,Redis使用了一种称为AOF的机制,全称为Append Only File。在这种情况下,每个更改都会持续保存到磁盘以确保持久性。当重新启动Redis或发生宕机时,Redis将重新播放Append Only File日志以重建状态。因此,AOF更持久,但可能比快照慢。

快照和AOF的结合

当然,您也可以同时使用AOF和快照的组合,其中追加日志文件持续将数据从内存保存到磁盘,同时定期进行快照以保存数据状态,以防需要恢复数据。这意味着即使Redis数据库本身或运行Redis的服务器及其底层基础设施全部发生故障,您仍然可以安全地保留所有数据,并且可以轻松地重新创建和启动一个新的Redis数据库,并恢复所有数据。

持久化存储在哪里?

一个非常有趣的问题是,持久化存储在哪里?那个存储快照和追加日志文件的磁盘位于何处?它们是否位于运行Redis的相同服务器上?

这个问题实际上引导我们讨论在云环境中数据持久性的趋势或最佳实践,即最好将运行应用程序和数据服务的服务器与存储数据的持久性存储分开

举个具体的例子:如果您的应用程序和服务在云上运行,比如在AWS EC2实例上,您应该使用EBS或弹性块存储来持久化您的数据,而不是将其存储在EC2实例的硬盘上。因为如果那个EC2实例出现故障,您将无法访问任何存储在上面的数据,无论是RAM还是磁盘存储或其他任何数据。因此,如果您希望数据具有持久性和耐久性,您必须将数据放在实例外部的外部网络存储上。

结果,通过分离这两者,如果服务器实例失败或所有实例失败,您仍然拥有硬盘和上面的所有数据,不受影响。您只需启动其他实例并从EBS获取数据,就可以了。这样使得您的基础设施更易于管理,因为每个服务器都是平等的;您不会有任何特殊的服务器或其中存有任何特殊数据或文件。因此,您不必担心如果整个基础设施丢失,因为您可以重新创建一个新的基础设施并从独立存储中获取数据,然后继续工作。

回到Redis的例子,Redis服务将在服务器上运行,并使用服务器的RAM来存储数据,而追加只读文件日志和快照将持久保存在服务器外部的磁盘上,从而使您的数据更加耐用。

使用 Redis on Flash 进行成本优化

现在我们知道,您可以通过 Redis 持久化数据以实现耐用性和恢复,同时利用RAM或内存存储以获得出色的性能和速度。那么您可能会问的问题是:将数据存储在内存中不是很昂贵吗?因为与将数据存储在磁盘上的数据库相比,您需要更多的服务器,这是因为内存的大小是有限的。在成本和性能之间存在权衡。

实际上,Redis 通过一种名为Redis on Flash的服务来优化这一点,这是 Redis Enterprise 的一部分。

Redis on Flash 的工作原理

实际上,这是一个非常简单的概念:Redis on Flash 将 RAM 扩展到闪存驱动器或固态硬盘(SSD),其中经常使用的值存储在 RAM 中,而不经常使用的值存储在 SSD 上。因此,对于 Redis 而言,它只是服务器上的更多 RAM。这意味着 Redis 可以通过同时使用 RAM 和 SSD 驱动器来存储数据,利用底层基础设施或底层服务器资源更多,以增加每台服务器的存储容量,从而节省基础设施成本。

扩展 Redis:复制和分片

我们已经讨论了 Redis 数据库的数据存储方式以及其运作方式,包括最佳实践。现在另一个非常有趣的话题是如何扩展 Redis 数据库?

复制和高可用性

假设我的一个 Redis 实例的内存用尽了,因此数据变得太大而无法容纳在内存中,或者 Redis 成为瓶颈无法处理更多请求。在这种情况下,我该如何增加 Redis 数据库的容量和内存大小?

我们有几个选择。首先,Redis支持集群,这意味着您可以拥有一个主 Redis 实例,用于读写数据,并且可以有多个该主实例的副本用于读取数据。这样,您可以扩展 Redis 以处理更多请求,并且增加数据库的高可用性。如果主节点发生故障,其中一个副本可以接管,您的 Redis 数据库基本上可以继续正常运行。

这些副本都会保存主实例的数据副本。因此,您拥有的副本越多,需要的内存空间就越多。并且一个服务器可能没有足够的内存用于所有副本。此外,如果您将所有副本都放在一个服务器上,而该服务器发生故障,那么您整个 Redis 数据库都将丢失,并且会出现停机时间。相反,您希望将这些副本分布在多个节点或服务器之间。例如,您的主实例将位于一个节点,另外两个节点将各自承载两个副本。

用于更大数据集的分片

嗯,这看起来已经不错了,但是如果您的数据集增长到无法在单个服务器的内存中容纳怎么办?此外,我们已经在数据库中扩展了读取操作,因此所有请求基本上只是查询数据,但我们的主实例仍然独自一人,仍然必须处理所有写入操作。那么,在这种情况下该怎么解决呢?

为此,我们使用分片的概念,这是数据库中的一个通用概念,Redis也支持。分片基本上意味着您将完整的数据集划分为更小的块或数据子集,其中每个分片负责其自己的数据子集。

这意味着,与其拥有一个处理完整数据集所有写入的主实例,您可以将其分成,比方说,四个分片,每个分片负责对数据子集的读取和写入。每个分片还需要更少的内存容量,因为它只有四分之一的数据。这意味着您可以将分片分布在较小的节点上并基本上使集群在水平方向扩展。当然,随着数据集的增长以及您需要更多资源,您可以重新对Redis数据库进行分片,这基本上意味着您只需将数据分割成更小的块并创建更多分片。

因此,运行多个Redis的多个副本的多个节点,这些节点都经过分片,将为您提供一个性能优越、高可用的Redis数据库,可以处理更多请求而不会产生任何瓶颈。

现在,我必须指出,这种设置很棒,但您需要自行管理它,进行扩展、添加节点、进行分片,然后进行重新分片等等。对于一些更专注于应用开发和业务逻辑而不是运行和维护数据服务的团队来说,这可能是许多不必要的工作。因此,作为一种更简便的选择,在Redis Enterprise中,您可以自动获得这种设置,因为扩展、分片等都是由系统为您管理的。

Redis的全局复制:主动-主动部署

让我们考虑另一个有趣的场景,适用于需要在多个地理位置实现更高可用性和性能的应用程序。假设我们在伦敦欧洲的数据中心中有一个复制的、分片的 Redis 数据库集群。但是我们有以下两种用例:

  1. 我们的用户地域分布广泛,因此他们从世界各地访问应用程序。我们希望将我们的应用程序和数据服务全球分布,靠近用户,以提供更好的性能。
  2. 例如,如果伦敦欧洲的整个数据中心发生故障,我们希望立即切换到另一个数据中心,以保持 Redis 服务可用。换句话说,我们希望在多个地理位置或区域的数据中心中复制整个 Redis 集群的副本。

跨区域的多个 Redis 集群

这意味着单个数据应该被复制到分布在多个地区的许多集群中,每个集群都完全能够接受读取和写入。在这种情况下,您将拥有多个 Redis 集群,它们将在每个区域充当本地 Redis 实例,并且数据将在这些地理分布的集群之间同步。这是 Redis Enterprise 中提供的一项功能,称为主动-主动部署,因为您在不同位置拥有多个活动数据库。

通过这种设置,我们将为用户提供更低的延迟。即使一个地区的Redis数据库完全崩溃,其他地区也不会受影响。如果由于某些网络问题导致地区之间的连接或同步中断了一小段时间,例如,这些地区的Redis集群可以独立更新数据,一旦重新建立连接,它们可以再次同步这些更改。

CRDTs冲突解决

当然,当你听到这个时,你脑海中可能会冒出的第一个问题是:Redis如何解决多个地区对同一数据集的更改? 因此,如果相同的数据在多个地区发生更改,Redis如何确保任何地区的数据更改不会丢失,数据正确同步,并确保数据一致性呢?

具体来说,Redis Enterprise使用了一个叫做CRDTs的概念,即冲突自由复制数据类型,这个概念被用来在数据库级别自动解决任何冲突,而且没有任何数据丢失。所以基本上,Redis本身具有一种机制,用于合并从多个来源对同一数据集进行的更改,以确保没有任何数据更改丢失,并且任何冲突都得到正确解决。并且,正如你所了解的,Redis支持多种数据类型,每种数据类型都使用自己的数据冲突解决规则,这些规则对于该特定数据类型来说是最优的。

简单来说,与其只覆盖一个源的更改并丢弃其他所有更改,所有并行更改都会被保留并智能解决。同样,这是通过此主动-主动地理复制功能自动完成的,因此您无需担心这一点。

在 Kubernetes 中运行 Redis

我要与 Redis 地址的最后一个主题是在 Kubernetes 中运行 Redis。正如我所说,Redis 非常适合需要支持多种数据类型并且需要轻松扩展数据库而无需担心数据一致性的复杂微服务。我们也知道,运行微服务的新标准是 Kubernetes 平台。因此,在 Kubernetes 中运行 Redis 是一个非常有趣且常见的用例。那么这是如何工作的呢?

在 Kubernetes 上的开源 Redis

使用开源 Redis,您可以将复制的 Redis 部署为 Helm 图表或 Kubernetes 清单文件,并且基本上使用我们已经讨论过的复制和扩展规则,设置并运行一个高可用的 Redis 数据库。唯一的区别是 Redis 运行的主机将是 Kubernetes pod,而不是例如 EC2 实例或任何其他物理或虚拟服务器。但是,当您想在 Kubernetes 中运行 Redis 集群时,相同的分片、复制和扩展概念同样适用,您基本上需要自行管理该设置。

Redis 企业运营商

然而,正如我之前提到的,许多团队不愿意花力气去维护这些第三方服务,因为他们宁愿将时间和资源投入到应用程序开发或其他任务中。因此,在这里拥有一个更简便的替代方案也是很重要的。Redis Enterprise拥有一个托管的Redis集群,您可以将其部署为一个Kubernetes运算符。

如果你不了解运算符,在Kubernetes中,运算符基本上是一个概念,您可以将操作某个应用程序或服务所需的所有资源捆绑在一起,这样您就不必自己管理它或操作它。与人类操作数据库不同,您基本上将所有这些逻辑以自动化形式放入其中,以便为您操作数据库。许多数据库都针对Kubernetes提供运算符,每个这样的运算符当然都有其基于编写者及编写方式的独特逻辑。

Redis Enterprise在Kubernetes上的运算符专门自动化部署和配置整个Redis数据库在您的Kubernetes集群中。它还负责扩展、执行备份,并在需要时恢复Redis集群,等等。因此,它接管了在Kubernetes集群中Redis集群的全部操作。

结论

希望您在本博客中学到了很多知识,并且我能够回答您的许多问题。如果您想了解更多类似的技术和概念,请务必关注我,因为我定期撰写关于人工智能、DevOps和云技术的博客。

此外,如果您对Redis或任何新的主题有任何问题或建议,请在下方留言。最后,感谢您的阅读,我们下一篇博客见。

让我们在领英上连接!

Source:
https://dzone.com/articles/redis-as-a-primary-database-for-complex-applications