学习

如何使用Redis进行写穿缓存策略

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

什么是直写缓存?#

假设您已经构建了一个电影流应用程序。您使用 PostgreSQL 作为您的数据存储,并且随着您需要扩展,您使用 Redis 实现了缓存。但是,现在您遇到了反映更新的用户配置文件或订阅的缓慢问题。

例如,当用户购买或修改订阅时,用户期望更改立即反映在他的帐户上,以便可以观看新订阅的所需电影/节目。因此,您需要一种快速提供用户数据的强一致性的方法。在这种情况下,您需要的就是“直写模式”。

使用**直写**模式,每次应用程序将数据写入缓存时,它也会更新数据库中的记录,不像写后线程在此模式下等待,直到写入数据库也完成。

以下是应用程序直写模式的图表

该模式的工作原理如下

  1. 1.应用程序读取和写入 Redis 中的数据。
  2. 2.Redis 将任何更改的数据**同步/立即**同步到 PostgreSQL 数据库。

注意:**Redis 服务器被阻塞**,直到收到来自主数据库的响应。

存在两种相关的写入模式,它们之间的主要区别如下

写后

直写

异步同步数据

同步/立即同步数据

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

缓存和记录系统(数据库)之间的数据始终**一致**

详细了解写后模式

为什么应该使用 Redis 进行直写缓存#

使用 Redis 的直写缓存确保(关键数据)缓存始终与数据库保持同步,提供**强一致性**并**提高应用程序性能**。

考虑以下不同应用程序的场景

  • 电子商务应用程序:在电子商务应用程序中,直写缓存可用于确保产品库存的一致性。每当客户购买产品时,应立即更新库存数量,以避免超卖。Redis 可用于缓存库存数量,并且对数量的每次更新都可写入数据库。这确保了缓存中的库存数量始终是最新的,并且客户无法购买缺货的商品。
  • 银行应用程序:在银行应用程序中,直写缓存可用于确保帐户余额的一致性。每当进行交易时,应立即更新帐户余额,以避免透支或其他问题。Redis 可用于缓存帐户余额,并且每次交易都可写入数据库。这确保了缓存中的余额始终是最新的,并且交易可以以强一致性进行处理。
  • 在线游戏平台:假设您有一个在线游戏平台,用户可以在该平台上互相玩游戏。使用直写缓存,对用户分数或游戏状态所做的任何更改都会保存到数据库并缓存到 Redis 中。这确保了对该用户分数或游戏状态的任何后续读取将首先命中缓存。这有助于减少数据库的负载,并确保显示给用户的游戏状态始终是最新的。
  • 索赔处理系统:在保险索赔处理系统中,索赔数据需要在不同的系统和应用程序之间保持一致性和最新状态。使用 Redis 中的直写缓存,可以将新的索赔数据写入数据库和 Redis 缓存。这确保了不同的应用程序始终拥有有关索赔的最新信息,从而使索赔员可以更轻松地访问他们需要处理索赔的信息,并更快、更有效地处理索赔。
  • 医疗保健应用程序:在医疗保健应用程序中,患者数据需要在不同的系统和应用程序之间保持一致性和最新状态。使用 Redis 中的直写缓存,可以将更新的患者数据写入数据库和 Redis 缓存,确保不同的应用程序始终拥有最新的患者信息。这可以通过向医疗保健提供者提供准确及时的信息来帮助改善患者护理。
  • 社交媒体应用程序:在社交媒体应用程序中,直写缓存可用于确保用户配置文件的一致性。每当用户更新其个人资料时,更改应立即反映出来,以避免向其他用户显示过时信息。Redis 可用于缓存用户配置文件,并且每次更新都可写入数据库。这确保了缓存中的配置文件信息始终是最新的,并且用户可以看到彼此的准确信息。

使用 RedisGears 进行直写缓存的 Redis 可编程性#

提示

如果您已经熟悉 RedisGears,则可以跳过本节。

什么是 RedisGears?#

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

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

  1. 1.批处理:由 Run 操作触发,执行是立即的,并且是在现有数据上执行的
  2. 2.事件:由 Register 操作触发,执行由新事件及其数据触发

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

  • 对 KeySpace 中的所有键或与特定模式匹配的键运行操作,例如:
    • 将所有 KeyName 前缀为 person:
    • 删除所有值为负数的键
    • 将所有以 person: 开头的 KeyName 写入集合
  • 对所有(或匹配的)键运行一组操作,其中一个操作的输出是另一个操作的输入,例如
    • 查找所有以 person: 为前缀的键(假设它们都是哈希类型)
    • 将用户的 days_old 增加 1,然后按年龄组(10-20、20-30 等)进行汇总
    • 将今天的统计数据添加到每个客户的排序集中,计算过去 7 天的平均值,并将计算结果保存到字符串中

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

  • RedisGears 还可以注册事件监听器,这些监听器会在每次监视的键发生变化时触发函数执行,例如
    • 监听所有键上的所有操作,并将所有键名称保存在键空间中
    • 监听对以 I-AM-IMPORTANT: 为前缀的键的 DEL 操作,并异步地将它们转储到“已删除的键”日志文件中
    • 监听对以 player: 为前缀的键的元素分数的 HINCRBY 操作,并在分数达到 1000 时同步更新用户的等级

如何使用 RedisGears?#

运行 Docker 容器

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

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

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 进行编程#

对于我们的示例代码,我们将演示将 users 写入 Redis,然后将其写入 PostgreSQL。使用以下 docker-compose.yml 文件来设置所需的环境:

docker-compose.yml
version: '3.9'
services:
  redis:
    container_name: redis
    image: 'redislabs/redismod:latest'
    ports:
      - 6379:6379
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
  postgres:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: password
      POSTGRES_DB: example
  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

要运行 docker-compose 文件,请运行以下命令

$ docker compose up -d

这将创建一个 Redis 服务器、一个 PostgreSQL 服务器和一个 Adminer 服务器。Adminer 是一款基于 Web 的数据库管理工具,允许您查看和编辑数据库中的数据。

接下来,打开您的浏览器,访问 https://localhost:8080/?pgsql=postgres&username=root&db=example&ns=public&sql=。您需要输入密码(在上面的示例中为 password),

然后您将被带到 SQL 命令页面。运行以下 SQL 命令以创建表

users.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(255) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    first_name VARCHAR(255),
    last_name VARCHAR(255),
    date_of_birth DATE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

开发人员需要在使用直写模式(它将数据从 Redis 同步到记录系统)之前将一些代码(例如示例中的 Python)加载到 Redis 服务器中。Redis 服务器有一个 RedisGears 模块,它解释 Python 代码并将数据从 Redis 同步到记录系统。

现在,我们需要创建一个 RedisGears 规则,它将直写到 PostgreSQL 数据库。以下 Python 代码将直写到 PostgreSQL 数据库

write-through.py
from rgsync import RGWriteThrough
from rgsync.Connectors import PostgresConnector, PostgresConnection

'''
Create Postgres connection object
'''
connection = PostgresConnection('root', 'password', 'postgres:5432/example')

'''
Create Postgres users connector
'''
usersConnector = PostgresConnector(connection, 'users', 'id')

usersMappings = {
    'username': 'username',
    'email': 'email',
    'pwhash': 'password_hash',
    'first': 'first_name',
    'last': 'last_name',
    'dob': 'date_of_birth',
    'created_at': 'created_at',
    'updated_at': 'updated_at',
}

RGWriteThrough(GB, keysPrefix='__',     mappings=usersMappings,
               connector=usersConnector, name='UsersWriteThrough', version='99.99.99')

确保您创建了“write-through.py”文件,因为接下来的说明将使用它。为了示例的目的,我们展示了如何将 Redis 哈希字段映射到 PostgreSQL 表列。 RGWriteThrough 函数接受 usersMapping 作为输入,其中键是 Redis 哈希键,值是 PostgreSQL 表列。

什么是 RedisGears 规则?

RedisGears 函数的集合以及它们可能具有的任何依赖项,这些函数和依赖项实现了高级功能性目的,称为 规则。例如:上面 Python 代码中的 “RGJSONWriteThrough” 函数

Python 文件为了工作需要一些依赖项。以下是包含依赖项的 requirements.txt 文件,请在“write-through.py”文件旁边创建它

requirements.txt
rgsync
psycopg2-binary
cryptography

有两种方法(gears CLI 和 RG.PYEXECUTE)可以将 Python 文件加载到 Redis 服务器中

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

gears-clirgsync 中查找有关 Gears CLI 的更多信息。

# install
pip install gears-cli

要使用 gears-cli 运行我们的直写规则,我们需要运行以下命令:

$ gears-cli run --host localhost --port 6379 write-through.py --requirements requirements.txt

您应该会收到一条显示“OK”的响应。这就是您知道已成功将 Python 文件加载到 Redis 服务器中的方式。

提示

如果您使用的是 Windows,建议您使用 WSL 安装和使用 gears-cli。

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

# Via redis cli
RG.PYEXECUTE 'pythonCode' REQUIREMENTS rgsync psycopg2-binary cryptography
提示

RG.PYEXECUTE 命令也可以从 Node.js 代码中执行(有关更多详细信息,请参阅 示例节点文件

提示

Redis Gears GitHub 存储库 中查找更多示例。

使用 RedisInsight 验证直写模式#

提示

RedisInsight 是用于查看 Redis 中数据的免费 Redis GUI。 点击此处下载。

下一步是验证 RedisGears 是否正在 Redis 和 PostgreSQL 之间同步数据。请注意,在我们的 Python 文件中,我们为键指定了一个前缀。在本例中,我们指定了 __ 作为前缀、users 作为表以及 id 作为唯一标识符。这指示 RedisGears 查找以下键格式:__{users:<id>}。尝试在 Redis 命令行中运行以下命令

hset __{users:1} username john email john@gmail.com pwhash d1e8a70b5ccab1dc2f56bbf7e99f064a660c08e361a35751b9c483c88943d082 first John last Doe dob 1990-01-01 created_at 2023-04-20 updated_at 2023-04-20

查看 RedisInsight 以验证哈希值是否已进入 Redis。在 RedisGears 处理完 __{users:1} 键后,它将从 Redis 中删除,并替换为 users:1 键。查看 RedisInsight 以验证 users:1 键是否在 Redis 中。

接下来,通过打开 Adminer 中的 select 页面 确认用户是否也插入到 PostgreSQL 中。您应该看到插入到表中的用户。

这就是您可以使用 RedisGears 将数据直写到 PostgreSQL 的方法,到目前为止,我们只添加了一个哈希键。您也可以更新特定的哈希字段,它将在您的 PostgreSQL 数据库中得到反映。运行以下命令以更新 username 字段:

> hset __{users:1} username bar

在 RedisInsight 中,验证 username 字段是否已更新

现在进入 Adminer 并检查 username 字段。您应该看到它已更新为 bar

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

您现在知道了如何使用 Redis 进行直写缓存。可以使用不同的策略/模式,在需要的地方逐步采用 Redis。有关缓存主题的更多资源,请查看以下链接

其他资源#