cf-framework模块新增biz-id,统一封装雪花id生成注入

This commit is contained in:
gaoqr
2025-02-18 15:25:11 +08:00
parent 47e4e69354
commit d50d4772f0
5 changed files with 64 additions and 2 deletions
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.cf.imes</groupId>
<artifactId>cf-framework</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cf-spring-boot-starter-biz-id</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>主键id生成</description>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 -->
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>com.cf.imes</groupId>
<artifactId>cf-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,19 @@
package com.cf.imes.framework.id.config;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
* ip自动注册配置
*
* @author 晨丰科技
*/
@AutoConfiguration
public class ChenfengIDAutoConfiguration {
@Bean
public SnowflakeIdWorker3rd ipQueryService() {
return new SnowflakeIdWorker3rd();
}
}
@@ -0,0 +1,25 @@
package com.cf.imes.framework.id.core.util;
import java.util.concurrent.atomic.AtomicInteger;
public class MinuteCounter {
private static final int MASK = 0x7FFFFFFF;
private final AtomicInteger atom;
public MinuteCounter() {
atom = new AtomicInteger(0);
}
public final int incrementAndGet() {
return atom.incrementAndGet() & MASK;
}
public int get() {
return atom.get() & MASK;
}
public void set(int newValue) {
atom.set(newValue & MASK);
}
}
@@ -0,0 +1,130 @@
package com.cf.imes.framework.id.core.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
/**
* @ClassName: SnowflakeIdWorker3rd
* @Description:snowflake算法改进
* @author: yonnie
* @date: 2024/06/18 14:10:47
* @version V1.0
*
* 将产生的Id类型更改为Integer 32bit <br>
* 把时间戳的单位改为分钟,使用25bit的时间戳
* 7bit作为自增值即 2^7 = 128
*/
@Slf4j
@Component
public class SnowflakeIdWorker3rd {
/** 初始时间 (2024-01-01: 1704038400) */
// private final int twepoch = 28400640;// 1704038400000L/1000/60;
private final int twepoch = 1704038400;
/** 序列在id中占位数 */
private final long sequenceBits = 7L;
/** 时间截向左移7bit */
private final long timestampLeftShift = sequenceBits;
/** 生成序列的MASK (0x7F) */
private final int sequenceMask = -1 ^ (-1 << sequenceBits);
/** 分钟内序 (0~127) */
private int sequence = 0;
private int laterSequence = 0;
/** 上次生成ID的时间戳 */
private int lastTimestamp = -1;
private final MinuteCounter counter = new MinuteCounter();
/** 预支时间标志 */
boolean isAdvance = false;
// ==============================Constructors=====================================
public SnowflakeIdWorker3rd() {
// No Args Constructors
}
// ==============================Test=============================================
/** 测试 */
public static void main(String[] args) {
SnowflakeIdWorker3rd idWorker = new SnowflakeIdWorker3rd();
for (int i = 0; i < 1000; i++) {
long id = idWorker.nextId();
System.out.println(i + ": " + id + " " + "2406" + Long.toString(id).substring(2));
}
// long id = idWorker.nextId();
// System.out.println(id);
}
// ==============================Methods==========================================
/**
* 获取当前年月
* @return null
*/
public static int obtainingTime() {
LocalDate now = LocalDate.now();
int year = now.getYear();
String year_last_two_digits = String.valueOf(year).substring(2);
int month = now.getMonthValue();
String formatted_date = year_last_two_digits + String.format("%02d", month);
return Integer.parseInt(formatted_date);
}
/**
* 获得下一个ID (该方法是线程安全)
*
* @return SnowflakeId
*/
public synchronized int nextId() {
int timestamp = timeGen();
// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟修改过
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (timestamp > counter.get()) {
counter.set(timestamp);
isAdvance = false;
}
// 如果是同时间生成的,则进行分钟内序列
if (lastTimestamp == timestamp || isAdvance) {
if (!isAdvance) {
sequence = (sequence + 1) & sequenceMask;
}
// 分钟内自增列溢出
if (sequence == 0) {
// 预支下一分获得新的时间戳
isAdvance = true;
int laterTimestamp = counter.get();
if (laterSequence == 0) {
laterTimestamp = counter.incrementAndGet();
}
int nextId = ((laterTimestamp - twepoch) << timestampLeftShift) | laterSequence;
laterSequence = (laterSequence + 1) & sequenceMask;
return nextId;
}
} else { // 时间戳改变,分钟内序列置0
sequence = 0;
laterSequence = 0;
}
// 上次生成ID的时间截
lastTimestamp = timestamp;
// 移位并或运算拼成32位的ID
return ((timestamp - twepoch) << timestampLeftShift) | sequence;
}
/**
* 返回以分钟为单位的当前时
*
* @return 当前时间(分钟)
*/
protected int timeGen() {
// String timestamp = String.valueOf(System.currentTimeMillis() / 1000 / 60);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
return Integer.valueOf(timestamp);
}
}
@@ -0,0 +1 @@
com.cf.imes.framework.id.config.ChenfengIDAutoConfiguration