diff --git a/apps/utils/models.py b/apps/utils/models.py index a242ed8e..b68031b6 100755 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -117,25 +117,23 @@ class BaseModel(models.Model): def safe_get_or_create(cls, defaults=None, **kwargs): defaults = defaults or {} - for attempt in range(3): + for i in range(3): + try: + obj = cls.objects.create(**kwargs, **defaults) + return obj, True + except IntegrityError: try: - # 先尝试获取(带锁) - try: - obj = cls.objects.select_for_update().get(**kwargs) - return obj, False - except cls.DoesNotExist: - # 不存在则创建 - obj = cls(**kwargs, **defaults) - obj.save() - return obj, True - except IntegrityError: - # 发生唯一约束冲突时重试 - if attempt == 2: - raise - time.sleep(0.1 * (attempt + 1)) - except Exception: - # 其他异常直接抛出 - raise + # 有别的进程抢先创建了,直接 get + obj = cls.objects.get(**kwargs) + return obj, False + except cls.DoesNotExist: + # 极端并发情况下 create 和 get 都失败,稍微等一下重试 + time.sleep(0.001 * (i + 1)) # 微等一下避免竞争 + continue + + # 最终重试失败(极罕见) + obj = cls.objects.get(**kwargs) + return obj, False def handle_parent(self):