这是一个 Python 函数,用于为 UUID 生成我自己的特定类型(关于为什么我不能使用 uuid.uuid1() 说来话长):

def uuid():
    sec = hex(int(time()))[2:]
    usec = hex(datetime.now().microsecond)[2:]
    rand = hex(choice(range(256)))[2:]

    return upper(sec + usec + rand)
    # 534AD79CDF1D27

现在,让我们让它运行很长时间,看看我们是否发现任何重复:
UUIDs   Duplicates
100000  2
200000  8
300000  8
400000  8
500000  8
600000  9
700000  9
800000  9
900000  9
1000000     10
1100000     14
1200000     14
1300000     14
1400000     17
1500000     17
1600000     18
1700000     21
1800000     24
1900000     24
2000000     27

是的!实际上有近 30 个重复项……现在,这是一个末尾没有随机字节的新函数:
def uuid():
    sec = hex(int(time()))[2:]
    usec = hex(datetime.now().microsecond)[2:]

    return upper(sec + usec)
    #534ADA2AC4A41

让我们看看现在有多少重复:
UUIDs   Duplicates
100000  0
200000  0
300000  0
400000  0
500000  0
600000  0
700000  0
800000  0
900000  0
1000000     0
1100000     0
1200000     0
1300000     0
1400000     0
1500000     0
1600000     0
1700000     0
1800000     0
1900000     0
2000000     0

嗯,你会看吗?没有一个重复!另外,如果您对我如何确定重复次数感到好奇,这里是代码:
len([x for x, y in Counter(ids).items() if y > 1])

现在,进入实际问题: 添加随机生成的字节如何增加重复的数量?

最佳答案

问题是您使用的是没有零填充的 hex()hex(int(time())) 基本上总是 8 个 nybbles 长,因为它增加的很慢,所以第一部分是恒定长度。这里的 Nybble 指的是单个十六进制数字。

但是,hex(datetime.now().microsecond) 不是恒定长度。它会在 1 nybble(最多 9 us)到 5 nybble(999999 us)之间变化。如果没有“随机字节”,这不是问题,因为您可以通过截断秒来唯一地获得微秒值。

但是,您的“随机字节”也是在没有任何填充的情况下生成的!因此,您最终可以生成 1 nybble 随机字节或 2 nybble 随机字节。因此,您最终可能会产生更多冲突,因为您可以使用例如生成相同的 uuid 3-nybble usec 和 2-nybble rand,与 4-nybble usec 和 1-nybble rand 一样。因此,例如,这两个是碰撞:

usec = 0xabc
rand = 0xde


usec = 0xabcd
rand = 0xe

要解决此问题,请填充所有字符串。这很容易用 format 做到:
usec = format(datetime.now().microsecond, '05x') # hexify `microsecond` with 5 fixed hex digits

关于python - 如何添加随机字节*增加*重复?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23046796/

10-09 05:31