想象您构建了一个电影流媒体应用。您使用 PostgreSQL 作为数据存储,并随着需要扩展而使用 Redis 实现了缓存。然而,现在您遇到了更新用户资料或订阅反映缓慢的问题。
例如,当用户购买或修改订阅时,用户期望更改立即反映在其账户上,以便新的订阅允许观看所需的电影/节目。因此,您需要一种快速提供用户数据强一致性的方法。在这种情况下,您需要的就是所谓的“Write-through 模式”。
使用 Write-through 模式,应用程序每次将数据写入缓存时,也会更新数据库中的记录,这与 Write behind 不同,Write-through 模式中线程会等待直到数据写入数据库完成。
下面是应用程序的 Write-through 模式图
该模式的工作原理如下
注意:在收到主数据库的响应之前, Redis 服务器会被阻塞。
有两种相关的写入模式,它们的主要区别如下
Write Behind | Write through |
---|---|
异步同步数据 | 同步/立即同步数据 |
缓存和主记录系统(数据库)之间的数据在 短时间内可能不一致 | 缓存和主记录系统(数据库)之间的数据始终 一致 |
了解更多关于 Write behind 模式
使用 Redis 实现 Write-through 缓存确保(关键)数据缓存始终与数据库保持同步,提供了 强一致性 并 提高了应用性能。
考虑以下不同应用的场景
如果您已经熟悉 RedisGears,可以跳过本节)
RedisGears 是一个可编程的无服务器引擎,用于事务、批处理和事件驱动的数据处理,允许用户在 Redis 中存储的数据上编写和运行自己的函数。
函数可以用不同的语言实现,包括 Python 和 C,并可以通过 RedisGears 引擎以两种方式之一执行
RedisGears 可以执行的一些批处理类型操作
person:
person:
开头的 KeyNames 写入一个集合person:
的键(假设它们都是 hash 类型)RedisGears 可以执行的一些事件类型操作
I-AM-IMPORTANT:
的键上的 DEL 操作,并将其异步转储到“已删除键”日志文件中player:
的键的元素分数上的所有 HINCRBY 操作,并在分数达到 1000 时同步更新用户级别运行 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 工具提供了一种更简单的方式来执行 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 ...]]
对于我们的示例代码,我们将演示如何将 users
写入 Redis,然后 Write-through 到 PostgreSQL。使用下面的 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://:8080/?pgsql=postgres&username=root&db=example&ns=public&sql=。您需要输入密码(在上面的示例中是 password
),
然后您将被带到 SQL 命令页面。运行以下 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
);
开发者需要在使用 Write-through 模式(将数据从 Redis 同步到主记录系统)之前将一些代码(例如本例中的 python)加载到 Redis 服务器。Redis 服务器有一个 RedisGears 模块,可以解释 python 代码并将数据从 Redis 同步到主记录系统。
现在,我们需要创建一个 RedisGears Recipe,它将 Write-through 到 PostgreSQL 数据库。以下 Python 代码将 Write-through 到 PostgreSQL 数据库
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 hash 字段映射到 PostgreSQL 表列。 RGWriteThrough
函数接受 usersMapping
,其中键是 Redis hash 键,值是 PostgreSQL 表列。
一个由 RedisGears 函数及其可能拥有的任何依赖项组成的集合,用于实现高层功能目的,称为 recipe
。示例:上面 Python 代码中的 "RGJSONWriteThrough" 函数
该 Python 文件为了正常工作需要一些依赖项。下面是包含这些依赖项的 requirements.txt 文件,请将其与 "write-through.py" 文件一同创建。
rgsync
psycopg2-binary
cryptography
# install
pip install gears-cli
要使用 gears-cli
运行我们的 write-through recipe,需要运行以下命令:
$ 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 代码中执行(有关更多详细信息,请参阅 示例 Node 文件)
在 Redis Gears GitHub 仓库 中找到更多示例。
RedisInsight 是用于在 Redis 中查看数据的免费 Redis GUI。 点击此处下载。
下一步是验证 RedisGears 是否正在 Redis 和 PostgreSQL 之间同步数据。请注意,在我们的 Python 文件中,我们为键指定了一个前缀。在这种情况下,我们指定了 __
作为前缀,users
作为表,以及 id
作为唯一标识符。这指示 RedisGears 查找以下键格式:__{users:<id>}
。尝试在 Redis 命令行中运行以下命令
hset __{users:1} username john email [email protected] 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 中的 users 选择页面 来确认用户也已插入到 PostgreSQL 中。您应该会看到用户已插入到表中。
这就是如何使用 RedisGears 将数据 write through 到 PostgreSQL 的方法,到目前为止,我们只添加了一个哈希键。您还可以更新特定的哈希字段,这将在您的 PostgreSQL 数据库中体现。运行以下命令来更新 username
字段:
> hset __{users:1} username bar
在 RedisInsight 中,验证 username
字段已更新
现在进入 Adminer 检查 username
字段。您应该会看到它已更新为 bar
。
您现在知道了如何使用 Redis 进行 write-through 缓存。可以根据需要使用不同的策略/模式逐步采用 Redis。有关缓存主题的更多资源,请查看以下链接