2

我们正在构建一个新的 REST API,并且有一些关于主键和幂等键的决定。我们的 API 有很多用户,用户只能查找属于他们的对象。请求经过身份验证,因此我们知道userId与给定请求相关联。

关注的属性:

  • userId用户的标识。
  • idempotenyKey在对 API 的幂等请求中使用的幂等密钥。每个用户唯一。

假设有一个Cars带有端点的假设表GET .../cars/{id},我们将以此为基础进行讨论。

选项

选项 1 - 使用 userId 和 idempotencyKey 的组合作为主键

CREATE TABLE Cars (
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (userId, idempotencyKey),
 INDEX user_index (userId)
);

项目查找: GET .../cars/{idempotencyKey}

想法:

  • 查找中使用的 id 是可以猜测的。
  • 由于对象是经过身份验证的,这似乎不会造成直接的安全问题,但这确实意味着如果 API 中有一个端点允许我们的用户查找某些内容,我们需要假设查找是可猜测的。

选项 2 - 使用 userId + idempotencyKey 的哈希作为主键

CREATE TABLE Cars (
 id VARCHAR(255) NOT NULL,
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (id),
 INDEX user_index (userId)
);

插入时我们会计算id = hash(userId + idempotencyKey).

项目查找: GET .../cars/{id}

想法:

  • 主键是不可猜测的。
  • 这进一步防止了针对ids.
  • 不再是复合主键。
  • 与选项 3 不同,不需要对 (userId, idempotencyKey) 的唯一约束。

选项 3 - 生成 uuid 主键

CREATE TABLE Cars (
 id VARCHAR(255) NOT NULL,
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (id),
 INDEX user_index (userId),
 CONSTRAINT unique_by_user UNIQUE (userId, idempotencyKey)
);

插入时我们会设置id = UUID.randomUUID().

项目查找: GET .../cars/{id}

想法:

  • id 是完全不可猜测的,并且与任何业务数据无关。
  • 需要额外的索引。

选项 4 - 从未向用户公开的自动递增主键

CREATE TABLE Cars (
 id INT NOT NULL AUTO_INCREMENT,
 userId VARCHAR(255) NOT NULL,
 idempotencyKey VARCHAR(255) NOT NULL,
 description VARCHAR(255),
 PRIMARY KEY (id),
 INDEX user_index (userId),
 CONSTRAINT unique_by_user UNIQUE (userId, idempotencyKey)
);

有几种方法可以进行查找。查找可以完全基于 idempotencyKey,即: GET .../cars/{idempotencyKey}

或者,我们可以自动生成一个 referenceId uuid,它将被索引并用于查找。

想法:

  • 主键永远不会暴露给用户,这是一种非常常见的做法。
  • 如果业务逻辑发生变化,则允许更大的灵活性(尽管对于像 userId 和 idempotencyKey 这样的基本概念,我看不出它们会如何变化)。
  • 主键是 INT,因此更小。这允许更小的索引和可以说更高的性能。
  • 再次需要一个额外的索引。

寻求有关采取何种方法的建议。围绕性能和规模的考虑非常重要。

谢谢!

4

0 回答 0