Python线程和进程之间的同步

2024-03-29 07:02:13 发布

您现在位置:Python中文网/ 问答频道 /正文

一点背景:

我正在Django中编写一个函数来获取下一个发票号,它需要是连续的(而不是间隙),因此该函数如下所示:

def get_next_invoice_number():
    """
    Returns the max(invoice_number) + 1 from the payment records
    Does NOT pre-allocate number
    """
    # TODO ensure this is thread safe
    max_num = Payment.objects.aggregate(Max('invoice_number'))['invoice_number__max']
    if max_num is not None:
        return max_num + 1
    return PaymentConfig.min_invoice_number

现在的问题是,这个函数只返回max()+1,在我的生产环境中,我有多个Django进程,因此如果对两个不同的付款(在保存第一条记录之前)调用这个函数两次,它们将得到相同的发票号。你知道吗

为了缓解这个问题,我可以重写save()函数来调用get_next_invoice_number(),以最小化这些函数调用之间的时间间隔,但是问题发生的可能性仍然很小。你知道吗

所以我想在approve方法中实现一个锁,比如

from multiprocessing import Lock
lock = Lock()

class Payment(models.Model):
    def approve(self):
        lock.acquire()
        try:
            self.invoice_number = get_next_invoice_number()
            self.save()
        except: 
            pass
        finally:
            lock.release()

所以我的问题是:

  1. 这看起来还好吗?你知道吗
  2. 锁是多进程的,线程呢?你知道吗

更新:

  1. 正如我的同事指出的,当它被部署到多个服务器上时,这是行不通的,锁将毫无意义。你知道吗
  2. 看起来DB事务锁定是一个不错的选择。你知道吗

Tags: thedjango函数fromselflocknumberget
1条回答
网友
1楼 · 发布于 2024-03-29 07:02:13

到目前为止,最简单的方法是使用数据库中现有的用于创建序列的工具。实际上,如果您不介意从1开始的值,您可以使用Django的^{}。你知道吗

如果您的业务需求是这样的,您需要选择一个起始编号,那么您必须在数据库中了解如何执行此操作。这里有somequestions可能会有所帮助。你知道吗

尝试用锁或事务来确保这一点将更难做到,执行起来也更慢。你知道吗

相关问题 更多 >