雪花算法作为数据表的主键合适吗,如果合适,请给我一个雪花算法的工具类
时间: 2023-06-28 09:07:47 浏览: 115
多语言雪花算法里最好用的主键ID生成工具.zip
雪花算法可以作为数据表的主键,因为它可以保证在分布式系统中生成全局唯一的ID,且不需要进行额外的存储和查询。但是需要注意的是,雪花算法生成的ID可能会存在一定程度的时钟回拨问题,需要在实际应用中进行处理。
关于雪花算法的工具类,可以参考以下Java代码实现:
```java
public class SnowflakeIdGenerator {
//定义起始时间戳,用于减小ID长度
private static final long START_TIMESTAMP = 1480166465631L;
//定义机器ID所占位数
private static final long WORKER_ID_BITS = 5L;
//定义数据中心ID所占位数
private static final long DATA_CENTER_ID_BITS = 5L;
//定义序列号所占位数
private static final long SEQUENCE_BITS = 12L;
//定义机器ID的最大值
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
//定义数据中心ID的最大值
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
//定义序列号的最大值
private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);
//定义机器ID左移位数
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
//定义数据中心ID左移位数
private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
//定义时间戳左移位数
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;
//定义序列号
private long sequence = 0L;
//定义上次生成ID的时间戳
private long lastTimestamp = -1L;
//定义机器ID
private final long workerId;
//定义数据中心ID
private final long dataCenterId;
/**
* 构造函数
*
* @param workerId 机器ID
* @param dataCenterId 数据中心ID
*/
public SnowflakeIdGenerator(long workerId, long dataCenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", MAX_WORKER_ID));
}
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
throw new IllegalArgumentException(String.format("Data center ID can't be greater than %d or less than 0", MAX_DATA_CENTER_ID));
}
this.workerId = workerId;
this.dataCenterId = dataCenterId;
}
/**
* 生成ID
*
* @return ID
*/
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate ID for %d milliseconds", lastTimestamp - timestamp));
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT) |
(dataCenterId << DATA_CENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
/**
* 获取下一个时间戳
*
* @param lastTimestamp 上次生成ID的时间戳
* @return 下一个时间戳
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
}
```
使用时可以创建一个SnowflakeIdGenerator对象,传入机器ID和数据中心ID,然后调用nextId()方法即可生成唯一ID。例如:
```java
public class Test {
public static void main(String[] args) {
SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
long id = idGenerator.nextId();
System.out.println(id);
}
}
```
阅读全文