一些背景知识:
我正在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进程,所以如果这个函数被调用两次进行2次不同的付款(在保存第一个记录之前),它们将会得到相同的发票号码。
为了缓解这个问题,我可以覆盖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()
所以我的问题是:
更新