如何使用Redis避免竞态条件?

18
我使用Redis作为我的数据库,客户端使用ServiceStack.Redis。问题在于,如果两个并发请求需要更新一个键,则可能会产生竞争条件。例如:
A: 1. 获取 key 的值 2. 开始 MULTI 3. a = a - 100 4. 设置 key 的值为 a 5. 执行 EXEC
B: 1. 获取 key 的值 2. 开始 MULTI 3. a = a - 100 4. 设置 key 的值为 a 5. 执行 EXEC
如果原始的“key”值为1000,并且A和B是串行的,则这两个“key”的操作得到正确的结果将是800。但是,如果A和B同时发生,在A可以提交之前,操作B从“key”获取值1000,并将900设置为“key”的值。这不是我想要的。如何避免这种竞争条件,使用“WATCH”?
2个回答

20

您应该阅读有关Redis事务的文档,Redis事务本质上是将多个操作批处理,以便作为单个原子操作执行。

由于它只是批处理操作,因此您不能在事务上下文中执行任何读取操作。您需要在事务开始之前检索所需的任何读取操作。您可以使用Redis WATCH来监视在事务完成之前不应修改的任何键,如果修改了键,则事务将失败并且不会处理任何操作。


谢谢你提醒我。在我的程序中,我在开始事务之前读取。我已经将伪代码更改为正确的顺序。那么,WATCH应该解决我的问题了吗? - Allan Yang
@AllanYang 是的,在任何读取操作之前使用 WATCH 将确保如果在事务执行之前键已被修改,则不会执行该事务。 - mythz

0

@NoobEditor 不,仅仅使用watch是不能帮助您解决竞态条件的。使用watch-exec将确保在监视键未被其他人更新的情况下才能运行整个批处理。

利用Redis分布式锁来正确处理竞态条件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接