雪花算法实战

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
public class SnowflakeDistributeId {
private long startTime = 1572537600000L;
private final long clusterIdBits = 6L;
private final long maxClusterId = 63L;
private final long machineIdBits = 6L;
private final long maxMachineId = 63L;
private final long sameServiceBits = 1L;
private final long maxServiceId = 1L;
private final long sequenceBits = 9L;
private final long sameServiceLeftShift = 9L;
private final long machineIdLeftShift = 10L;
private final long clusterIdLeftShift = 16L;
private final long timestampLeftShift = 22L;
private final long sequenceMask = 511L;
private long lastTimestamp = -1L;
private long clusterId;
private long machineId;
private long serviceId;
private long sequence = 0L;

public SnowflakeDistributeId(long clusterId, long machineId, long serviceId) {
Objects.requireNonNull(this);
Object[] var10003;
if (clusterId <= 63L && clusterId >= 0L) {
Objects.requireNonNull(this);
if (machineId <= 63L && machineId >= 0L) {
Objects.requireNonNull(this);
if (serviceId <= 1L && serviceId >= 0L) {
this.clusterId = clusterId;
this.machineId = machineId;
this.serviceId = serviceId;
} else {
var10003 = new Object[1];
Objects.requireNonNull(this);
var10003[0] = 1L;
throw new IllegalArgumentException(String.format("serviceId can't be greater than %d or less than 0", var10003));
}
} else {
var10003 = new Object[1];
Objects.requireNonNull(this);
var10003[0] = 63L;
throw new IllegalArgumentException(String.format("machineId can't be greater than %d or less than 0", var10003));
}
} else {
var10003 = new Object[1];
Objects.requireNonNull(this);
var10003[0] = 63L;
throw new IllegalArgumentException(String.format("clusterId can't be greater than %d or less than 0", var10003));
}
}

public synchronized long nextId() {
long timestamp = this.timeGen();
if (timestamp < this.lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", this.lastTimestamp - timestamp));
} else {
if (this.lastTimestamp == timestamp) {
this.sequence = this.sequence + 1L & 511L;
if (this.sequence == 0L) {
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0L;
}

this.lastTimestamp = timestamp;
long var10000 = timestamp - this.startTime << 22;
long var10001 = this.clusterId;
Objects.requireNonNull(this);
var10000 |= var10001 << 16;
var10001 = this.machineId;
Objects.requireNonNull(this);
var10000 |= var10001 << 10;
var10001 = this.serviceId;
Objects.requireNonNull(this);
return var10000 | var10001 << 9 | this.sequence;
}
}

public static long getMaxId(Date endTime) {
Calendar c = Calendar.getInstance();
c.setTime(endTime);
c.set(14, 999);
SnowflakeDistributeId d = new SnowflakeDistributeId(0L, 0L, 0L);
long var10000 = c.getTimeInMillis() - d.startTime;
Objects.requireNonNull(d);
var10000 <<= 22;
Objects.requireNonNull(d);
long var10001 = ~(-1L << 6);
Objects.requireNonNull(d);
var10000 |= var10001 << 16;
Objects.requireNonNull(d);
var10001 = ~(-1L << 6);
Objects.requireNonNull(d);
var10000 |= var10001 << 10;
Objects.requireNonNull(d);
var10001 = ~(-1L << 1);
Objects.requireNonNull(d);
var10000 |= var10001 << 9;
Objects.requireNonNull(d);
return var10000 | 511L;
}

public static long getMinId(Date startTime) {
SnowflakeDistributeId d = new SnowflakeDistributeId(0L, 0L, 0L);
long var10000 = startTime.getTime() - d.startTime;
Objects.requireNonNull(d);
var10000 <<= 22;
Objects.requireNonNull(d);
var10000 |= (long)(0 << 16);
Objects.requireNonNull(d);
var10000 |= (long)(0 << 10);
Objects.requireNonNull(d);
return var10000 | (long)(0 << 9) | 0L;
}

protected long tilNextMillis(long lastTimestamp) {
long timestamp;
for(timestamp = this.timeGen(); timestamp <= lastTimestamp; timestamp = this.timeGen()) {
}

return timestamp;
}

protected long timeGen() {
return System.currentTimeMillis();
}

public static synchronized void check(Set<Long> set, long s) {
if (set.contains(s)) {
System.err.println(s);
} else {
set.add(s);
}

}

public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(11, 21);
c.set(12, 24);
c.set(13, 44);
c.set(14, 0);
System.out.println(c.getTimeInMillis());
System.out.println(System.currentTimeMillis());
long max = getMaxId(c.getTime());
long min = getMinId(c.getTime());
System.out.println(max);
System.out.println(min);
Calendar c2 = Calendar.getInstance();
c2.set(1, 2090);
System.out.println("---" + c2.getTimeInMillis());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class GeneratedIDFactory {
private final ConcurrentHashMap<String, SnowflakeDistributeId> distributeIds = new ConcurrentHashMap();
private final long clusterId;
private final long machineId;
private final long serviceId;

public GeneratedIDFactory(long clusterId, long machineId, long serviceId) {
this.clusterId = clusterId;
this.machineId = machineId;
this.serviceId = serviceId;
}

private SnowflakeDistributeId getSnowflakeDistributeId(String type) {
SnowflakeDistributeId distributeId = (SnowflakeDistributeId)this.distributeIds.get(type);
if (distributeId == null) {
distributeId = new SnowflakeDistributeId(this.clusterId, this.machineId, this.serviceId);
SnowflakeDistributeId tmp = (SnowflakeDistributeId)this.distributeIds.putIfAbsent(type, distributeId);
if (tmp != null) {
distributeId = tmp;
}
}

return distributeId;
}

public long generatId(String type) {
return this.getSnowflakeDistributeId(type).nextId();
}
}

用法

1
2
3
4
5
6
7
8
9
10
@Bean
public GeneratedIDFactory id() {
GeneratedIDFactory generatedIDFactory = new GeneratedIDFactory(1, 1, 1);
return generatedIDFactory;
}

@Autowired
private GeneratedIDFactory generatedIDFactory;

generatedIDFactory.generatId("user")