『壹』 怎麼用java產生唯一ID號
uuid
時間戳
隨機數+用戶id
-- 來自億千年信息科技有限公司的回答
『貳』 設計分布式唯一id生成
db不幫你自動生成的時候。比如:
a. 不依賴第三方唯一id生成服務,利用業務db的特性來生成id
比如業務的「訂單表」做了分庫分表後,想要全局唯一的訂單id,就讓分庫後每個庫按不同的起點和步長做遞增。這樣訂單系統就不用依賴發號服務了,自己解決問題
缺點是db擴縮容時候太復雜。
另一個思路是每個分表有一個前綴,在分表內自增
這樣其實可以避免擴縮容麻煩的問題,比如sharding策略是預先分1000個表,每個表的id有個通用前綴,表內id自增
b. 非中心化方案,機器標識(比如mac地址)作為命名空間,通過命名空間保證唯一
比如:
c. 中心化方案,實現一個唯一id生成服務,基於寫操作線性一致的存儲
比如用mysql自增特性做個發號器服務
比如隨機,往線性化存儲里cas寫,寫成功就算申請到id
如果吞吐量過大、對存儲有壓力,可以在存儲上面加個cache,預先從存儲申請多個id(號段)。這個cache就不需要用redis等,起個java程序做進程內cache即可
再比如nosql之類的在時間戳欄位上加索引很難,分頁查最新數據的時候,只想按id查
https://www.w3cschool.cn/architectroad/architectroad-distributed-id.html
Q: 類snowflake演算法基於時間戳+命名空間,時鍾回撥怎麼辦?
(發生閏秒、NTP時鍾同步等情況都可能導致時鍾回撥)
a. 外接存儲記錄最新時間戳,檢測回撥。比如美團外接了個zk
b. 最終往線性化存儲里寫的時候檢測重復,重復就報錯重來
c. 多加幾個命名空間,讓概率小到忽略不計
Q: snowflake里的workerId咋生成
a. 基於線性化存儲
比如美團方案,外接一個zk,每個機器順序取workerId(依賴機器);
但是這樣太重了,可以把workerId換成業務id,思想是通過命名空間減少沖突概率,而不是絕對唯一
b. 沒必要一定用機器id,本質上只是加個命名空間,加幾個業務欄位作為命名空間就行
我們之前用到的方案是id裡面除了時間戳還加上一些uid、業務類型、隨機數之類的欄位,作為命名空間,減少沖突概率
Q: 分布式關系庫能否自動生成全局單調遞增的唯一id?
看Tidb的只是單機遞增,沒法保證全局單調遞增:
https://docs.pingcap.com/zh/tidb/stable/auto-increment
「趨勢遞增」和「全局單調遞增」這兩種保證處於兩個極端,能否給出介於兩者之間的保證?
架構 細聊分布式ID生成方法
Leaf——美團點評分布式ID生成系統
https://www.liaoxuefeng.com/article/1280526512029729
『叄』 什麼是UUID,Java中怎麼產生UUID
UUID: 通用唯一識別碼 (Universally Unique Identifier),是根據時間,機器碼,網路地址生成的全球唯一數。
引入 java.util.UUID,直接調用以下即可得到一個32為的隨機數,即UUID.
UUID uuid = UUID.randomUUID();
『肆』 java輸入唯一編號,這么干可以嗎
可以把信息存放到HashMap里,key為EmpNO,value為Emp。直接可以判斷是否包含EmpNO特定值
『伍』 java生成唯一標識符有什麼用
有時我們不依賴於資料庫中自動遞增的欄位產生唯一ID,比如多表同一欄位需要統一一個唯一ID,這時就需要用程序來生成一個唯一的全局ID,然後在資料庫事務中同時插入到多章表中實現同步.
在java中有個類工具很好的實現產生唯一ID(UUID),但是由數字和字母及中劃線組成的,故資料庫欄位應該設置為char 並相應的建立索引.
UUID是128位整數(16位元組)的全局唯一標識符(Universally Unique Identifier).
指在一台機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的.通常平台會提供生成UUID的API.UUID按照開放軟體基金會(OSF)制定的標准計算,用到了乙太網卡地址,納秒級時間,晶元ID碼和許多可能的數字.由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關,如果你在生成一個 UUID之後,過幾秒又生成一個UUID,則第一個部分不同,其餘相同),時鍾序列,全局唯一的IEEE機器識別號(如果有網卡,從網卡獲得,沒有網卡以其他方式獲得),UUID的唯一缺陷在於生成的結果串會比較長.關於UUID這個標准使用最普遍的是微軟的GUID(Globals Unique Identifiers).
在ColdFusion中可以用CreateUUID()函數很簡單的生成UUID,其格式為:xxxxxxxx- xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每個 x 是 0-9 或 a-f 范圍內的一個十六進制的數字.而標準的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
,可以從cflib 下載CreateGUID() UDF進行轉換.
使用UUID的好處在分布式的軟體系統中(比如:DCE/RPC, COM+,CORBA)就能體現出來,它能保證每個節點所生成的標識都不會重復,並且隨著WEB服務等整合技術的發展,UUID的優勢將更加明顯.
關於UUID的更多信息可以多google 一下.
Java生成UUID
UUID(Universally Unique Identifier)全局唯一標識符,是指在一台機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的.按照開放軟體基金會(OSF)制定的標准計算,用到了乙太網卡地址,納秒級時間,晶元ID碼和許多可能的數字.由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關,如果你在生成一個UUID之後,過幾秒又生成一個UUID,則第一個部分不同,其餘相同),時鍾序列,全局唯一的IEEE機器識別號(如果有網卡,從網卡獲得,沒有網卡以其他方式獲得),UUID的唯一缺陷在於生成的結果串會比較長.
在Java中生成UUID主要有以下幾種方式:
JDK1.5
如果使用的JDK1.5的話,那麼生成UUID變成了一件簡單的事,以為JDK實現了UUID:
java.util.UUID, 直接調用即可.
UUID uuid = UUID.randomUUID();
String s = UUID.randomUUID().toString();//用來生成資料庫的主鍵id非常不錯..
Java代碼
package com.taobao.tddl.client.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author huangshang
*
*/
public class UniqId {
private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
private static Map<Character, Integer> rDigits = new HashMap<Character, Integer>(
16);
static {
for (int i = 0; i < digits.length; ++i) {
rDigits.put(digits[i], i);
}
}
private static UniqId me = new UniqId();
private String hostAddr;
private Random random = new SecureRandom();
private MessageDigest mHasher;
private UniqTimer timer = new UniqTimer();
private ReentrantLock opLock = new ReentrantLock();
private UniqId() {
try {
InetAddress addr = InetAddress.getLocalHost();
hostAddr = addr.getHostAddress();
} catch (IOException e) {
hostAddr = String.valueOf(System.currentTimeMillis());
}
if (hostAddr == null || hostAddr.length() == 0
|| "127.0.0.1".equals(hostAddr)) {
hostAddr = String.valueOf(System.currentTimeMillis());
}
try {
mHasher = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nex) {
mHasher = null;
}
}
/**
* 獲取UniqID實例
*
* @return UniqId
*/
public static UniqId getInstance() {
return me;
}
/**
* 獲得不會重復的毫秒數
*
* @return
*/
public long getUniqTime() {
return timer.getCurrentTime();
}
/**
* 獲得UniqId
*
* @return uniqTime-randomNum-hostAddr-threadId
*/
public String getUniqID() {
StringBuffer sb = new StringBuffer();
long t = timer.getCurrentTime();
sb.append(t);
sb.append("-");
sb.append(random.nextInt(8999) + 1000);
sb.append("-");
sb.append(hostAddr);
sb.append("-");
sb.append(Thread.currentThread().hashCode());
return sb.toString();
}
/**
* 獲取MD5之後的uniqId string
*
* @return uniqId md5 string
*/
public String getUniqIDHashString() {
return hashString(getUniqID());
}
/**
* 獲取MD5之後的uniqId
*
* @return byte[16]
*/
public byte[] getUniqIDHash() {
return hash(getUniqID());
}
/**
* 對字元串進行md5
*
* @param str
* @return md5 byte[16]
*/
public byte[] hash(String str) {
opLock.lock();
try {
byte[] bt = mHasher.digest(str.getBytes("UTF-8"));
if (null == bt || bt.length != 16) {
throw new IllegalArgumentException("md5 need");
}
return bt;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("unsupported utf-8 encoding", e);
} finally {
opLock.unlock();
}
}
/**
* 對二進制數據進行md5
*
* @param str
* @return md5 byte[16]
*/
public byte[] hash(byte[] data) {
opLock.lock();
try {
byte[] bt = mHasher.digest(data);
if (null == bt || bt.length != 16) {
throw new IllegalArgumentException("md5 need");
}
return bt;
} finally {
opLock.unlock();
}
}
/**
* 對字元串進行md5 string
*
* @param str
* @return md5 string
*/
public String hashString(String str) {
byte[] bt = hash(str);
return bytes2string(bt);
}
/**
* 對位元組流進行md5 string
*
* @param str
* @return md5 string
*/
public String hashBytes(byte[] str) {
byte[] bt = hash(str);
return bytes2string(bt);
}
/**
* 將一個位元組數組轉化為可見的字元串
*
* @param bt
* @return
*/
public String bytes2string(byte[] bt) {
int l = bt.length;
char[] out = new char[l << 1];
for (int i = 0, j = 0; i < l; i++) {
out[j++] = digits[(0xF0 & bt[i]) >>> 4];
out[j++] = digits[0x0F & bt[i]];
}
return new String(out);
}
/**
* 將字元串轉換為bytes
*
* @param str
* @return byte[]
*/
public byte[] string2bytes(String str) {
if (null == str) {
throw new NullPointerException("參數不能為空");
}
if (str.length() != 32) {
throw new IllegalArgumentException("字元串長度必須是32");
}
byte[] data = new byte[16];
char[] chs = str.toCharArray();
for (int i = 0; i < 16; ++i) {
int h = rDigits.get(chs[i * 2]).intValue();
int l = rDigits.get(chs[i * 2 + 1]).intValue();
data[i] = (byte) ((h & 0x0F) << 4 | (l & 0x0F));
}
return data;
}
/**
* 實現不重復的時間
*
* @author dogun
*/
private static class UniqTimer {
private AtomicLong lastTime = new AtomicLong(System.currentTimeMillis());
public long getCurrentTime() {
return this.lastTime.incrementAndGet();
}
}
}
『陸』 Java 如何實現生成有序且唯一的id
毫秒:System.currentTimeMillis(),這個毫秒其實就是自1970年1月1日0時起的毫秒數。
納秒:System.nanoTime(),這個毫秒其實就是自1970年1月1日0時起的納秒數。
產生的數據都是唯一的,且有序的,都可以做成序列~
『柒』 java生成唯一ID
讓資料庫自動生成把
mysql
把Id設置為auto_increment
oracle
生成一個序列.sequence
java可以通過UUID這個類生成一個唯一的Id但不是你想的那樣
『捌』 java有關自動生成ID的方法
自動生成ID,比如是sqlserver資料庫可以直接用主鍵,設置自增就行
如果是oracle資料庫,就使用序列,把序列插入到要用的那個ID里米就行拉
『玖』 什麼是UUID,Java中怎麼產生UUID
UUID含義是通用唯一識別碼 (Universally Unique Identifier),這 是一個軟體建構的標准,也是被開源軟體基金會 (Open Software Foundation, OSF) 的組織應用在分布式計算環境(Distributed Computing Environment, DCE) 領域的一部分。
UUID 的目的,是讓分布式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人沖突的 UUID。在這樣的情況下,就不需考慮資料庫建立時的名稱重復問題。目前最廣泛應用的 UUID,即是微軟的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的應用,則有 Linux ext2/ext3 檔案系統、LUKS 加密分割區、GNOME、KDE、Mac OS X 等等。
UUID是指在一台機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。通常平台會提供生成的API。
//如果使用的JDK1.5的話,那麼生成UUID變成了一件簡單的事,以為JDK實現了UUID:
java.util.UUID,直接調用即可.
UUIDuuid=UUID.randomUUID();
Strings=UUID.randomUUID().toString();//用來生成資料庫的主鍵id非常不錯。。
//UUID是由一個十六位的數字組成,表現出來的形式例如
//550E8400-E29B-11D4-A716-446655440000