以下是使用 Spring Boot 实现雪花算法的完整代码。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SnowflakeGeneratorApplication {public static void main(String[] args) {SpringApplication.run(SnowflakeGeneratorApplication.class, args);}}
import org.springframework.stereotype.Component;@Component
public class SnowflakeGenerator {private final long START_STMP = 1480166465631L;// 每部分占用的位数,注意不能超过63位,即 long 类型的最大位数private final long SEQUENCE_BIT = 12; // 序列号占用的位数private final long MACHINE_BIT = 5; // 机器标识占用的位数private final long DATACENTER_BIT = 5;// 数据中心占用的位数// 每部分最大值private final long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);private final long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);private final long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);// 每部分向左的位移private final long MACHINE_LEFT = SEQUENCE_BIT;private final long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private final long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;private long datacenterId; // 数据中心private long machineId; // 机器标识private long sequence = 0L; // 序列号private long lastStmp = -1L; // 上一次时间戳public SnowflakeGenerator() {this.datacenterId = getDatacenterId(MAX_DATACENTER_NUM);this.machineId = getMachineId(MAX_MACHINE_NUM);}public synchronized long nextId() {long currStmp = getNewstmp();if (currStmp < lastStmp) {throw new RuntimeException("Clock moved backwards. Refusing to generate id");}if (currStmp == lastStmp) {sequence = (sequence + 1) & MAX_SEQUENCE;if (sequence == 0L) {currStmp = getNextMill();}} else {sequence = 0L;}lastStmp = currStmp;return (currStmp - START_STMP) << TIMESTMP_LEFT //| datacenterId << DATACENTER_LEFT // 数据中心部分| machineId << MACHINE_LEFT // 机器标识部分| sequence; // 序列号部分}private long getNextMill() {long mill = getNewstmp();while (mill <= lastStmp) {mill = getNewstmp();}return mill;}private long getNewstmp() {return System.currentTimeMillis();}/*** 获取 maxDatacenterId*/protected long getDatacenterId(long maxDatacenterId) {long id = 0L;try {InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);if (network == null) {id = 1L;} else {byte[] mac = network.getHardwareAddress();if (mac != null) {id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;id = id % (maxDatacenterId + 1);}}} catch (Exception e) {System.out.println("get data center id error:" + e.getMessage());}return id;}/*** 获取 maxWorkerId*/protected long getMachineId(long maxWorkerId) {long id = 0L;try {InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);if (network == null) {id = 1L;} else {byte[] mac = network.getHardwareAddress();if (mac != null) {id = ((0x0000FF & (long) mac[mac.length - 2]) | (0x00FF00 & (((long) mac[mac.length - 1]) << 8))) >> 4;id = id % (maxWorkerId + 1);}}} catch (Exception e) {System.out.println("get machine id error:" + e.getMessage());}return id;}}
使用:
@Autowired
private SnowflakeGenerator snowflakeGenerator;long id = snowflakeGenerator.nextId();