为什么在GCP上使用Python会生成重复的UUID?

11
我遇到了一个奇怪的问题。我的一些(5%)celery任务被默默地丢弃了。
通过查看celery日志,我发现在某些情况下,相同的任务ID会为不同的任务生成。自然地,任何新任务都会覆盖具有相同任务ID的现有任务;如果旧任务未被执行,则会静默地丢弃旧任务。
在1.5个小时内,相同的UUID被生成了3次。我进行了一些随机抽样,并发现在同一台机器上,在短时间内(1-2小时内)出现这种情况。服务器每天生成约100万个UUID。与具有38位数字的可能UUID数量相比,这是一个带有7位数字的微小数字。
我在Linux VM上运行Python 3.6和Celery 4.4.2。
Celery使用Python的uuid.uuid4参考文献 我不确定该怎么继续下去。是否存在Python版本(或Linux内核)的错误、配置问题或硬件/VM错误?所有这些方案似乎都非常不可能。
更新:
VM是运行Ubuntu 18 LTS的Google Cloud Plaftform计算实例。

有趣。 uuid4只是调用os.urandom 来作为其字节的来源,所以我猜这可能是与随机性相关的平台特定问题? - bnaecker
你有关于虚拟机如何与底层硬件交互的细节吗?我很好奇在这样的设置中随机性实际上来自哪里。 - bnaecker
@bnaecker我在我的问题中添加了更多信息。 - Vedant Agarwala
人们过去曾经看到过 uuid4 的碰撞(https://github.com/ramsey/uuid/issues/80),但在这种特定情况下,得出的结论是这是一个系统问题。 - Roy2012
如果任务在该时间内未被确认,它将会被重新传送并由另一个工作者接手,可能会导致这种行为...您是否使用acks_late=True - DejanLekic
显示剩余2条评论
1个回答

1

我想不出原因,但我实现了一个解决方法。

我对uuid.uuid4进行了猴子补丁。由于某些原因,我无法对celery.utils.uuidkombu.utils.uuid进行相同的操作。

我制作了一个非常简单的随机数生成器,它将系统纳秒时间和主机名连接起来,并生成UUID:

def __my_uuid_generator():
    time_hex = float.hex(time.monotonic())[4:-4]  # 13 chars
    host = hex(abs(hash(socket.gethostname())))[2:]  # 16 chars
    hashed = bytes(f'{time_hex}{host}', 'ascii').hex()[:32]  # always a 32 chars long hex string
    return uuid.UUID(hashed)

# Monkey patch uuid4, because https://dev59.com/21IG5IYBdhLWcg3w6mJ8. Sigh!
uuid.uuid4 = __my_uuid_generator

只是让你知道 - 可以出现重复运行的任务,这不是因为UUID冲突,而是因为我在上面的评论中写的内容... - DejanLekic
@DejanLekic 在时间范围内存在重复项 <可见超时。未设置acks_late。此外,在实施上述措施后,我没有收到重复项。 - Vedant Agarwala

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接