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

时间:2018-08-29 14:12:40

标签: amazon-web-services redis aws-lambda amazon-dynamodb atomic

假设我有几个构成我的API的AWS Lambda函数。其中一个功能从单个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

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

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

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

我试图查看是否有一种方法可以执行此操作,而无需单独的EC2进程来跟踪时序。

redis + lambda + dynamoDB是否适合我要完成的工作,或者有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

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

一种方法是通过在您的业务逻辑周围添加某种锁定来使它们原子化。例如,可以是done with Redis

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

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

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