为了账号安全,请及时绑定邮箱和手机立即绑定

关于《redis实战》中6-9代码片段使用setex锁的不解

关于《redis实战》中6-9代码片段使用setex锁的不解

眼眸繁星 2019-02-20 21:16:36
想了很久,实在不能理解代码清单6-9中锁的使用原理,锁只是设置了一个key,而且完全没有用到(比如if getkey()==true之类的),生成的锁还是随机的,也就是不还是没解决并发的问题吗? 同一时间仍然有可能会有其他客户端对数据进行操作。求大佬解惑,谢谢。 # 代码清单 6-8 # <start id="_1314_14473_8641"/> def acquire_lock(conn, lockname, acquire_timeout=10): # 128位随机标识符。 identifier = str(uuid.uuid4()) end = time.time() + acquire_timeout while time.time() < end: # 尝试取得锁。 if conn.setnx('lock:' + lockname, identifier): return identifier time.sleep(.001) return False # <end id="_1314_14473_8641"/> # 代码清单 6-9 # <start id="_1314_14473_8645"/> def purchase_item_with_lock(conn, buyerid, itemid, sellerid): buyer = "users:%s" % buyerid seller = "users:%s" % sellerid item = "%s.%s" % (itemid, sellerid) inventory = "inventory:%s" % buyerid # 尝试获取锁。 locked = acquire_lock(conn, 'market:') if not locked: return False pipe = conn.pipeline(True) try: # 检查物品是否已经售出,以及买家是否有足够的金钱来购买物品。 pipe.zscore("market:", item) pipe.hget(buyer, 'funds') price, funds = pipe.execute() if price is None or price > funds: return None # 将买家支付的货款转移给卖家,并将售出的物品转移给买家。 pipe.hincrby(seller, 'funds', int(price)) pipe.hincrby(buyer, 'funds', int(-price)) pipe.sadd(inventory, itemid) pipe.zrem("market:", item) pipe.execute() return True finally: # 释放锁。 release_lock(conn, 'market:', locked) # <end id="_1314_14473_8645"/> # 代码清单 6-10 # <start id="_1314_14473_8650"/> def release_lock(conn, lockname, identifier): pipe = conn.pipeline(True) lockname = 'lock:' + lockname while True: try: # 检查并确认进程还持有着锁。 pipe.watch(lockname) if pipe.get(lockname) == identifier: # 释放锁。 pipe.multi() pipe.delete(lockname) pipe.execute() return True pipe.unwatch() break # 有其他客户端修改了锁;重试。 except redis.exceptions.WatchError: pass # 进程已经失去了锁。 return False # <end id="_1314_14473_8650"/>
查看完整描述

2 回答

?
慕斯709654

TA贡献1840条经验 获得超5个赞

请仔细查看一下手册,setnx命令是如果当前redis中没有设置的key才会设置成功返回1,否则设置失败返回0,把它当成锁使用,就是利用了这个特性,至于设置什么值关系不大。

查看完整回答
反对 回复 2019-03-01
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

单从例子上看,acquire_lock 中使用了setnx,只有一个操作可以锁定成功。而且redis是单进程的,所有命令都是一个接着一个串行处理。所以不觉得有什么并发问题

查看完整回答
反对 回复 2019-03-01
  • 2 回答
  • 0 关注
  • 744 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信