2014-09-08 1 views
0

비트 처리합니다파이썬은 스레드간에 동기화 및 배경의

내가 (간격되지 않음) 연속 할 필요가 다음 송장 번호를 얻기 위해 장고의 기능을 쓰고를, 그래서 기능은 다음과 같습니다 :

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 

지금 문제는,이 기능은 내가 여러 장고 프로세스를, 그래서 (첫 번째 레코드를 저장하기 전에)이 기능은 2 개 개의 다른 지불 두 번 호출되는 경우 내 생산 환경에서 max()+1 반환, 그들은 얻을 것이다 동일한 인보이스 번호.

이 문제를 완화하려면 을 호출하여 이러한 함수 호출 간의 시간 간격을 최소화해야하지만 아직 문제가 발생할 가능성은 매우 낮습니다.

그래서 나는 그래서 내 질문은,

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. 잠금은 다중 프로세스를위한 것이며, 스레드는 어떻습니까?

UPDATE : 내 동료는 지적이는 여러 서버에 배포 때 작동하지 않을

  1. , 잠금 의미가 될 것입니다.
  2. DB 트랜잭션 잠금이 필요합니다.
+0

1. 왜 순차적이어야합니까? 2.) 수표에 인보이스 ID를 미리 할당 할 수없는 이유는 무엇입니까 (예 : DB의 자동 증분 기능 사용)? 그렇게 중복되지 않습니다. – Andy

+0

@Andy 송장 번호가 순차적이되도록하는 비즈니스 회계 요구 사항입니다. –

답변

0

이 작업을 수행하는 가장 쉬운 방법은 시퀀스 작성을위한 데이터베이스의 기존 도구를 사용하는 것입니다. 사실 1부터 시작하는 값에 신경 쓰지 않는다면 장고의 AutoField을 사용할 수 있습니다.

비즈니스 요구 사항이 시작 번호를 선택해야하는 경우, 데이터베이스에서이를 수행해야합니다. 도움이 될 somequestions 있습니다.

잠금 또는 트랜잭션으로이를 보장하려는 시도는 더 어렵고 수행 속도가 느려집니다.