Redis:如何防止这种竞争条件
Redis : How to prevent this race condition
我在 redis 中有一个散列,其中一个字段的值为字符串化数组,每当用户注册一个事件时,
- 从 redis 中获取这个字符串化数组
- 在后端解析并在数组中添加用户的用户名
- 将数组字符串化并存储回散列
如果两个用户在足够接近的时间注册,这里可能存在潜在的竞争条件。
竞争条件可能是这样的,两个用户从 redis 获得相同的字符串化数组,然后他们修改,并且只有一个更新会发生,因为一个将被另一个覆盖。
有没有办法像 SQL 中的事务一样防止这种竞争条件。我读过 multi
,但它不允许在服务器上的命令之间进行计算。
或者存储字符串化数组并存储为哈希字段是个坏主意,我应该在 Redis 上为此使用普通列表。
解决方案是尽可能使用原子操作。您有多种选择:
- 使用真正的 Redis 列表,支持
LPUSH
等方便的命令
- 在 Lua script 中执行所有操作(根据定义,它们是原子的)
- 使用 Redis transactions 和
WATCH
命令跟踪更改
典型的 WATCH
用法包括尝试执行事务直到成功。您可以使用一个简单的循环来完成此操作,但是您的连接器可能有一个专门用于此目的的特殊便捷方法。
我在 redis 中有一个散列,其中一个字段的值为字符串化数组,每当用户注册一个事件时,
- 从 redis 中获取这个字符串化数组
- 在后端解析并在数组中添加用户的用户名
- 将数组字符串化并存储回散列
如果两个用户在足够接近的时间注册,这里可能存在潜在的竞争条件。
竞争条件可能是这样的,两个用户从 redis 获得相同的字符串化数组,然后他们修改,并且只有一个更新会发生,因为一个将被另一个覆盖。
有没有办法像 SQL 中的事务一样防止这种竞争条件。我读过 multi
,但它不允许在服务器上的命令之间进行计算。
或者存储字符串化数组并存储为哈希字段是个坏主意,我应该在 Redis 上为此使用普通列表。
解决方案是尽可能使用原子操作。您有多种选择:
- 使用真正的 Redis 列表,支持
LPUSH
等方便的命令
- 在 Lua script 中执行所有操作(根据定义,它们是原子的)
- 使用 Redis transactions 和
WATCH
命令跟踪更改
典型的 WATCH
用法包括尝试执行事务直到成功。您可以使用一个简单的循环来完成此操作,但是您的连接器可能有一个专门用于此目的的特殊便捷方法。