2021SC@SDUSC
雪花算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的.
首先在项目中导入相应的依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
</dependency>
配置全局配置类,并统一注解,解决前后端交互Long类型精度丢失的问题
package com.zw.wiki.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
获取机器码,使用机器的
ip
地址取模获取,因为只有一台机器,也可以直接取
1
private static void initMachineId() {
try {
if (!machineInitialized) {
String hostname = InetAddress.getLocalHost().getHostName();
char[] hostnameChars = hostname.toCharArray();
int sumOfHostname = 0;
for (char hostnameChar : hostnameChars) {
sumOfHostname += hostnameChar;
}
machineId = sumOfHostname % MAX_MACHINE;
}
} catch (UnknownHostException e) {
e.printStackTrace();
} finally {
machineInitialized = true;
}
}
根据时间戳同步获取id,如果已经达到最大允许机器上限,那么进入下一毫秒的取值,获取是阻塞的。
private static synchronized long nextId(long nowSeconds) {
long currentTimestamp = nowSeconds;
if (currentTimestamp < lastTimestamp) {
currentTimestamp = lastTimestamp;
}
if (currentTimestamp == lastTimestamp) {
long nextSequence = sequence + 1;
if (nextSequence >= MAX_SEQUENCE) {
return nextId(nowSeconds + 1);
} else {
sequence = nextSequence;
}
} else {
sequence = 0L;
}
lastTimestamp = currentTimestamp;
long timeDelta = currentTimestamp - START_TIMESTAMP;
return timeDelta << TIMESTAMP_LEFT
| machineId << MACHINE_LEFT
| sequence;
}