当多个客户端尝试同时读/写一个项目时,Redis 是原子的吗?

fro*_*773 5 atomic amazon-web-services redis amazon-dynamodb aws-lambda

假设我有几个 AWS Lambda 函数组成了我的 API。其中一个函数从单个 Redis 节点上的特定键读取特定值。业务逻辑如下:

if the key exists:
    serve the value of that key to the client
if the key does not exist:
    get the most recent item from dynamoDB
    insert that item as the value for that key, and set an expiration time
    delete that item from dynamoDB, so that it only gets read into memory once
    Serve the value of that key to the client
Run Code Online (Sandbox Code Playgroud)

这个想法是每次客户提出请求时,他们都会获得所需的价值。如果密钥已过期,则 lambda 需要先从数据库中获取该项目并将其放回 Redis。

但是如果 2 个客户端同时对 lambda 进行 API 调用会发生什么?两个 lambda 进程是否都会读取没有密钥,并且都将从数据库中获取一个项目?

我的目标是实现一个队列,其中某个项目仅在内存中存在 X 时间,并且一旦该项目过期,就应该从数据库中拉出下一个项目,当它被拉出时,它也应该被删除以免它再次被拉动。

我想看看是否有办法做到这一点,而无需单独的 EC2 进程来跟踪时间。

redis+lambda+dynamoDB 是我想要完成的工作的一个很好的设置,还是有更好的方法?

Kev*_*nry 7

Redis 服务器将以原子方式执行命令(或事务或脚本)。但是一系列涉及单独服务(例如 Redis 和 DynamoDB)的操作不会是原子的。

一种方法是通过在业务逻辑周围添加某种锁来使它们具有原子性。例如,这可以通过Redis 完成

但是,这是一种成本高昂且相当麻烦的解决方案,因此如果可能,最好将业务逻辑简单地设计为在并发操作时具有弹性。为此,您必须查看步骤并想象如果多个客户端同时运行会发生什么。

在您的情况下,我可以看到的缺陷是可以从 DynamoDB 读取和删除两个值,一个在 Redis 中覆盖另一个。这可以通过使用 Redis 的SETNX(SET if Not eXists) 命令来避免。像这样的东西:

GET the key from Redis
If the value exists:
    Serve the value to the client
If the value does not exist:
    Get the most recent item from DynamoDB
    Insert that item into Redis with SETNX
        If the key already exists, go back to step 1
    Set an expiration time with EXPIRE
    Delete that item from DynamoDB
    Serve the value to the client
Run Code Online (Sandbox Code Playgroud)