背景
由于使用推特的雪花算法,导致Long类型数据返回前端精度丢失,因此顺手自己定义了一个15位自增长ID生成方法和11位不重复Key
代码
废话不多说,上代码。
public class SnowUtils {
private static final int minNum = 1024;
private static final int strMinNum = 100;
private static final AtomicInteger bigAtomic = new AtomicInteger(minNum);
private static final AtomicInteger strAtomic = new AtomicInteger(strMinNum);
private static Integer machineCode=null;
private static Long recordSecond=null;
private static Long recordTimeMillis=null;
private static void checkAndInit() {
if(machineCode==null){
synchronized (SnowUtils.class){
if(machineCode==null){
initData();
}
}
}
}
private static void initData(){
recordSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
recordTimeMillis = System.currentTimeMillis();
try {
String machineIp = InetAddress.getLocalHost().getHostAddress();
String codeStr = machineIp.substring(machineIp.length() - 1);
machineCode = new BigInteger(codeStr).intValue();
} catch (UnknownHostException e) {
machineCode = 3;
}
}
/**
* 获取15位长度的自增长Key
* 每秒可生成8970个不重复编号
* @return long
*/
public static Long bigKey() {
checkAndInit();
if (LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) != recordSecond) {
recordSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
bigAtomic.set(minNum);
}
String differ = String.valueOf(recordSecond);
int atomic = bigAtomic.getAndIncrement();
if (atomic == 9999) {
String text = "bigKey超出阈值:" + LocalDateTime.now().toString();
throw new RuntimeException(text);
}
return new BigInteger(differ + atomic + machineCode).longValue();
}
/**
* 获取11位不重复Key
* 每毫秒可生成890个不重复的11位编号
* @return String
*/
public static String strKey() {
checkAndInit();
long localTimeMillis=System.currentTimeMillis();
if(localTimeMillis!=recordTimeMillis){
recordTimeMillis = localTimeMillis;
strAtomic.set(strMinNum);
}
String differ = String.valueOf(recordTimeMillis);
int atomic = strAtomic.getAndIncrement();
long bigNum=new BigInteger(differ+atomic+machineCode).longValue();
if (atomic == 999) {
String text = "strKey超出阈值:" + LocalDateTime.now().toString();
throw new RuntimeException(text);
}
return Long.toUnsignedString(bigNum,32).toUpperCase();
}
}
讲点废话,由于阈值限制,生成ID有一定条件。由于我所用的服务器节点内网IP最后一位不一样,因此我用最后一位做机器码,如超过很多节点或者多节点下内网ip最后一位存在重复,请看注释酌情使用,或者自行修改。