【问题标题】:How to create a big list of different UUIDs, efficiently?如何有效地创建不同 UUID 的大列表?
【发布时间】:2019-09-22 10:21:24
【问题描述】:

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

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

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

谢谢!

【问题讨论】:

  • 您对重复的担忧是没有根据的:stackoverflow.com/questions/1155008/how-unique-is-uuid
  • 您是否考虑过自动递增的行号或按顺序分配的编号是否比唯一的随机数更适合作为工单 ID?
  • “自动递增的行号或顺序分配的编号”不太合适,因为此代码将位于票证上的二维码下方。
  • 相反:不扫描二维码,是随机数、顺序分配的数字还是其他唯一的数字是不明显的(尤其是二维条码如二维码通常采用某种纠错机制)。这些数字中的任何一个最终都必须分配给某种数据库记录。
  • 但是,如果您的目标是创建“不可预测”的数字,并且您的应用程序可以容忍生成重复的 124 位“随机”数字的风险(尽管可以忽略不计),那么您可以生成一个版本- 4 UUID 借助加密 RNG(node.js 拥有;查看文档)。但是,如果您将生成的工单 ID 的数量非常少(可能大约为一千),那么检查工单号的唯一性并没有什么坏处。另请参阅my article on this matter

标签: node.js list random unique uuid


【解决方案1】:

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

https://minerlock.com/lock/F50f4b8d8e27e

【讨论】:

  • 这是一个例子:
  • | 346 | 2018-02-17 | 21:48:01.0 | iFrannex | | 1f3e315d-b98e-3f67-a663-b2176c200d7a | 170.239.130.1 |
  • 是从库 uuid 生成的吗?
  • 它只是我上传的文件中的一个示例
【解决方案2】:

您可以使用自制的 UUID 函数,它保证是 [0...2128) 范围内的唯一伪随机整数。下面是基于Linear Contguential Generator 的一个。常量取自herehere。您只需要保留之前的数字/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。

【讨论】:

  • 我怎样才能使这些数字不可预测?
  • @DimitrieDavid 抱歉,不明白这个问题 - 什么数字? ac?这些来自我提供的 PCG 随机链接。
【解决方案3】:

您可以创建一个空对象,并且每次生成 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 有什么好处?
  • @DimitrieDavid 这样做是在使用哈希映射,这意味着您不必检查列表中的每个元素以查看它是否与生成的 UUID 匹配.它将要检查的元素数量减少到 1 而不是所有列表。
  • @KevinPastor 你知道,典型的 64 位散列不太适合保存 128 位随机数,对吧?
猜你喜欢
  • 2012-07-01
  • 2014-07-07
  • 1970-01-01
  • 1970-01-01
  • 2018-02-09
  • 2021-08-24
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
相关资源
最近更新 更多