使用 Redis Springboot 3 进行数据库插入所需的幂等性原子 Redis 事务

问题描述 投票:0回答:1

我们使用 springboot 3.2.5 和 spring data jpa 将数据插入 RDBMS。 现在需要确保重复数据不会插入到 RDBMS 中。

所以我们首先要根据key检查数据记录是否已经插入,然后检查Redis是否包含该key,如果包含该key,则返回保存的实体的标识符。

如果 Redis 中不存在该键 - 第一次请求时,创建一个新的 Redis 键,然后将该键保存在 Redis 中,然后将数据插入 RDBMS,一旦插入成功,将标识符更新为该键对应的 Redis 值.

我们正在使用 Redis,需要确保在原子操作中检查密钥是否存在并创建新密钥(如果不存在)——意味着这需要在单个事务中进行。我们使用的是 spring data redis 3.2.X JSON,其中包含 Lettuce。请帮忙。

我们目前使用简单的 Redis 命令,例如 set 和 get,使用 lettuce ProtocolKeyword 来执行命令。 Redis 文档建议使用 MULTI 和 EXEC,但不确定 Lettuce 是否可以使用这些(Lettuce 文档无法访问)

有一些使用管道和事务的方法,我们倾向于事务的原子性。不过,我还没有找到可行的方法来在代码中做到这一点。

redis spring-data-redis spring-boot-3
1个回答
0
投票

您面临的最大挑战是您想要原子地

  1. 检查 Redis 是否存在密钥
  2. 将数据插入数据库
  3. 在Redis中设置数据

现在,您正在两个不同的未链接的数据源之间进行操作,因此纯粹的原子机制根本不可能,MULTI/EXEC 将无济于事,因为您正在这些数据源之间进行操作。但是,您可以使用分布式锁确保一次只有一名写入者。

假设您坚持使用简单的字符串键,让我们调用您要使用的数据键

key:1

锁定钥匙

SET
NX
命令和
EX
选项一起使用,可以在某些锁定键上发布超时,例如
key:1:lock
- 例如

SET key:1:lock 1 NX EX 10

这会将值 1 写入该键 如果 Redis 中尚不存在该键,并且它将在 10 秒后自动使该键过期(以防您的线程因某种原因终止)

检查您是否收到回复

如果你收到

OK
结果,这意味着你已经获得了锁,如果你得到
null
那么你知道另一个线程已经获得了锁,你可以在这里终止或退出并稍后重试

将数据写入数据库

您现在可以编写数据库 - 这应该是非常不言自明的

写入您的数据密钥并删除锁定密钥

现在您将把实际数据写入Redis,并且您将删除锁定键,允许其他线程更新数据,您可以使用SET和UNLINK来完成此操作

SET key:1 your_data
UNLINK key:1:lock
© www.soinside.com 2019 - 2024. All rights reserved.