无论使用何种技术堆栈,许多开发人员已经使用过
Redis 以为基于集群的应用程序提供分布式缓存机制而闻名。虽然这是真的,但这不是它的唯一目的。
Redis 是一个功能强大且用途广泛的内存数据库。强大,因为它非常快。用途广泛,因为它可以处理缓存、类似数据库的功能、会话管理、实时分析、事件流等。
但是,当将其用作常规数据库时,必须注意内存部分。
在本文中,我们将探索 Redis 缓存模式的一些最有趣的细微差别,使用 Node.js 作为环境来运行一些基准测试。让我们开始吧!
Redis,或者至少听说过它。
多个缓存领域
你以前听过这个故事。建立在关系数据库之上并开始快速增长的系统通常最终需要在查询方面消除一些压力,以实现更好的性能。
作为物理实现的问题,缓存可以发生在系统中的许多地方:从数据库层本身到应用程序服务层,甚至作为远程分布式独立服务(就像 Redis 一样)。
在继续之前,让我们探索这些类型中的每一种。
类型 1. 类数据库集成
根据您所遵循的系统设计,数据库的组合可以帮助您的系统获得一些处理性能。
例如,如果您使用 CQRS 在读取数据时将一部分负载驱动到 NoSQL 数据库,而在写入数据时将另一部分负载驱动到关系数据库,这可以是一种类似于数据库的集成形式来实现缓存。
但是,这很容易出错,并且需要大量人力才能使其运行,更不用说维护它了。
其他数据库,例如Aurora,稍微超越并提供内置机制以在数据库级别启用缓存。换句话说,应用程序层和客户端不需要知道缓存的存在,因为数据库架构本身会处理整个事情:通过内部复制逻辑在记录到达时添加和更新记录。
显然,在可用内存和跨集群实例的数据同步方面存在一些限制。但是,考虑到正确的用例场景,这将是一个需要考虑的强大集成。
类型 2. 基于本地应用程序
程序化缓存是最常用的类型之一,因为它们只是保存数据的内存结构。
每种编程语言都有其内置或社区驱动的库,可以立即轻松地提供本地缓存。
主要优点是速度超级快。数据在内存中,因此您的代码可以比通过类似 TCP 的请求来获取它更快地访问它。
另一方面,如果您在分布式微服务世界中工作(我敢打赌),集群的每个节点都会保留自己的版本化数据集,这些数据不会在其他节点之间共享。更不用说在特定节点突然关闭的情况下所有的数据丢失。
类型 3. 远程缓存(又名Redis)
通常,这种类型的缓存也称为
因为它们是远程工作的,所以它们必须能够在极端情况下表现良好。这就是为什么他们通常可以在几毫秒内处理大量数据负载。
选择这种类型的缓存是需要讨论和考虑的事情。例如,您是否有关于您(或您的提供商)网络延迟的详细信息?你能水平扩展你的 Redis 集群吗?
由于您的应用程序与外部世界之间存在通信,因此必须制定计划以应对失败或变得太慢的情况。
开发人员通常通过混合本地和远程缓存策略来解决这个问题,这将为他们在边缘情况下提供第二道保护屏障。
侧缓存,这意味着它作为服务存在于其他地方,而不是您的应用程序或数据库。
一些缓存模式
再一次,根据您的系统要求,您实现缓存的方式可能会根据您希望事情发生的反应程度而有所不同。
让我们花一些时间来分解最常见的缓存模式。
缓存模式
这是最常用的缓存模式。顾名思义,它存在于系统架构的不同方面,除了应用程序。
应用程序负责缓存和数据库之间的协调,因为它认为是最好的。看下图:
缓存侧表示流程
- 第一步包括检查缓存以查看是否存在所需的数据。如果成功,应用程序将信息返回给客户端,而不调用数据库。
- 如果不是,应用程序会转到数据库以获取最新信息。
- 最后,一旦它拥有最新版本的数据,应用程序决定写入缓存以使其也能感知。
这种策略有很多好处,例如可以灵活地处理缓存和数据库中完全不同的数据类型。需要彻底考虑数据库,因为那里的更改可能会变得太痛苦。然而,缓存让您可以更自由地使用更具
请注意,如果您将数据写入数据库并且缓存更新失败,上图中演示的策略可能会很麻烦。对于这种情况,重要的是要有第二个计划,例如 TTL(生存时间)设置,开发人员在该计划中建立超时以使缓存中的特定数据无效。这样,当缓存数据更新失败时,应用程序不会处理过时的数据太久。
弹性的数据结构。
直写模式
此模式采用与缓存端相反的方法。在这里,当检测到任何更改时,应用程序首先写入缓存,然后再进入数据库。
这就是它得名的地方,因为它在进行最终的数据库写入之前会通过缓存层。
直写表示流程
在对此类策略进行建模时必须小心,尤其是在数据库写入失败的情况下。
对于这种情况,您可以建立重试策略以不惜一切代价尝试保存到数据库,或者引发事务错误,以回滚先前的缓存写入。
请注意每个流程的整体处理时间的相应增加。