如果您只有一个数据库实例,您可以创建一个新表来分配 ID:
CREATE TABLE id_gen (
id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL
);
现在您可以轻松地生成新的唯一 ID 并使用它们来存储您的行:
INSERT INTO id_gen () VALUES ();
INSERT INTO foo (id, x) VALUES (LAST_INSERT_ID(), 42);
当然,当你不得不对它进行分片时,你就有点麻烦了。您可以留出一个管理此表的数据库实例,但是您会遇到所有写入的单点故障和严重的 I/O 瓶颈(如果您必须处理地理位置不同的数据中心,这种情况只会变得更糟)。
Instagram 有一篇关于他们的 ID 生成方案的精彩博客文章,它利用 PostgreSQL 的强大功能和一些关于其特定应用程序的知识来跨分片生成唯一 ID。
另一种方法是使用 UUID,它极不可能出现冲突。您可以“免费”获得全球唯一性,但需要进行一些权衡:
- 尺寸稍大:一个 BIGINT 是 8 个字节,而一个 UUID 是 16 个字节;
- 索引的痛苦:对于未排序的键,INSERT 速度较慢。(UUID 实际上比 hashes 更可取,因为它们包含一个按时间戳排序的段。)
另一种方法(前面提到过)是使用可扩展的 ID 生成服务,例如Snowflake。(当然,这涉及到安装、集成和维护所述服务;这样做的可行性是高度特定于项目的。)