0

一些介绍:在考虑了将在 URL 和其他地方使用的唯一 ID 类型之后,我选择了线性同余生成器 ( http://en.wikipedia.org/wiki/Linear_congruential_generator )。为什么不使用 UUID 或自动增量?

  • UUID 太长且难以存储在 db 中(推荐的方法是将它们转换为 VARBINARY(16))。
  • Auto_increment 公开了新实体的注册和添加序列,并提供了预测下一个 id 的能力。例如,如果一个服务流行起来,用户可以多次注册以获得一个不错的 id,然后尝试出售这样的帐户,id 会给出某种状态:注册越早越酷。我宁愿避免这样的事情。

使用 LCG,序列是随机的,我可以选择参数,以便可能的值很好地适合特定目的的数据类型。例如,对用户 ID 使用 INT UNSIGNED 并选择参数以给出 2^32 的周期。

问题是要生成下一个 id,我需要获取最后一个 id 的值:

nextId = (a * lastId + c) % m
  1. 据我了解,我必须自己设置第一个 ID?我选择哪个号码重要吗?
  2. 什么是生成新 ID 的巧妙方法?也许创建一个表,其中包含每个表的最后生成的 id 列表?或者在每个表中添加一个 auto_increment 列来跟踪最后生成的 id?又如何在短时间内出现大量注册时避免出现问题?

更新1 : 我找到了一种使用此处信息的多用户安全方法:http: //dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id

CREATE TABLE sequences (users INT UNSIGNED NOT NULL, posts BIGINT UNSIGNED NOT NULL);
INSERT INTO sequences VALUES(123456,123456789);

然后得到一个新的ID:

UPDATE sequences SET users=LAST_INSERT_ID((a * users + c) % m);
SELECT LAST_INSERT_ID();
4

1 回答 1

1

要在 MySQL 中可靠地执行此操作,您将需要编写一个存储过程,并使用其中包含最新 ID 的单行表。

您的存储过程需要锁定表,读取最新 ID,生成新 ID,将其更新到表中,解锁表,并将新 ID 返回给调用者。

您还可以保留一个包含您生成的 ID 列表的多行表。在这种情况下,您的存储过程需要锁定、读取最近生成的 ID、生成新 ID、将其插入表中、解锁并返回。显然,在这种情况下,您将需要一种可靠的方法来查找最近生成的 ID。也许使用自动增量列和 ID 列就可以了。

完成您想要的另一种方法是编写一个生成多位随机数的存储过程(我会使用至少 48 个二进制数字),然后尝试将其作为表的主键插入。只要插入因密钥冲突而失败,尝试另一个随机数。这些长随机数比你的 LCG 序列更难预测。

开发完成后,您必须在繁重的多客户端负载下严格测试您的存储过程,然后再将其投入生产。如果你没有充分测试,你后悔的。我凭经验知道这东西很难做对。

UUID 确实具有您提到的大小缺点。但它有一个非常强大的优势:它已经过彻底的测试。如果您选择它,则无需尝试重​​新发明轮子。(根据我重新发明轮子的经验,我想出了一些漏气的轮胎。)

于 2013-06-03T22:34:11.870 回答