2、在Redis事务中,可利用watch监控某个或几个key值的变化,可以完成Redis 事务的乐观锁。模拟user_1账户中有80元钱,user_2账户有20元钱,然后user_1向 user_2 转了 50元钱?具体代码
时间: 2024-12-18 08:31:00 浏览: 3
在Redis事务中,乐观锁主要是通过`MGET`和`SETNX`命令来实现的。首先,我们需要设置watch来监视用户余额的键,然后尝试获取并检查当前余额是否与预期一致。如果匹配,我们再执行转账操作;如果不匹配,则表示有人在并发环境中修改了数据,需要回滚事务。
以下是一个简单的Python示例,使用`redis-py`库:
```python
import redis
# 创建Redis连接
r = redis.Redis(host='localhost', port=6379, db=0)
# 设置watch key
target_keys = ['user_1:balance', 'user_2:balance']
for key in target_keys:
r.watch(key)
try:
# 获取初始余额
initial_balances = {k: r.get(k) for k in target_keys}
# 模拟转账条件
if all(initial_balances.values()):
amount_to_transfer = 50
# 执行转账
new_balances = {
'user_1:balance': int(initial_balances['user_1:balance']) - amount_to_transfer,
'user_2:balance': int(initial_balances['user_2:balance']) + amount_to_transfer
}
# 使用SETNX原子替换旧余额
pipe = r.pipeline(True)
for old_key, new_value in new_balances.items():
pipe.multi()
pipe.setnx(old_key, new_value)
result = pipe.execute()
# 如果所有setnx都成功,说明没有并发修改
if all(result):
print("Transaction successful")
else:
print("Transaction failed due to concurrent modification")
except redis.WatchError:
print("Transaction failed because of a key change during the watch period")
finally:
# 确保无论交易结果如何,都要取消watch以释放资源
r.unwatch()
```
这个代码片段假设转账操作只在单线程环境下运行,因为Redis的watch不会自动重试。在高并发场景下,你可能需要使用其他机制,如分布式锁或者Redis的乐观锁功能(例如`INCRBY`和`GETSET`)配合使用。
阅读全文