我过去通常使用数据库序列实现 序列号生成

例如使用 Postgres SERIAL 类型 http://www.neilconway.org/docs/sequences/

我很好奇如何为没有数据库的大型分布式系统生成序列号。是否有人对以 线程安全 方式为多个客户端实现序列号生成的最佳实践有任何经验或建议?

最佳答案

好的,这是一个非常古老的问题,我现在第一次看到。

您需要区分 序列号 唯一 ID ,它们是(可选地)按时间特定标准松散排序的(通常可以按特定时间进行排序)。真正的序列号意味着知道所有其他 worker 做了什么,因此需要共享状态。以分布式、大规模的方式做到这一点并不容易。您可以查看网络广播、每个工作人员的窗口范围和 distributed hash tables for unique worker IDs 之类的内容,但工作量很大。

唯一ID是另一回事,有几种很好的方法可以以分散的方式生成唯一ID:

a) 您可以使用 Twitter's Snowflake ID network service 雪花是:

  • 网络化服务,即通过网络调用获取唯一ID;
  • 产生按生成时间排序的 64 位唯一 ID;
  • 并且该服务具有高度可扩展性和(潜在)高可用性;每个实例每秒可以生成数千个 ID,并且您可以在 LAN/WAN 上运行多个实例;
  • 用 Scala 编写,运行在 JVM 上。

  • b) 您可以使用源自 how UUIDs 和 Snowflake 的 ID 的 方法在客户端本身上生成唯一 ID。 有多种选择,但大致如下:
  • 最高 40 位左右: 时间戳; ID的生成时间。 (我们使用时间戳的最高有效位使 ID 可按生成时间排序。)
  • 接下来的 14 位左右: 每个生成器的计数器,,每个生成器每生成一个新 ID,就会增加 1。这确保在同一时刻(相同时间戳)生成的 ID 不会重叠。
  • 最后 10 位左右: 每个生成器的唯一值。 使用这个,我们不需要在生成器之间做任何同步(这是非常困难的),因为所有生成器都会因为这个值产生不重叠的 ID。

  • c) 您可以仅使用 时间戳和随机值在客户端上生成 ID。 这避免了需要知道所有生成器,并为每个生成器分配一个唯一值。另一方面,这样的 ID 不能保证是全局唯一的,它们只是很有可能是唯一的。 (要发生碰撞,一个或多个生成器必须在完全相同的时间创建相同的随机值。)大致如下:
  • 最高 32 位: Timestamp, ID 的生成时间。
  • 最低 32 位: 32 位随机性, 为每个 ID 重新生成。

  • d) 简单的方法, use UUIDs / GUIDs

    关于java - 分布式序列号生成?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2671858/

    10-16 21:31