学习

如何使用 Redis 进行写后缓存

Prasan Kumar
作者
Prasan Kumar, Redis 技术解决方案开发者
Will Johnston
作者
Will Johnston, Redis 开发者增长经理
GITHUB 代码

以下是克隆本教程中使用的应用源代码(前端和后端)的命令

git clone https://github.com/redis-developer/ebook-speed-mern-frontend.git

git clone https://github.com/redis-developer/ebook-speed-mern-backend.git

什么是写后缓存?#

想象你构建了一个电影流媒体应用。你使用 MongoDB 作为数据存储,随着需要扩展,你使用 Redis 实现了缓存。这极大地加快了读取速度。然而,现在你在写入 MongoDB 时遇到了缓慢的问题。

例如,你可能想让用户从上次离开的地方继续观看电影。这就需要存储用户暂停电影时的观看时间戳。对于数百万用户来说,这开始导致在需求高峰时 MongoDB 变慢。

你需要一种方法来平滑需求高峰,让你能够快速写入数据,然后在需求下降时将其持久化到 MongoDB。这正是“写后模式”所需。

这种模式很简单,你的应用将数据写入 Redis,然后数据异步写入 MongoDB。写入操作排队等待,这样应用可以快速继续,而缓存可以随着时间赶上。然而,这确实意味着缓存和记录系统之间的数据会在短时间内不一致。

下图是该应用中写后模式的示意图

这种模式工作原理如下

  1. 1.应用读写数据到 Redis。
  2. 2.Redis 异步同步任何更改的数据到 MongoDB 数据库。

有两种相关的写入模式,它们的主要区别如下

写后 (Write Behind)

写穿透 (Write through)

异步同步数据

同步/立即同步数据

缓存和记录系统(数据库)之间的数据在 短时间内不一致

缓存和记录系统(数据库)之间的数据总是 一致的

了解更多关于 写穿透模式

为何应使用 Redis 进行写后缓存?#

需要时,请考虑使用 Redis 和此模式

  1. 1.平滑需求高峰:在高压下,应用可能需要快速写入数据。如果你的应用需要高速执行大量写入操作,请考虑使用 Redis。Redis 的可编程能力确保缓存中存储的数据与数据库同步。
  2. 2.批量写入:频繁写入数据库有时成本很高(例如,日志记录)。在这种情况下,使用 Redis 批量写入数据库,让数据按间隔同步是划算的。
  3. 3.分担主数据库负载:当大量写入操作在 Redis 上执行时,数据库负载会降低,因此我们可以分散写入以在应用使用高峰期间提高性能。

使用 RedisGears 实现 Redis 可编程性以进行写后缓存#

提示

如果你已经熟悉 RedisGears,可以跳过本节)

什么是 RedisGears?#

RedisGears 是一个可编程的无服务器引擎,用于事务、批量和事件驱动的数据处理,允许用户编写和运行自己的函数来处理存储在 Redis 中的数据。

函数可以用不同的语言实现,包括 Python 和 C,并可以通过 RedisGears 引擎以两种方式执行

  1. 1.批量 (Batch):由 Run 操作触发,立即执行并作用于现有数据
  2. 2.事件 (Event):由 Register 操作触发,由新事件触发并作用于它们的数据

RedisGears 可以执行的一些批量类型操作

  • 对 KeySpace 中的所有键或匹配特定模式的键执行操作,例如:
    • 为所有键名添加 person: 前缀
    • 删除值小于零的所有键
    • 将所有以 person: 开头的键名写入一个集合
  • 对所有(或匹配的)键执行一组操作,其中一个操作的输出是另一个操作的输入,例如:
    • 查找所有带有 person: 前缀的键(假设它们都是 hash 类型)
    • 将用户的 days_old 增加 1,然后按年龄组(10-20、20-30 等)求和
    • 将今天的统计信息添加到每个客户端的有序集合中,计算最近 7 天的平均值,并将计算结果保存为一个字符串

RedisGears 可以执行的一些事件类型操作

  • RedisGears 还可以注册事件监听器,每当监视的键发生更改时就会触发函数执行,例如:
    • 监听所有键上的所有操作,并维护 KeySpace 中所有键名的列表
    • 监听带有 I-AM-IMPORTANT: 前缀的键上的 DEL 操作,并将其异步转储到“已删除键”日志文件中
    • 监听带有 player: 前缀的键上对元素 score 的 HINCRBY 操作,并在 score 达到 1000 时同步更新用户级别

如何使用 RedisGears?#

运行 Docker 容器

docker run -p 6379:6379 redislabs/redisgears:latest

对于一个非常简单的示例,列出 Redis 数据库中所有带有 person: 前缀的键,创建一个名为 hello_gears.py 的 Python 脚本如下

gb = GearsBuilder() gb.run('person:*')

执行你的函数

docker exec -i redisgears redis-cli RG.PYEXECUTE "`cat hello_gears.py`"

使用 gears-cli#

gears-cli 工具提供了一种更简单的方式来执行 RedisGears 函数,特别是当你需要传递一些参数时。

它用 Python 编写,可以使用 pip 进行安装

pip install gears-cli
gears-cli hello_gears.py REQUIREMENTS rgsync

用法

gears-cli --help
usage: gears-cli [-h] [--host HOST] [--port PORT]
[--requirements REQUIREMENTS] [--password PASSWORD] path [extra_args [extra_args ...]]

RedisGears 参考资料#

在使用 Redis 和 MongoDB 的 NodeJS 应用中实现写后缓存#

演示应用#

本教程其余部分使用的演示应用展示了一个电影应用,包含基本的创建、读取、更新和删除 (CRUD) 操作。

电影应用仪表盘顶部有一个搜索区域,中间是电影卡片列表。浮动的加号图标在用户选择时会显示一个弹窗,允许用户输入新的电影详情。搜索区域有一个文本搜索栏和一个在文本搜索和基本(即基于表单的)搜索之间切换的链接。每个电影卡片都有编辑和删除图标,这些图标在鼠标悬停在卡片上时显示。

GITHUB 代码

以下是克隆本教程中使用的应用源代码(前端和后端)的命令

git clone https://github.com/redis-developer/ebook-speed-mern-frontend.git

git clone https://github.com/redis-developer/ebook-speed-mern-backend.git

为了使用电影应用演示这种模式,想象用户打开弹窗添加新电影。

应用不再立即将数据存储到 MongoDB 中,而是将更改写入 Redis。在后台,RedisGears 自动将数据与 MongoDB 数据库同步。

使用写后模式编程 Redis#

开发者在使用写后模式(将数据从 Redis 同步到 MongoDB)之前,需要将一些代码(例如本例中的 python 代码)加载到 Redis 服务器。Redis 服务器有一个 RedisGears 模块,它解释 python 代码并将数据从 Redis 同步到 MongoDB。

加载 Python 代码比听起来要容易。只需替换 Python 文件中的数据库详情,然后将文件加载到 Redis 服务器。

创建 Python 文件(如下所示,可在线获取)。然后更新 MongoDB 连接详情、数据库、集合和主键名称以进行同步。

movies-write-behind.py
# Gears Recipe for a single write behind

# import redis gears & mongo db libs
from rgsync import RGJSONWriteBehind, RGJSONWriteThrough
from rgsync.Connectors import MongoConnector, MongoConnection

# change mongodb connection (admin)
# mongodb://usrAdmin:[email protected]:27017/dbSpeedMernDemo?authSource=admin
mongoUrl = 'mongodb://usrAdmin:[email protected]:27017/admin'

# MongoConnection(user, password, host, authSource?, fullConnectionUrl?)
connection = MongoConnection('', '', '', '', mongoUrl)

# change MongoDB database
db = 'dbSpeedMernDemo'

# change MongoDB collection & it's primary key
movieConnector = MongoConnector(connection, db, 'movies', 'movieId')

# change redis keys with prefix that must be synced with mongodb collection
RGJSONWriteBehind(GB,  keysPrefix='MovieEntity',
                  connector=movieConnector, name='MoviesWriteBehind',
                  version='99.99.99')
什么是 REDISGEARS recipe?

实现高级功能目的的 RedisGears 函数及其任何依赖项的集合称为 recipe。示例:上面 python 代码中的 "RGJSONWriteBehind" 函数

有两种方法将该 Python 文件加载到 Redis 服务器中

  1. 1.使用 gears 命令行界面 (CLI)

更多关于 Gears CLI 的信息请访问 gears-cli 和 rgsync

# install
pip install gears-cli
# If python file is located at “/users/tom/movies-write-behind.py”
gears-cli --host <redisHost> --port <redisPort> --password <redisPassword> run /users/tom/movies-write-behind.py REQUIREMENTS rgsync pymongo==3.12.0

2. 使用 Redis 命令行中的 RG.PYEXECUTE 命令。

更多信息请访问 RG.PYEXECUTE

# Via redis cli
RG.PYEXECUTE 'pythonCode' REQUIREMENTS rgsync pymongo==3.12.0

RG.PYEXECUTE 命令也可以从 Node.js 代码中执行(请查阅 示例 Node 文件 了解更多详情)

更多示例请访问 Redis Gears 与 MongoDB 同步

使用 RedisInsight 验证写后模式#

提示

RedisInsight 是免费的 Redis GUI,用于查看 Redis 中的数据。 点击这里下载。

下一步是验证 RedisGears 是否正在 Redis 和 MongoDB 之间同步数据。

使用 Redis CLI 插入一个以指定前缀(在 Python 文件中指定)开头的键

接下来,确认 JSON 也已插入到 MongoDB 中。

你还可以查看 RedisInsight 来验证数据是否通过 Streams 流入其消费者(例如 RedisGears)。

所有这些如何与演示应用配合工作?下面是一个插入电影的代码片段。一旦数据写入 Redis,RedisGears 会自动将其同步到 MongoDB。

之前(使用 MongoDB)
...
//(Node mongo query)
if (movie) {
  //insert movie to MongoDB
  await db.collection("movies")
           .insertOne(movie);
}
...
之后(使用 Redis)
...
//(Redis OM Node query)
if (movie) {
  const entity = repository.createEntity(movie);
  //insert movie to Redis
  await moviesRepository.save(entity);
}
...

准备好使用 Redis 进行写后缓存了吗?#

你现在已经了解如何使用 Redis 进行写后缓存了。可以使用不同的策略/模式,根据需要逐步采用 Redis。关于缓存的更多资源,请查看以下链接

其他资源#

使用 Redis 缓存

通用