分布式系统可以通过Flake或加密ID生成唯一的id(例如,128位杂音3)。
想知道每种方法的优缺点是什么。
我将假设 128 位 id,有点像 UUID。不过,让我们从基线开始
TL;DR:使用随机 ID。当且仅当您遇到数据库性能问题时,请尝试片状 ID。
自动递增 ID
自动递增 ID 是指后端系统为每个新实体分配一个唯一的密集 ID。这通常由数据库完成,但并非总是如此。
明显的优势是保证 id 对于您的系统是唯一的,尽管 128 位可能有点矫枉过正。
第一个缺点是每次暴露ID时都会泄漏信息。您泄露了其他ID(攻击者可以轻松猜测要查找的内容)。您还会泄露您的系统有多忙(您的竞争对手现在知道您在一段时间内创建了多少个 ID,并且可以推断出财务信息)。
第二个缺点是后端不再具有可扩展性。您被绑定到一些缓慢,可扩展性较差的id生成器,这始终是大型系统中的瓶颈。
随机 ID
随机 ID 是指您只生成 128 个随机字节。 v4 UUID122位随机 ID(例如2bbfb5ba-f5a2-11e7-8c3f-9a214cf093ae
)。这些实际上也是独一无二的。
随机 ID 摆脱了自动增量 ID 的两个缺点:它们不泄漏任何信息并且是无限可扩展的。
当将 id 存储在 b 树(à la 数据库)中时,缺点是因为它们随机化树访问的内存/磁盘页。这可能是系统速度变慢的原因。
对我来说,这仍然是理想的 id 方案,你应该有一个很好的理由来摆脱它。(即探查器数据)。
片状内酯
片状 id 是随机 ID,不同之处在于高位k
位取自时间戳的低位。例如,您可能会连续获得以下三个 ID,其中顶部位非常接近。
- 2bbfb5baf5a211e78c3f9a214cf093ae
- 2bbf9d4ec10c41049fb1671d6616b213
- 2BC6bb66e5964fb59050fcf3beed51b1
虽然您可能会泄露一些信息,但如果k
和时间戳粒度设计良好,则不会泄露太多信息。
但是,如果你错误地设计了id,它们可能没有多大帮助,要么更新得太少——导致b树依赖于顶部的随机位来否定有用性——要么太频繁——因为你的更新而破坏数据库。
注意:通过时间粒度,我的意思是时间戳的低位更改的频率。根据您的数据吞吐量,您可能希望此值为小时、十分钟或分钟。这是一种平衡。
如果您看到 id 在其他方面没有语义(即从不从顶部位推断任何内容),那么您可以随时更改这些参数中的任何一个而不会中断——甚至可以回到纯随机k = 0
。
加密标识
我假设你的意思是 id 中加密了一些语义信息。也许喜欢哈希德?
缺点比比皆是:
- 对于不同的数据,您将有不同的长度 ID,除非您有固定长度的协议。
- 你会很想向 id 添加越来越多的信息。
- 看起来是随机的,但没有缓解措施将片状时间戳添加到前面
- ID 与制造它的系统相关联。您可能会开始要求该系统提供 id 的解密版本,而不仅仅是询问它指向的数据。
- 您的系统会消耗解密 ID 的时间以提取数据。
- 添加加密问题
- 如果密钥泄露会怎样?(最好不要有太敏感的数据,客户名称,或者天堂禁止信用卡号)
- 协调密钥轮换。
- 像哈希德这样的小ID可能是暴力攻击。
如您所见,我一般不喜欢语义 ID。有几个地方我使用它们,尽管我称它们为令牌。这些不会作为密钥存储在数据库中(或者可能没有存储在任何地方)。
例如,我对分页令牌使用加密:分页 API 的加密{last-id / context}
。我更喜欢这样,而不是让客户端传递上一页的最后一个元素,因为我们对用户隐藏了数据库上下文。它对每个人来说都更简单,加密只不过是混淆(没有敏感信息)。