gpt4 book ai didi

python - 在 Python Web 应用程序中执行全局锁定?

转载 作者:IT王子 更新时间:2023-10-29 06:15:43 24 4
gpt4 key购买 nike

基本上,我有以下问题。有一个处理付款的订单处理系统。在极少数情况下,我们最终会收到双重订单,因为当我们通过 API 查询信用卡处理程序时,如果用户非常快速地刷新页面,信用卡处理程序有时会将两个请求都响应为“成功”,我们在系统中获得了两个成功的“付费”事件。

所以我的想法是围绕支付内容(每个订单)实现锁定,如果锁定被锁定,则告诉客户关闭(如果客户刷新页面非常快,就会发生这种情况 - 我认为在我们的例子中是实际上是故意的)。

所以我考虑用 Redis 来做,并想到了这个:

def _PaymentInterlock(object):
def __init__(self, pp):
self.key = GlobalKey('pay_ilk_%s'%pp._ident)

def lock(self):
self.key(1)

def unlock(self):
self.key.delete()

def try_lock(self):
result = self.key()
if result == 1:
return False
self.lock()
return True

唯一的问题是 try_lock 操作不是原子的(与真正的比较和存储 操作相反),所以从技术上讲,两个 WSGI worker 可以 key 未命中,然后都锁定“锁”,导致同样的问题。

关于我将如何解决这类问题有什么建议吗?

最佳答案

由于 Redis 的单线程特性,在 Redis 中锁定实际上非常容易。只需使用 SetNX .该链接页面上有更多信息,但基本思想是:

  1. Client1 请求锁定。如果它得到它,它会将锁名称设置为某个唯一的 transaction_id。该值应为当前时间。
  2. Client2(可能是用户刷新)要求锁定同名。它没有收到。
  3. 作为退避措施,client2 检查锁上的时间戳。如果它超过了一些 max_time,这意味着由于某种原因 client1 没有正确释放它的锁,所以我们无论如何都会用新的时间戳将锁授予 client2。否则,client2 不走运,不会继续。
  4. Client1 完成了它正在做的事情(在您的例子中是交易)并释放了锁,所以现在它可以再次访问,以防用户想对交易做其他事情。

这是此设计模式的简化/修改版本。我在生产中使用了非常相似的东西:

def getRedisLock(name, max_time, r):
lock = r.setnx(name, int(time.mktime(time.gmtime())))
if not lock:
lock_time = int(r.get(name))
#if the lock expired (assume some client failed)
if lock_time + max_time < int(time.mktime(time.gmtime())):
old_time = int(r.getset(name, int(time.mktime(time.gmtime()))))
if old_time == lock_time:
lock = True
#If you still have no lock, do something special here, if you want
if not lock:
pass
return lock

def releaseRedisLock(self, name):
r = self.r
return r.delete(name)

只需在每次交易之前使用一些唯一的 transaction_id 调用 getRedisLock()。只有在获得锁定时才处理信用卡,否则告诉用户不要再 SCSS 了:)

关于python - 在 Python Web 应用程序中执行全局锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18345572/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com