如何有效地创建一个包含不同 UUID 的大列表?

How to create a big list of different UUIDs, efficiently?

我想为活动生成门票。我需要生成很多,因此我决定将票号作为 UUID。问题是如何生成一个大的 UUID 列表并且它是不同的。

我知道检查现有列表中生成的每个新 UUID 的简单方法,但这对性能不是很友好。 :)

我正在使用带有 UUID v4 的 NodeJS。

谢谢!

您可以创建一个空对象,每次生成 UUID 时,您都会向该对象添加一个属性,其中键是生成的 UUID。当您将生成另一个 UUID 时,您只需检查对象属性是否为 undefined 或不查看它是否已被使用。

const uuids = [];
let uuidUsed = {};
const size = 10;
for (let i = 0; i < size; i++) {
    let uuid = uuidv4();
    while (uuidUsed[uuid] !== undefined) {
        uuid = uuidv4();
    }
    uuidUsed[uuid] = true;
}

您可以使用自制的 UUID 函数,它保证是 [0...2128) 范围内唯一的伪随机整数。下面是基于 Linear Contguential Generator. Constants are taken from here or here 的一个。您只需要保留上一个 number/UUID 就可以生成下一个,无需检查,因为它只会在 2128.

的完整周期后重复

代码依赖 BigInt,使用节点 v12 测试

const a = 199967246047888932297834045878657099405n; // should satisfy a % 8n = 5n
const c = 1n;                                       // should be odd
const m = (1n << 128n);
const mask = m - 1n;

function LCG128(state) {
    return (BigInt(state) * a + c) & mask; // same as % m
}

q = 7654321n; // seed

q = LCG128(q);
q.toString(16); // first UUID

q = LCG128(q);
q.toString(16); // second UUID

q = LCG128(q);
q.toString(16); // third UUID

更新

只是为了在手头的问题上更具哲学性:

  1. 您可以将 UUID4 视为黑盒并相信它 - 这是@ChrisWhite 提出的建议
  2. 您可以将 UUID4 视为黑匣子并且不信任它 - 这是您建议检查列表或@KevinPastor 回答的内容
  3. 制作你自己的透明盒子,它产生的数字在适当的范围内并且是独一无二的 - 这是我的建议

LCG 方法的美妙之处在于,如果有良好的乘数和进位,它可以唯一且可逆地将范围 [0...2128) 映射到自身(它可以为64 位数字,具有不同的 ac 或 32 位数字等等)。您甚至可以使用从 0 开始到 2128-1 的计数器作为输入,它会在相同范围内生成不可重复的数字,填充整个 [0...2128).所以你知道,如果你将它与以前的 uuid 链接起来,或者使用计数器,则冲突的可能性为 0。

这里是 446,538 IPs 的列表,格式如下: |编号 |日期 |姓名 | uuid | ip |

https://minerlock.com/lock/F50f4b8d8e27e