在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位 机器ID 10位 毫秒内序列12位。
10---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
1</pre>
2
3package com.twitter.service.snowflake
4
5import com.twitter.ostrich.stats.Stats
6import com.twitter.service.snowflake.gen._
7import java.util.Random
8import com.twitter.logging.Logger
9
10
16class IdWorker(val workerId: Long, val datacenterId: Long, private val reporter: Reporter, var sequence: Long = 0L)
17extends Snowflake.Iface {
18 private[this] def genCounter(agent: String) = {
19 Stats.incr("ids_generated")
20 Stats.incr("ids_generated_%s".format(agent))
21 }
22 private[this] val exceptionCounter = Stats.getCounter("exceptions")
23 private[this] val log = Logger.get
24 private[this] val rand = new Random
25
26 val twepoch = 1288834974657L
27
28 //机器标识位数
29
30 private[this] val workerIdBits = 5L
31
32//数据中心标识位数
33 private[this] val datacenterIdBits = 5L
34
35//机器ID最大值
36 private[this] val maxWorkerId = -1L ^ (-1L << workerIdBits)
37
38//数据中心ID最大值
39 private[this] val maxDatacenterId = -1L ^ (-1L << datacenterIdBits)
40
41//毫秒内自增位
42 private[this] val sequenceBits = 12L
43
44//机器ID偏左移12位
45
46 private[this] val workerIdShift = sequenceBits
47
48//数据中心ID左移17位
49 private[this] val datacenterIdShift = sequenceBits workerIdBits
50
51//时间毫秒左移22位
52 private[this] val timestampLeftShift = sequenceBits workerIdBits datacenterIdBits
53 private[this] val sequenceMask = -1L ^ (-1L << sequenceBits)
54
55 private[this] var lastTimestamp = -1L
56
57 // sanity check for workerId
58 if (workerId > maxWorkerId || workerId < 0) {
59 exceptionCounter.incr(1)
60 throw new IllegalArgumentException("worker Id can't be greater than %d or less than 0".format(maxWorkerId))
61 }
62
63 if (datacenterId > maxDatacenterId || datacenterId < 0) {
64 exceptionCounter.incr(1)
65 throw new IllegalArgumentException("datacenter Id can't be greater than %d or less than 0".format(maxDatacenterId))
66 }
67
68 log.info("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
69 timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId)
70
71 def get_id(useragent: String): Long = {
72 if (!validUseragent(useragent)) {
73 exceptionCounter.incr(1)
74 throw new InvalidUserAgentError
75 }
76
77 val id = nextId()
78 genCounter(useragent)
79
80 reporter.report(new AuditLogEntry(id, useragent, rand.nextLong))
81 id
82 }
83
84 def get_worker_id(): Long = workerId
85 def get_datacenter_id(): Long = datacenterId
86 def get_timestamp() = System.currentTimeMillis
87
88 protected[snowflake] def nextId(): Long = synchronized {
89 var timestamp = timeGen()
90
91 //时间错误
92
93 if (timestamp < lastTimestamp) {
94 exceptionCounter.incr(1)
95 log.error("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
96 throw new InvalidSystemClock("Clock moved backwards. Refusing to generate id for %d milliseconds".format(
97 lastTimestamp - timestamp))
98 }
99
100 if (lastTimestamp == timestamp) {
101//当前毫秒内,则 1
102 sequence = (sequence 1) & sequenceMask
103 if (sequence == 0) {
104//当前毫秒内计数满了,则等待下一秒
105 timestamp = tilNextMillis(lastTimestamp)
106 }
107 } else {
108 sequence = 0
109 }
110
111 lastTimestamp = timestamp
112//ID偏移组合生成最终的ID,并返回ID
113
114((timestamp - twepoch) << timestampLeftShift) |
115 (datacenterId << datacenterIdShift) |
116 (workerId << workerIdShift) |
117 sequence
118 }
119
120//等待下一个毫秒的到来
121
122protected def tilNextMillis(lastTimestamp: Long): Long = {
123 var timestamp = timeGen()
124 while (timestamp <= lastTimestamp) {
125 timestamp = timeGen()
126 }
127 timestamp
128 }
129
130 protected def timeGen(): Long = System.currentTimeMillis()
131
132 val AgentParser = """([a-zA-Z][a-zA-Z\-0-9]*)""".r
133
134 def validUseragent(useragent: String): Boolean = useragent match {
135 case AgentParser(_) => true
136 case _ => false
137 }
138}
转载自:http://blog.sina.com.cn/s/blog_6b7c2e660102vbi2.html#userconsent#
相关推荐
Twitter的分布式自增ID算法snowflake (Java版)
Twitter的分布式自增ID雪花算法snowflake (Java版)
主要介绍了Java实现Twitter的分布式自增ID算法snowflake,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Twitter Snowflake算法,php版代码; 请见博客: http://blog.csdn.net/envon123/article/details/52953872
We have retired the initial release of Snowflake and working on open sourcing the next version based on Twitter-server, in a form that can run anywhere without requiring Twitter's own infrastructure ...
而twitter的snowflake解决了这种需求,最初是Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序的ID生成机制,所以开发了这样一套唯一的ID生成服务。结构雪花的结构如下(每部分用-分开): 0 - ...
雪花算法,分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。
雪花算法分布式ID生成器 这个项目的目的是提供一个轻量级,高并发,高可用的生成唯一ID的服务,生成的ID是一个64位的长整型,彼此唯一,保持递增,相对有序。来生成ID,用于取代UUID类型无序,128位的字符串形式的ID...
nodejs-snowflake是一种快速可靠的方法,可以为分布式系统生成时间可排序的64位ID。 主要的ID生成功能是使用N-API用C ++编写的,这使得ID生成的过程非常快。 使用C ++进行id生成还可以确保生成的数字大小为64位。 ...
snowflake算法是个啥?首先我来提出个问题,怎么在分布式系统中生成唯一性id并保持该id大致自增?在twitter中这是最重要的业务场景,于是twitter推出了一种snowflake算法。
雪花算法分布式ID生成器 该项目的目的是提供一个轻量级、高并发、高可用的生成唯一ID的服务,生成的ID是一个64位的 长整型,全局唯一,保持递增,相对有序。基于twitter的雪花算法来生成ID,用于取代UUID那种无序、...
snowflake算法是Twitter开源的分布式ID生成算法,结果是一个long类型的ID 。其核心思想:使用41bit作为毫秒数,10bit作为机器的ID(5bit数据中心,5bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每个...
Twitter 的 snowflake 在分布式生成唯一 UUID 应用还是蛮广泛的,基于 snowflake 的一些变种的算法网上也有不少。使用 snowflake 生成 UUID 很多都是在分布式场景下使用,我看了下网上有其中有几篇 PHP 实现的都没有...
提到id生成器,twitter的snowflake算法 不得不被提起,但是snowflake的算法因为使用了二进制的移位做法,导致其生成的算法过 度的对于机器友好,对于人类并不是那么的友好,也就是说snowflake生成的id对于人类来 说...
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的,后面的代码中有...
一个基于Snowflake算法PHP ID生成器(Twitter已宣布)。描述雪花算法PHP实现。 Snowflake是一项网络服务,可通过一些简单的保证大规模生成唯一的ID号。 第一位是未使用的符号位。 第二部分包括一个41位的时间戳...
twitter雪花算法的java实现,分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。 有些时候我们希望能使用...
一个实现 Twitter SnowFlake 算法 的 Go 分布式 UID 生成器
高效GUID产生算法(sequence),基于Snowflake实现64位自增ID算法。新增特性:支持自定义允许时间回拨的范围解决跨毫秒起始值每次为0开始的情况(避免末尾必定为偶数,而不便于取余使用问题)解决高并发场景中获取...
Twitter的雪花算法SnowFlake,使用Java代码实现。 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些...