UUID生成幫助類、UUID工具類
阿新 • • 發佈:2019-02-14
資料庫主鍵id使用自動增長的壞處
1. 程式後臺新增測試
2. 舊資料匯入
3. 資料庫遷移
4. 快取 (如,兩個庫中id都為2時,快取的時候會覆蓋)以下為程式碼塊
結論:一般在實際生產環境中,一般用程式來確保id的唯一性。
以下為UUID的生成工具類:
package com.cnksi.utils;
import java.net.InetAddress;
/**
* 在分散式系統中,需要生成全域性UID的場合還是比較多的,twitter的snowflake解決了這種需求,
* 實現也還是很簡單的,除去配置資訊,核心程式碼就是毫秒級時間41位+機器ID 10位+毫秒內序列12位。
* 該專案地址為:https://github.com/twitter/snowflake是用Scala實現的。
* python版詳見開源專案https://github.com/erans/pysnowflake。
*
* @author xiqiao
* @Date 2017-12-19
*/
public class IdWorker {
//根據具體機器環境提供
private final long workerId;
//濾波器,使時間變小,生成的總位數變小,一旦確定不能變動
private final static long twepoch = 1361753741828L;
private long sequence = 0L;
private final static long workerIdBits = 10L;
private final static long maxWorkerId = -1 L ^ -1L << workerIdBits;
private final static long sequenceBits = 12L;
private final static long workerIdShift = sequenceBits;
private final static long timestampLeftShift = sequenceBits + workerIdBits;
private final static long sequenceMask = -1L ^ -1L << sequenceBits;
private long lastTimestamp = -1L;
//根據主機id獲取機器碼
private static IdWorker worker = new IdWorker();
/**
* 建立 IdWorker物件.
*
* @param workerId
* @Deprecated 請呼叫靜態方法getId()
*/
@Deprecated
public IdWorker(final long workerId) {
if (workerId > IdWorker.maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0",
IdWorker.maxWorkerId));
}
this.workerId = workerId;
}
public IdWorker() {
this.workerId = getAddress() % (IdWorker.maxWorkerId + 1);
}
public static long getId() {
return worker.nextId();
}
public synchronized long nextId() {
long timestamp = this.timeGen();
if (this.lastTimestamp == timestamp) {
this.sequence = (this.sequence + 1) & IdWorker.sequenceMask;
if (this.sequence == 0) {
//System.out.println("###########" + sequenceMask);//等待下一毫秒
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0;
}
if (timestamp < this.lastTimestamp) {
try {
throw new Exception(String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds", this.lastTimestamp
- timestamp));
} catch (Exception e) {
e.printStackTrace();
}
}
this.lastTimestamp = timestamp;
long nextId = ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << IdWorker.workerIdShift)
| (this.sequence);
// System.out.println("timestamp:" + timestamp + ",timestampLeftShift:"
// + timestampLeftShift + ",nextId:" + nextId + ",workerId:"
// + workerId + ",sequence:" + sequence);
return nextId;
}
private long tilNextMillis(final long lastTimestamp1) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp1) {
timestamp = this.timeGen();
}
return timestamp;
}
private static long getAddress() {
try {
String currentIpAddress = InetAddress.getLocalHost().getHostAddress();
String[] str = currentIpAddress.split("\\.");
StringBuilder hardware = new StringBuilder();
for (int i = 0; i < str.length; i++) {
hardware.append(str[i]);
}
return Long.parseLong(hardware.toString());
} catch (Exception e) {
e.printStackTrace();
}
return 2L;
}
private long timeGen() {
return System.currentTimeMillis();
}
public static void main(final String[] args) {
//IdWorker worker2 = new IdWorker(0);
//System.out.println(worker2.nextId());
//long ll = getAddress() % 16;
//System.out.println(ll);
// long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
System.out.println(getId());
}
// long end = System.currentTimeMillis();
// System.out.println((10 / (end - start)) + "個/ms");
// System.out.println(getId());
}
}