问题
我一般在过去使用数据库序列实现了序列号生成。
我很好奇,因为如何为没有数据库的大型分布式系统生成序列号。对于多个客户,a线程安全手册中是否有任何实现序列号生成的最佳实践经验或建议?
#1 热门回答(105 赞)
好的,这是一个非常古老的问题,我现在第一次看到它。
你需要区分序列号和唯一ID,这些ID(可选)可以按特定条件(通常为生成时间)进行松散排序。真正的序列号意味着知道所有其他工作者所做的事情,因此需要共享状态。没有简单的方法以分布式,高规模的方式这样做。你可以查看网络广播,每个工作人员的窗口范围以及distributed hash tables for unique worker IDs等内容,但这需要做很多工作。
唯一ID是另一个问题,有几种以分散方式生成唯一ID的好方法:
a)你可以使用Twitter's Snowflake ID network service.Snowflake是:
网络服务,即你进行网络呼叫以获取唯一ID;
产生按生成时间排序的64位唯一ID;
该服务具有高度可扩展性和(可能)高度可用性;每个实例每秒可以生成数千个ID,你可以在LAN / WAN上运行多个实例;
用Scala编写,在JVM上运行。
b)你可以使用从how UUIDs派生的方法在客户端本身生成唯一ID,并制作Snowflake的ID。有多种选项,但有些内容如下:
最重要的40位左右:时间戳; ID的生成时间。 (我们使用时间戳的最高位来按生成时间对ID进行排序。)
接下来的14个位:每个发生器计数器,每个生成器为每个生成的新ID递增1。这可确保在同一时刻生成的ID(相同时间戳)不重叠。
最后10位:每个发生器的唯一值。使用它,我们不需要在生成器之间进行任何同步(这是非常困难的),因为所有生成器都会因为此值而生成非重叠的ID。
c)你可以使用a**时间戳和随机值在客户端上生成ID。**这样就无需了解所有生成器,并为每个生成器分配一个唯一值。另一方面,这些ID不保证是全球唯一的,它们很可能是唯一的。 (要碰撞,一个或多个生成器必须在同一时间创建相同的随机值。)以下内容:
最重要的32位:时间戳,ID的生成时间。
最低有效32位:32位随机性,为每个ID重新生成。
#2 热门回答(15 赞)
你可以让每个节点都有一个唯一的ID(无论如何都可以使用),然后将其添加到序列号中。
例如,节点1生成序列001-00001 001-00002 001-00003等,节点5生成005-00001 005-00002
独特 :-)
或者,如果你想要某种集中式系统,你可以考虑让你的序列服务器以块的形式给出。这显着降低了开销。例如,不是从中央服务器为每个必须分配的ID请求新ID,而是从中央服务器请求10,000个块中的ID,然后在用完时只需要执行另一个网络请求。
#3 热门回答(13 赞)
现在有更多的选择。
你这个问题是"老",我来到这里,所以我认为留下我所知道的选项(到目前为止)可能是有用的:
你可以试试Hazelcast。在它的1.9版本中,它包含了java.util.concurrent.AtomicLong的Distributed实现
你也可以使用Zookeeper。它提供了创建序列节点的方法(附加到znode名称,我更喜欢使用节点的版本号)。你要小心这一点:如果你不想在你的序列中错过数字,那可能不是你想要的。
干杯