在分布式系统中,需要生成全局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的雪花算法(Snowflake)提供了一种高效、简单的分布式ID生成方案,通过合理的结构设计,确保了全局唯一性和顺序性。在Java环境下,可以通过实现相应的类和方法轻松地引入这一机制,为分布式系统的...
【Java实现Twitter的分布式自增ID算法snowflake】 在分布式系统设计中,生成全局唯一ID是一个常见的需求。Twitter的Snowflake算法就是为了解决这个问题而诞生的,它提供了一种高效、有序且不会冲突的ID生成策略。...
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 ...
在分布式系统中,为了生成全局唯一的自增ID,可以使用Snowflake算法、Twitter的分布式ID生成服务,或者基于Redis的序列号生成方案。Spring Boot可以轻松集成这些方案,通过配置和注解简化开发流程。 2. **Redis作为...
而twitter的snowflake解决了这种需求,最初是Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序的ID生成机制,所以开发了这样一套唯一的ID生成服务。结构雪花的结构如下(每部分用-分开): 0 - ...
Snowflake算法是由Twitter开源的一种高效且可扩展的分布式ID生成方案,广泛应用于Java和其他编程语言的系统中。 Snowflake算法的核心思想是将64位的整数划分为不同的部分,分别为: 1. **时间戳**(41位):自定义...
3. **分布式ID生成器**:如Snowflake算法,它是由Twitter开源的一种分布式ID生成方案。通过时间戳、工作机器ID和序列号三部分组合,可以生成全局唯一的ID,而且排序性好。在Java中,可以使用诸如Snowflake或者其变种...
public class SnowflakeIdGenerator { private static final SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0); public static long generateId() { return idWorker.nextId(); } } ``` 在这个例子中...
- 雪花算法由Twitter提出,生成的ID由时间戳、工作节点ID和序列号三部分组成,全局唯一且有序。 - 时间戳确保ID的全局唯一性和时间顺序;工作节点ID确保不同节点生成的ID不会冲突;序列号在每个节点内部确保唯一性...
为解决此问题,可以使用全局自增序列,如Twitter的Snowflake算法,它结合时间戳、工作节点ID和序列号生成全局唯一的64位ID。 2. UUID(通用唯一标识符):UUID是一种广泛使用的全局唯一ID生成方案,但其128位长度...
1. **Snowflake算法**:这是一种常见的分布式ID生成策略,由Twitter开源。它通过时间戳、工作节点ID和序列号三部分组成,确保全局唯一性。然而,这里的描述并没有明确提及Snowflake,而是暗示了可能有其他自定义实现...
Twitter的Snowflake是一种分布式ID生成算法,用于在大规模分布式系统中生成全局唯一的、有序的64位整数ID。这个算法由Twitter开源,解决了在分布式环境下如何生成具有时间序列属性且不重复的ID的问题。现在,我们将...
12. **分布式ID生成器**: 如Twitter的Snowflake算法,生成全局唯一且递增的ID。Python实现将关注时间戳、机器标识和序列号的组合。 项目中的实用工具类可能包括哈希函数、网络通信模块、并发控制、日志记录、配置...
雪花算法是由Twitter开源的一种分布式ID生成算法,它能够为分布式系统中的每个实体生成全局唯一的、单调递增的64位整数ID。这种算法在大数据和分布式环境下广泛应用于主键生成,因为它解决了在分布式环境下的ID唯一...
Snowflake算法就是一种被广泛使用的分布式ID生成方案,它由Twitter开源,具有时间戳、工作机器ID和序列号三部分组成,能够确保在分布式环境下生成的ID具有唯一性、有序性和高性能。 Snowflake算法的核心思想是将64...
Twitter开源的Snowflake算法是一种常用的分布式ID生成策略,它将ID分为三部分:时间戳(41位)、工作机器ID(10位)和序列号(12位)。通过这种方式,可以保证ID的全局唯一性,并且有序。 #### 3.2 UUID UUID...
这是一种基于Twitter开源的ID生成算法。它通过将ID分成多个部分(如时间戳、机器ID、序列号等),从而保证了ID的全局唯一性。此算法广泛应用于高并发场景下的分布式系统中。 - **优点**:支持高并发,性能优越;...
cpp-idgen可能采用了一种类似于Twitter的Snowflake算法或者百度的WID(Worker ID)算法,这些算法将ID分为多个部分,如时间戳、工作节点ID和序列号,确保了ID的唯一性和顺序性。具体实现可能会包括以下几个步骤: - ...