redis应该中如何解决多写的竞争问题

在Redis中,面对多个连接同时更新同一key值可能导致的并发问题,可以通过乐观锁策略来解决。具体做法是利用`watch`命令监控key,然后在`multi`、`set`和`exec`之间进行操作。当监控的key在事务执行前被修改,事务会失败,从而避免了并发冲突。然而,若多个写操作同时进行,只有一个是成功的,其余会失败。这个问题需要进一步的策略来处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目中需要使用到redis进行数据缓存及读写操作。遇到了一些问题并总结到这里。

考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这种方式进行对数据的更新。

假如有某个key = "price",  value值为10,现在想把value值进行+10操作。正常逻辑下,就是先把数据key为price的值读回来,加上10,再把值给设置回去。如果只有一个连接的情况下,这种方式没有问题,可以工作得很好,但如果有两个连接时,两个连接同时想对还price进行+10操作,就可能会出现问题了。

例如:两个连接同时对price进行写操作,同时加10,最终结果我们知道,应该为30才是正确。

考虑到一种情况:

T1时刻,连接1将price读出,目标设置的数据为10+10 = 20。

T2时刻,连接2也将数据读出,也是为10,目标设置为20。

T3时刻,连接1将price设置为20。

T4时刻,连接2也将price设置为20,则最终结果是一个错误值20。

如何解决?

方案一:可以使用独占锁的方式,类似操作系统的mutex机制。(网上有例子,http://blog.youkuaiyun.com/black_ox/article/details/48972085 不过实现相对复杂,成本较高)

方案二:使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)

如何用乐观锁方式进行解决?

本质上是假设不会进行冲突,使用redis的命令watch进行构造条件。伪代码如下:

watch price

get price $price

$price = $price + 10

multi

set price $price

exec

解释一下:

watch这里表示监控该key值,后面的事务是有条件的执行,如果从watch的exec语句执行时,watch的key对应的value值被修改了,则事务不会执行。

同样考虑刚刚的场景,

T1时刻,连接1对price进行watch,读出price值为10,目标计算为20;

T2时刻,连接2对price进行watch,读出price值为10,目标计算为20;

T3时刻,连接2将目标值为20写到redis中,执行事务,事务返回成功。

T4时刻,连接1也对price进行写操作,执行事务时,由于之前已经watch了price,price在T1至T4之间已经被修改过了,所以事务执行失败。

综上,该乐观锁机制可以简单明了的解决了写冲突的问题。

又问:如果多个写操作同时过来,100个写操作同时watch,则最终只会有一个成功,99个执行失败,何解?表急,请听下回分解。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值