淺談UUID生成的原理及優(yōu)缺點(diǎn)
一、UUID 的生成原理
UUID 的英文全稱為 Universally Unique Identifier,即通用唯一識(shí)別碼,它是由一組 16 個(gè)字節(jié)(128 位)組成的標(biāo)識(shí)符,可以用于唯一地標(biāo)識(shí)信息。UUID 的生成方式有多種,其中最為常用的是基于算法的 UUID 生成方式和基于硬件的 UUID 生成方式。下面我們分別來(lái)介紹這兩種生成方式的原理。
1. 基于算法的 UUID 生成方式
基于算法的 UUID 生成方式是指使用計(jì)算機(jī)程序根據(jù)一定的算法生成 UUID。這種方式的優(yōu)點(diǎn)是可以在任何環(huán)境中生成 UUID,并且不需要依賴于任何硬件設(shè)備,缺點(diǎn)是生成的 UUID 不夠隨機(jī),容易被猜測(cè)到,因此不適合用于安全領(lǐng)域。
目前最常用的基于算法的 UUID 生成方式是基于時(shí)間戳的 UUID 生成方式。該方式基于當(dāng)前時(shí)間戳和機(jī)器的 MAC 地址生成 UUID,它的算法流程如下:
- 獲取當(dāng)前時(shí)間戳和機(jī)器的 MAC 地址;
- 將當(dāng)前時(shí)間戳轉(zhuǎn)換為 UTC 時(shí)間,并計(jì)算出自 1582 年 10 月 15 日午夜(即格林威治標(biāo)準(zhǔn)時(shí)間 0 點(diǎn))以來(lái)的納秒數(shù),將其存儲(chǔ)在 UUID 的時(shí)間戳字段中;
- 將機(jī)器的 MAC 地址哈希得到其中的 6 個(gè)字節(jié)作為 UUID 的節(jié)點(diǎn)字段;
- 隨機(jī)生成兩個(gè)字節(jié)作為 UUID 的時(shí)鐘序列字段;
- 將時(shí)間戳、節(jié)點(diǎn)、時(shí)鐘序列等信息組合起來(lái),生成 UUID。
基于時(shí)間戳的 UUID 生成方式可以保證在同一時(shí)刻生成的 UUID 唯一,并且可以提供一定的順序性,因此非常適合用于分布式系統(tǒng)中對(duì)數(shù)據(jù)進(jìn)行排序操作。但是,如果多臺(tái)計(jì)算機(jī)的時(shí)鐘存在差異,就有可能導(dǎo)致生成重復(fù)的 UUID,因此需要采取一些措施來(lái)防止時(shí)鐘不同步的問(wèn)題。此外,這種方式也容易受到時(shí)鐘回?fù)芄舻挠绊?,因此需要特殊處理?/p>
2. 基于硬件的 UUID 生成方式
基于硬件的 UUID 生成方式是指使用計(jì)算機(jī)硬件設(shè)備生成 UUID,該方式的優(yōu)點(diǎn)是生成的 UUID 隨機(jī)性高,不容易被猜測(cè)到,缺點(diǎn)是只能在具備對(duì)應(yīng)硬件設(shè)備的機(jī)器上生成 UUID,不夠靈活。
基于硬件的 UUID 生成方式常用的有 MAC 地址 UUID 和 CPU ID UUID。
MAC 地址 UUID 是指使用計(jì)算機(jī)網(wǎng)卡設(shè)備的 MAC 地址作為 UUID 的節(jié)點(diǎn)字段,這種方式可以保證每個(gè)機(jī)器生成的 UUID 都是唯一的,并且不依賴于時(shí)鐘同步。但是,它也存在一些缺點(diǎn),比如計(jì)算機(jī)的網(wǎng)卡可能會(huì)被更換,導(dǎo)致 UUID 發(fā)生變化。
CPU ID UUID 是指使用計(jì)算機(jī) CPU 的序列號(hào)作為 UUID 的節(jié)點(diǎn)字段,這種方式與 MAC 地址 UUID 很相似,但是比 MAC 地址 UUID 更加安全,因?yàn)?CPU 序列號(hào)不會(huì)輕易發(fā)生變化。不過(guò),由于 CPU 可以被替換,因此這種方式也存在一定的風(fēng)險(xiǎn)。
二、UUID 的特性
UUID 具有以下幾個(gè)特性:
1. 唯一性
UUID 是全局唯一的標(biāo)識(shí)符,可以為分布式系統(tǒng)提供唯一的標(biāo)識(shí)。
2. 隨機(jī)性
UUID 的生成過(guò)程使用了隨機(jī)性或偽隨機(jī)性的元素,生成的 UUID 具有高度隨機(jī)性,不容易被猜測(cè)到。
3. 不可推測(cè)性
UUID 是通過(guò)一定的算法生成的,生成的 UUID 不能從中推測(cè)出任何信息。
4. 可復(fù)制性
UUID 可以在不同的時(shí)間和地點(diǎn)被重復(fù)生成,但是在實(shí)踐中,由于隨機(jī)數(shù)的使用,重復(fù)的概率非常低。
5. 可比較性
UUID 是一個(gè) 128 位的二進(jìn)制數(shù)字,可以進(jìn)行比較操作,比較操作具有一定的順序性。
三、UUID 的實(shí)用場(chǎng)景
由于 UUID 具有唯一性、隨機(jī)性等特性,因此在很多應(yīng)用場(chǎng)景中都得到了廣泛的應(yīng)用,下面列舉幾個(gè)典型的應(yīng)用場(chǎng)景。
1. 數(shù)據(jù)庫(kù)主鍵
在數(shù)據(jù)庫(kù)中,每個(gè)記錄都需要一個(gè)唯一的主鍵來(lái)區(qū)分,通常可以使用自增長(zhǎng) ID 作為主鍵。但是在分布式系統(tǒng)中,多個(gè)節(jié)點(diǎn)之間可能會(huì)產(chǎn)生 ID 沖突的問(wèn)題。因此,可以使用 UUID 作為主鍵,確保每個(gè)記錄的唯一性。
2. 分布式系統(tǒng)
在分布式系統(tǒng)中,需要將數(shù)據(jù)分布存儲(chǔ)在多個(gè)節(jié)點(diǎn)上,并對(duì)數(shù)據(jù)進(jìn)行全局唯一標(biāo)識(shí)。這時(shí)可以使用 UUID 來(lái)為數(shù)據(jù)生成唯一的 ID,以便在整個(gè)系統(tǒng)中進(jìn)行區(qū)分。
3. 日志跟蹤
在分布式系統(tǒng)中,系統(tǒng)運(yùn)行日志是監(jiān)控和排查問(wèn)題的重要依據(jù)。如果將日志中的每條記錄都打上唯一的標(biāo)識(shí)符,方便后期分析和跟蹤。這時(shí)可以使用 UUID 來(lái)為日志記錄生成唯一的 ID。
4. 安全領(lǐng)域
在安全領(lǐng)域中,需要為用戶會(huì)話、密鑰和證書等生成唯一的標(biāo)識(shí)符,以保證安全性。這時(shí)可以使用 UUID 來(lái)生成唯一的標(biāo)識(shí)符,確保不同對(duì)象之間的區(qū)分。
四、UUID 的優(yōu)缺點(diǎn)
UUID 具有以下幾個(gè)優(yōu)點(diǎn):
1. 全局唯一
UUID 可以為分布式系統(tǒng)提供全局唯一的標(biāo)識(shí)符,避免了 ID 沖突的問(wèn)題。
2. 可比較性
UUID 是一個(gè)數(shù)字,可以進(jìn)行比較操作,具有一定的順序性。
3. 無(wú)需中央?yún)f(xié)調(diào)機(jī)制
UUID 的生成不需要中央?yún)f(xié)調(diào)機(jī)制,因此可以在任何時(shí)間和地點(diǎn)生成 UUID。
4. 安全性高
UUID 的生成使用了隨機(jī)性或偽隨機(jī)性的元素,生成的 UUID 具有高度隨機(jī)性,不容易被猜測(cè)到。因此可以在安全領(lǐng)域中使用。
但是,UUID 也具有以下幾個(gè)缺點(diǎn):
1. 占用空間大
UUID 是一個(gè) 128 位的二進(jìn)制數(shù)字,占用的空間比較大,不適宜作為數(shù)據(jù)庫(kù)主鍵使用。
2. 不易讀懂
由于 UUID 是一個(gè)數(shù)字,因此不容易被人類讀懂,不便于調(diào)試和排查問(wèn)題。
3. 不適合順序訪問(wèn)
UUID 的生成具有隨機(jī)性,因此不適合對(duì)數(shù)據(jù)進(jìn)行順序訪問(wèn)操作。
4. 算法復(fù)雜
UUID 的生成算法比較復(fù)雜,在一定程度上影響了性能。
五、代碼示例
import java.util.Random;
public class GenerateUUID {
private static final long START_EPOCH = -12219292800000L;
// 定義版本號(hào)和變體標(biāo)識(shí)的位數(shù)
private static final int VERSION_BITS = 4;
private static final int VARIANT_BITS = 2;
// 生成的 UUID 二進(jìn)制形式共 128 位
private static final int TOTAL_BITS = 128;
public static void main(String[] args) {
Random random = new Random();
long timestamp = System.currentTimeMillis() + START_EPOCH;
long leastSigBits = random.nextLong();
long mostSigBits = random.nextLong();
// 根據(jù) RFC 4122 規(guī)范設(shè)置 UUID 版本號(hào)和變體標(biāo)識(shí)
mostSigBits &= ~(0xfL << 12); // 清空版本號(hào)
mostSigBits |= (4L << 12); // 設(shè)置版本號(hào)
leastSigBits &= ~(0x3L << 62); // 清空變體標(biāo)識(shí)
leastSigBits |= (0x2L << 62); // 設(shè)置變體標(biāo)識(shí)
// 將時(shí)間戳寫入 UUID 中段
long timeLow = timestamp & 0xffffffffL;
long timeMid = (timestamp >> 32) & 0xffffL;
long timeHiAndVersion = (timestamp >> 48) & 0x0fffL;
mostSigBits &= ~(0xffffffffffffL << 64); // 清空時(shí)間戳
mostSigBits |= (timeLow << 32);
mostSigBits |= (timeMid << 16);
mostSigBits |= timeHiAndVersion;
// 構(gòu)造 UUID 對(duì)象
java.util.UUID uuid = new java.util.UUID(mostSigBits, leastSigBits);
System.out.println(uuid.toString());
}
}上述代碼中,我們首先使用 Random 類生成兩個(gè) 64 位的偽隨機(jī)數(shù),分別作為 UUID 的高 64 位和低 64 位。然后,我們根據(jù) RFC 4122 規(guī)范對(duì) UUID 進(jìn)行版本號(hào)標(biāo)記和變體標(biāo)識(shí),并將當(dāng)前時(shí)間戳的毫秒部分寫入 UUID 的中段,以保證 UUID 具有一定的順序性。最后,我們將生成的 UUID 的高 64 位和低 64 位傳入 java.util.UUID 類的構(gòu)造方法中,以創(chuàng)建一個(gè) UUID 對(duì)象。
需要注意的是,由于我們?cè)谏?UUID 的過(guò)程中使用了偽隨機(jī)數(shù),因此生成的 UUID 并不是真正的隨機(jī)數(shù),它們僅具有偽隨機(jī)性。同時(shí),由于我們沒(méi)有保證時(shí)間戳的唯一性,因此同一時(shí)刻生成的 UUID 可能存在重復(fù)的風(fēng)險(xiǎn)。在實(shí)際應(yīng)用中,我們通常建議使用 java.util.UUID.randomUUID() 方法生成 UUID。
六、總結(jié)
UUID 是一套用于生成全局唯一標(biāo)識(shí)符的標(biāo)準(zhǔn),具有唯一性、隨機(jī)性等特性,可以在分布式系統(tǒng)中使用。UUID 的生成方式有多種,其中最為常用的是基于算法的 UUID 生成方式和基于硬件的 UUID 生成方式。UUID 在數(shù)據(jù)庫(kù)主鍵、分布式系統(tǒng)、日志跟蹤和安全領(lǐng)域等方面有廣泛的應(yīng)用。雖然 UUID 具有很多優(yōu)點(diǎn),但也存在一些缺點(diǎn),比如占用空間大、不易讀懂、不適合順序訪問(wèn)和算法復(fù)雜等。綜合來(lái)看,UUID 是一種非常有用的標(biāo)識(shí)符生成方式,在實(shí)際開發(fā)中應(yīng)根據(jù)具體情況選擇合適的 UUID 生成方式。
以上就是淺談UUID生成的原理及優(yōu)缺點(diǎn)的詳細(xì)內(nèi)容,更多關(guān)于UUID 生成原理及優(yōu)缺點(diǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中的equals()和toString()方法實(shí)例詳解
這篇文章主要介紹了java中的equals()和toString()方法實(shí)例詳解的相關(guān)資料,這里舉例說(shuō)明,并附實(shí)例代碼,和實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11
plsql實(shí)現(xiàn)DES對(duì)稱加密 Java解密
這篇文章主要介紹了plsql實(shí)現(xiàn)DES對(duì)稱加密 Java解密的方法,幫助大家更好的理解和學(xué)習(xí)使用Oracle與Java,感興趣的朋友可以了解下2021-02-02
Android中幾種圖片特效的處理的實(shí)現(xiàn)方法
這篇文章主要介紹了 Android中幾種圖片特效的處理的實(shí)現(xiàn)方法的相關(guān)資料,這里有放大縮小圖片,獲得圓角圖片,獲得帶倒影圖片的幾種方法,需要的朋友可以參考下2017-08-08

