java UUID&雪花算法生成和使用場(chǎng)景詳解
1. 引言
簡(jiǎn)介:為什么需要唯一標(biāo)識(shí)符
在現(xiàn)代軟件架構(gòu)和數(shù)據(jù)管理中,能夠唯一標(biāo)識(shí)信息資源是至關(guān)重要的。唯一標(biāo)識(shí)符(Unique Identifier,簡(jiǎn)稱(chēng)UID)允許系統(tǒng)在全局范圍內(nèi)區(qū)分每一個(gè)獨(dú)立的元素,無(wú)論是用戶(hù)、訂單、消息還是任何數(shù)據(jù)記錄。這種標(biāo)識(shí)的唯一性保證了數(shù)據(jù)的一致性和完整性,避免了數(shù)據(jù)處理過(guò)程中的混淆和錯(cuò)誤。
在分布式系統(tǒng)中,例如互聯(lián)網(wǎng)服務(wù)、云基礎(chǔ)設(shè)施和大規(guī)模計(jì)算環(huán)境,需要跨多個(gè)節(jié)點(diǎn)、位置和時(shí)間區(qū)間追蹤和管理數(shù)據(jù)。在這些環(huán)境中,生成全局唯一的標(biāo)識(shí)符尤為重要,因?yàn)閭鹘y(tǒng)的基于單一數(shù)據(jù)庫(kù)的自增ID生成策略在這些環(huán)境中可能會(huì)導(dǎo)致ID沖突。
UUID和雪花算法的重要性
UUID(Universally Unique Identifier)和雪花算法(Snowflake Algorithm)是生成唯一標(biāo)識(shí)符的兩種流行方法,它們各有優(yōu)勢(shì),并適用于不同的應(yīng)用場(chǎng)景。
- UUID:UUID是一個(gè)16字節(jié)的數(shù)字,通常以32個(gè)十六進(jìn)制數(shù)字表示,并通過(guò)特定的版本算法生成。它的主要優(yōu)點(diǎn)是簡(jiǎn)單易用,能夠在本地生成,無(wú)需通過(guò)網(wǎng)絡(luò)交互,從而避免了網(wǎng)絡(luò)延遲和中斷的問(wèn)題。UUID的生成不依賴(lài)于中心數(shù)據(jù)庫(kù)或其他外部系統(tǒng),這使得它非常適合需要高度解耦的系統(tǒng)架構(gòu)。
- 雪花算法:雪花算法是由Twitter開(kāi)發(fā)的,用于生成64位的長(zhǎng)整型數(shù)字作為唯一ID。它結(jié)合了機(jī)器ID、數(shù)據(jù)中心ID和時(shí)間戳信息,可以在分布式系統(tǒng)中快速生成具有時(shí)間順序性的ID。雪花算法的主要優(yōu)點(diǎn)是生成ID時(shí)考慮了時(shí)間順序,這對(duì)于需要維護(hù)記錄順序的系統(tǒng)特別有用。
這兩種算法的存在和發(fā)展,顯著提升了現(xiàn)代系統(tǒng)中數(shù)據(jù)處理的效率和可靠性,使得開(kāi)發(fā)者可以更專(zhuān)注于業(yè)務(wù)邏輯的實(shí)現(xiàn),而不必?fù)?dān)心數(shù)據(jù)標(biāo)識(shí)和沖突的問(wèn)題。
2. UUID生成方案
UUID的定義和標(biāo)準(zhǔn)
UUID(Universally Unique Identifier)是一種軟件建構(gòu)的標(biāo)準(zhǔn),也被稱(chēng)為GUID(Globally Unique Identifier)。UUID的主要目的是讓分布式系統(tǒng)中的所有元素,都能有唯一的識(shí)別信息,而不需要通過(guò)中央控制端來(lái)做標(biāo)識(shí)符的指定。如此一來(lái),每個(gè)人都可以創(chuàng)建不與其它人沖突的UUID。在這個(gè)方面,UUID的目標(biāo)與主鍵的目標(biāo)是相符合的。
UUID是由一個(gè)十六位的數(shù)字組成,通過(guò)特定的算法進(jìn)行生成,形如:550e8400-e29b-41d4-a716-446655440000。
UUID的標(biāo)準(zhǔn)型式包含32個(gè)16進(jìn)制數(shù)字,以連字號(hào)分為五段,形式為8-4-4-4-12的32個(gè)字符。
Java中生成UUID的方法
在Java中,可以使用java.util.UUID類(lèi)來(lái)生成UUID。以下是一個(gè)簡(jiǎn)單的示例:
import java.util.UUID;
public class Main {
public static void main(String[] args) {
UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());
}
}在這個(gè)示例中,UUID.randomUUID()方法被用來(lái)生成一個(gè)隨機(jī)UUID。
UUID的版本差異
UUID標(biāo)準(zhǔn)定義了五種不同的生成方法,或者說(shuō)五個(gè)版本。每個(gè)版本的UUID都包含一個(gè)4位的版本號(hào),以便我們可以區(qū)分生成的UUID使用了哪種方法。
- 版本1:基于時(shí)間的UUID:這種UUID使用了發(fā)起UUID生成請(qǐng)求的計(jì)算機(jī)的MAC地址和當(dāng)前的時(shí)間戳(精確到100納秒)來(lái)生成UUID。由于MAC地址是全球唯一的,所以生成的UUID也是全球唯一的。不過(guò),這種方法會(huì)因暴露MAC地址而帶來(lái)一定的安全風(fēng)險(xiǎn)。
- 版本4:隨機(jī)生成的UUID:這種UUID完全由隨機(jī)數(shù)生成,沒(méi)有時(shí)間和硬件的限制,也沒(méi)有安全性問(wèn)題。Java的
UUID.randomUUID()方法就是生成這種UUID。不過(guò),由于是隨機(jī)生成,所以理論上存在生成的UUID重復(fù)的可能,但實(shí)際上這種可能性非常非常小。
3. UUID的使用場(chǎng)景
UUIDs 提供了一種高度可靠的方式來(lái)生成唯一標(biāo)識(shí)符,這在許多不同的技術(shù)場(chǎng)景中都非常有用。
以下是一些典型的使用UUID的場(chǎng)景:
網(wǎng)絡(luò)系統(tǒng)中的唯一性需求
在網(wǎng)絡(luò)環(huán)境中,尤其是在互聯(lián)網(wǎng)應(yīng)用和服務(wù)中,需要追蹤和區(qū)分成千上萬(wàn)的請(qǐng)求和事務(wù)。UUID可以為每一個(gè)請(qǐng)求或事務(wù)生成一個(gè)唯一的標(biāo)識(shí)符,確保即使在高并發(fā)的情況下也不會(huì)產(chǎn)生沖突。例如,Web API可以為每個(gè)請(qǐng)求生成一個(gè)UUID,用于日志記錄、監(jiān)控和追蹤問(wèn)題,從而提高服務(wù)的可靠性和可追溯性。
數(shù)據(jù)庫(kù)主鍵
在數(shù)據(jù)庫(kù)設(shè)計(jì)中,使用UUID作為主鍵是一種常見(jiàn)的做法,尤其是在分布式數(shù)據(jù)庫(kù)系統(tǒng)中。與傳統(tǒng)的遞增整數(shù)主鍵相比,UUID可以避免跨數(shù)據(jù)庫(kù)的同步和沖突問(wèn)題,使得數(shù)據(jù)庫(kù)的擴(kuò)展更為靈活和可靠。此外,使用UUID作為主鍵可以減少數(shù)據(jù)庫(kù)遷移和合并時(shí)的復(fù)雜性,因?yàn)樗WC了即使在不同的數(shù)據(jù)庫(kù)間也不會(huì)出現(xiàn)主鍵的重復(fù)。
分布式系統(tǒng)中的身份標(biāo)識(shí)
在分布式系統(tǒng)中,尤其是那些涉及多個(gè)服務(wù)和組件的大型系統(tǒng)中,需要一種機(jī)制來(lái)唯一標(biāo)識(shí)每個(gè)組件或節(jié)點(diǎn)。UUID為這些系統(tǒng)提供了一種簡(jiǎn)單而有效的方式來(lái)生成這種唯一標(biāo)識(shí)符。例如,微服務(wù)架構(gòu)中的每個(gè)服務(wù)實(shí)例可以使用UUID來(lái)標(biāo)識(shí),這有助于在服務(wù)發(fā)現(xiàn)和負(fù)載均衡等過(guò)程中確保正確的資源分配和管理。
總的來(lái)說(shuō),UUID的使用可以極大地增強(qiáng)系統(tǒng)的健壯性、可擴(kuò)展性和安全性。其能夠在不依賴(lài)中心化控制的情況下生成全局唯一的標(biāo)識(shí)符,使得它成為現(xiàn)代軟件和系統(tǒng)設(shè)計(jì)中不可或缺的一個(gè)工具。
4. 雪花算法(Snowflake Algorithm)
雪花算法的介紹
雪花算法(Snowflake Algorithm)是由Twitter開(kāi)發(fā)的一種用于生成唯一ID的算法,特別適用于分布式系統(tǒng)中。
這種算法可以在不需要中央數(shù)據(jù)庫(kù)的情況下生成全局唯一的ID,非常適合需要處理大量數(shù)據(jù)和高并發(fā)請(qǐng)求的應(yīng)用。
結(jié)構(gòu)解析
雪花算法生成的ID是一個(gè)64位的整數(shù),這64位中包含了以下幾個(gè)部分:
- 時(shí)間戳 - 占用41位,精確到毫秒級(jí),可以使用約69年。
- 數(shù)據(jù)中心ID - 占用5位,可以有最多32個(gè)數(shù)據(jù)中心。
- 機(jī)器ID - 占用5位,每個(gè)數(shù)據(jù)中心可以有最多32臺(tái)機(jī)器。
- 序列號(hào) - 占用12位,每個(gè)節(jié)點(diǎn)每毫秒可以生成最多4096個(gè)ID。
這種結(jié)構(gòu)確保了即使在同一時(shí)間同一數(shù)據(jù)中心的同一機(jī)器上發(fā)生多個(gè)請(qǐng)求,生成的ID也是唯一的。
Java實(shí)現(xiàn)雪花算法
要在Java中實(shí)現(xiàn)雪花算法,我們需要定義一個(gè)類(lèi)來(lái)處理ID生成的邏輯。
下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)示例:
import cn.hutool.core.net.NetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Random;
/**
* Twitter_Snowflake<br>
* SnowFlake的結(jié)構(gòu)如下(每部分用-分開(kāi)):<br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 -
* 000000000000 <br>
* 1位標(biāo)識(shí),由于long基本類(lèi)型在Java中是帶符號(hào)的,最高位是符號(hào)位,正數(shù)是0,負(fù)數(shù)是1,所以id一般是正數(shù),最高位是0<br>
* 41位時(shí)間截(毫秒級(jí)),注意,41位時(shí)間截不是存儲(chǔ)當(dāng)前時(shí)間的時(shí)間截,而是存儲(chǔ)時(shí)間截的差值(當(dāng)前時(shí)間截 - 開(kāi)始時(shí)間截)
* 得到的值),這里的的開(kāi)始時(shí)間截,一般是我們的id生成器開(kāi)始使用的時(shí)間,由我們程序來(lái)指定的(如下下面程序IdWorker類(lèi)的startTime屬性)。41位的時(shí)間截,可以使用69年,年T
* = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* 10位的數(shù)據(jù)機(jī)器位,可以部署在1024個(gè)節(jié)點(diǎn),包括5位datacenterId和5位workerId<br>
* 12位序列,毫秒內(nèi)的計(jì)數(shù),12位的計(jì)數(shù)順序號(hào)支持每個(gè)節(jié)點(diǎn)每毫秒(同一機(jī)器,同一時(shí)間截)產(chǎn)生4096個(gè)ID序號(hào)<br>
* 加起來(lái)剛好64位,為一個(gè)Long型。<br>
* SnowFlake的優(yōu)點(diǎn)是,整體上按照時(shí)間自增排序,并且整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生ID碰撞(由數(shù)據(jù)中心ID和機(jī)器ID作區(qū)分),并且效率較高,經(jīng)測(cè)試,SnowFlake每秒能夠產(chǎn)生26萬(wàn)ID左右。
*/
@Component
public class SnowflakeIdWorker {
/**
* 開(kāi)始時(shí)間截 (2019-06-21)
*/
private final long twepoch = 1561104939733L;
/**
* 機(jī)器id所占的位數(shù)
*/
private final long workerIdBits = 5L;
/**
* 數(shù)據(jù)標(biāo)識(shí)id所占的位數(shù)
*/
private final long datacenterIdBits = 5L;
/**
* 支持的最大機(jī)器id,結(jié)果是31 (這個(gè)移位算法可以很快的計(jì)算出幾位二進(jìn)制數(shù)所能表示的最大十進(jìn)制數(shù))
*/
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/**
* 支持的最大數(shù)據(jù)標(biāo)識(shí)id,結(jié)果是31
*/
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/**
* 序列在id中占的位數(shù)
*/
private final long sequenceBits = 12L;
/**
* 機(jī)器ID向左移12位
*/
private final long workerIdShift = sequenceBits;
/**
* 數(shù)據(jù)標(biāo)識(shí)id向左移17位(12+5)
*/
private final long datacenterIdShift = sequenceBits + workerIdBits;
/**
* 時(shí)間截向左移22位(5+5+12)
*/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/**
* 生成序列的掩碼,這里為4095 (0b111111111111=0xfff=4095)
*/
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
/**
* 工作機(jī)器ID(0~31)
*/
private long workerId = getWorkId();
/**
* 數(shù)據(jù)中心ID(0~31)
*/
private long datacenterId = getDataId();
/**
* 毫秒內(nèi)序列(0~4095)
*/
private long sequence = 0L;
/**
* 上次生成ID的時(shí)間截
*/
private long lastTimestamp = -1L;
/**
* 機(jī)器隨機(jī)獲取數(shù)據(jù)中中心id的參數(shù) 32
*/
private final long DATA_RANDOM = maxDatacenterId + 1;
/**
* 隨機(jī)獲取的機(jī)器id的參數(shù)
*/
private final long WORK_RANDOM = maxWorkerId + 1;
private static final Logger logger = LoggerFactory.getLogger(SnowflakeIdWorker.class);
@PostConstruct
public void init() {
logger.debug("snowflake-work-id:{}", getWorkId());
logger.debug("snowflake-data-id:{}", getDataId());
}
public SnowflakeIdWorker() {
// this(0, 0);
}
/**
* 構(gòu)造函數(shù)
*
* @param workerId 工作ID (0~31)
* @param datacenterId 數(shù)據(jù)中心ID (0~31)
*/
public SnowflakeIdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(
String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(
String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* 獲得下一個(gè)ID (該方法是線(xiàn)程安全的)
*
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();
// 如果當(dāng)前時(shí)間小于上一次ID生成的時(shí)間戳,說(shuō)明系統(tǒng)時(shí)鐘回退過(guò)這個(gè)時(shí)候應(yīng)當(dāng)拋出異常
if (timestamp < lastTimestamp) {
if (lastTimestamp - timestamp < 2000) {
// 容忍2秒內(nèi)的回?fù)?,避免NTP校時(shí)造成的異常
timestamp = lastTimestamp;
} else {
// 如果服務(wù)器時(shí)間有問(wèn)題(時(shí)鐘后退) 報(bào)錯(cuò)。
throw new RuntimeException(String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
}
// 如果是同一時(shí)間生成的,則進(jìn)行毫秒內(nèi)序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
// 毫秒內(nèi)序列溢出
if (sequence == 0) {
// 阻塞到下一個(gè)毫秒,獲得新的時(shí)間戳
timestamp = tilNextMillis(lastTimestamp);
}
}
// 時(shí)間戳改變,毫秒內(nèi)序列重置
else {
sequence = 0L;
}
// 上次生成ID的時(shí)間截
lastTimestamp = timestamp;
// 移位并通過(guò)或運(yùn)算拼到一起組成64位的ID
return ((timestamp - twepoch) << timestampLeftShift) //
| (datacenterId << datacenterIdShift) //
| (workerId << workerIdShift) //
| sequence;
}
/**
* 阻塞到下一個(gè)毫秒,直到獲得新的時(shí)間戳
*
* @param lastTimestamp 上次生成ID的時(shí)間截
* @return 當(dāng)前時(shí)間戳
*/
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
/**
* 返回以毫秒為單位的當(dāng)前時(shí)間
*
* @return 當(dāng)前時(shí)間(毫秒)
*/
protected long timeGen() {
return System.currentTimeMillis();
}
/**
* 根據(jù)host name 取余,發(fā)生異常就獲取0到31之間的隨機(jī)數(shù)
*
* @return
*/
public long getWorkId() {
try {
String ip = NetUtil.getLocalhost().getHostAddress();
logger.info("服務(wù)器IP:{}", ip);
return getHostId(ip, maxWorkerId);
} catch (Exception e) {
return new Random().nextInt((int) WORK_RANDOM);
}
}
/**
* 根據(jù)host name 取余,發(fā)生異常就獲取0到31之間的隨機(jī)數(shù)
*
* @return
*/
public long getDataId() {
try {
String ip = NetUtil.getLocalhost().getHostAddress();
logger.info("服務(wù)器IP:{}", ip);
return getHostId(ip, maxDatacenterId);
} catch (Exception e) {
return new Random().nextInt((int) DATA_RANDOM);
}
}
/**
* 根據(jù)host name 取余
*
* @return
*/
private long getHostId(String s, long max) {
byte[] bytes = s.getBytes();
long sums = 0;
for (byte b : bytes) {
sums += b;
}
return sums % (max + 1);
}
/**
* 測(cè)試
*/
public static void main(String[] args) {
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
System.out.println(idWorker.nextId());
}
}
在這個(gè)實(shí)現(xiàn)中,我們創(chuàng)建了一個(gè)SnowflakeIdWorker類(lèi),該類(lèi)可以在構(gòu)造時(shí)接受數(shù)據(jù)中心ID和機(jī)器ID,并提供了一個(gè)nextId()方法來(lái)生成新的ID。
這個(gè)方法確保生成的ID是按時(shí)間順序遞增的,并且在多線(xiàn)程環(huán)境中是安全的。
5. 雪花算法的使用場(chǎng)景
雪花算法由于其獨(dú)特的結(jié)構(gòu)和高效的性能特點(diǎn),非常適用于特定的技術(shù)場(chǎng)景。以下是雪花算法的一些主要使用場(chǎng)景:
大規(guī)模分布式系統(tǒng)中的ID生成
在大規(guī)模分布式系統(tǒng)中,需要確保在多個(gè)節(jié)點(diǎn)和服務(wù)之間生成的ID是唯一的,同時(shí)又不能依賴(lài)于中央數(shù)據(jù)庫(kù)或服務(wù)來(lái)維護(hù)ID的唯一性。雪花算法通過(guò)結(jié)合時(shí)間戳、數(shù)據(jù)中心ID、機(jī)器ID和序列號(hào)生成唯一的ID,從而無(wú)需進(jìn)行網(wǎng)絡(luò)交互即可在各個(gè)節(jié)點(diǎn)獨(dú)立生成ID。這種方法非常適合用于電商平臺(tái)、社交網(wǎng)絡(luò)、在線(xiàn)游戲等業(yè)務(wù),其中需要處理大量數(shù)據(jù)并且對(duì)ID生成的性能要求極高。
性能考量和優(yōu)勢(shì)
雪花算法的一個(gè)顯著優(yōu)勢(shì)是其生成ID的速度非???,可以在毫秒級(jí)別生成數(shù)百萬(wàn)個(gè)ID,這對(duì)于高并發(fā)的應(yīng)用場(chǎng)景尤為重要。此外,由于ID是基于時(shí)間戳生成的,這自然地保證了生成的ID的順序性(在同一毫秒內(nèi)通過(guò)序列號(hào)保證順序),這對(duì)于需要保持事件順序的應(yīng)用場(chǎng)景(如日志記錄、消息隊(duì)列等)非常有用。
雪花算法的另一個(gè)優(yōu)勢(shì)是其擴(kuò)展性好。通過(guò)調(diào)整數(shù)據(jù)中心ID和機(jī)器ID的位數(shù),可以靈活適應(yīng)不同規(guī)模的系統(tǒng)擴(kuò)展需要。這使得雪花算法不僅適用于大型系統(tǒng),也適用于中小型系統(tǒng),甚至是動(dòng)態(tài)擴(kuò)展的云環(huán)境。
總之,雪花算法是解決分布式系統(tǒng)中ID生成問(wèn)題的一個(gè)高效、可靠的解決方案,它通過(guò)獨(dú)特的設(shè)計(jì)滿(mǎn)足了高性能、高可用性和可擴(kuò)展性的需求。
6. UUID與雪花算法的比較
UUID和雪花算法都是在特定場(chǎng)景下生成唯一ID的有效工具。然而,它們?cè)谛阅?、?yīng)用場(chǎng)景和選擇依據(jù)方面有著顯著的差異。
性能比較
- UUID:UUID的生成過(guò)程非常簡(jiǎn)單,只需要調(diào)用函數(shù)即可立即生成。因此,UUID的生成性能很高。然而,UUID的長(zhǎng)度較長(zhǎng)(32位十六進(jìn)制),在存儲(chǔ)和傳輸上會(huì)占用更多的資源。此外,如果在數(shù)據(jù)庫(kù)中使用UUID作為主鍵,可能會(huì)導(dǎo)致索引性能下降。
- 雪花算法:雪花算法生成的ID長(zhǎng)度較短(64位整數(shù)),在存儲(chǔ)和傳輸上更加高效。而且,由于雪花算法生成的ID是有序的,因此在數(shù)據(jù)庫(kù)中使用雪花算法生成的ID作為主鍵可以提高索引性能。然而,雪花算法的生成過(guò)程比UUID更復(fù)雜,需要維護(hù)時(shí)間戳、數(shù)據(jù)中心ID、機(jī)器ID和序列號(hào)等信息。
應(yīng)用場(chǎng)景差異
- UUID:UUID最大的優(yōu)點(diǎn)是可以在任何地方生成,不需要考慮系統(tǒng)的分布式架構(gòu)。因此,UUID非常適合在分布式系統(tǒng)中作為全局唯一標(biāo)識(shí)符使用。
- 雪花算法:雪花算法最大的優(yōu)點(diǎn)是生成的ID是有序的,非常適合在需要保證順序的場(chǎng)景中使用。例如,如果需要按照ID的生成順序進(jìn)行數(shù)據(jù)處理,那么雪花算法會(huì)是一個(gè)更好的選擇。
選擇依據(jù)
在選擇UUID和雪花算法時(shí),需要考慮以下幾個(gè)因素:
- 系統(tǒng)架構(gòu):如果系統(tǒng)是分布式的,并且需要在多個(gè)節(jié)點(diǎn)上生成唯一ID,那么雪花算法可能是一個(gè)更好的選擇。如果系統(tǒng)架構(gòu)較簡(jiǎn)單,或者不需要在多個(gè)節(jié)點(diǎn)上生成唯一ID,那么UUID可能是一個(gè)更好的選擇。
- 性能需求:如果系統(tǒng)對(duì)存儲(chǔ)和傳輸效率有較高的要求,那么應(yīng)該選擇生成長(zhǎng)度較短的雪花算法ID。如果系統(tǒng)對(duì)生成ID的速度有較高的要求,那么應(yīng)該選擇生成速度較快的UUID。
- 順序需求:如果系統(tǒng)需要按照ID的生成順序進(jìn)行操作,那么應(yīng)該選擇雪花算法。如果系統(tǒng)不需要保證ID的順序,那么可以選擇UUID。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于spring?data?jpa?模糊查詢(xún)like的坑點(diǎn)
這篇文章主要介紹了關(guān)于spring?data?jpa?模糊查詢(xún)like的坑點(diǎn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java利用序列化實(shí)現(xiàn)對(duì)象深度clone的方法
這篇文章主要介紹了Java利用序列化實(shí)現(xiàn)對(duì)象深度clone的方法,實(shí)例分析了java序列化及對(duì)象克隆的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
Java實(shí)現(xiàn)字符串解析為日期時(shí)間的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)字符串解析為日期時(shí)間的方法,結(jié)合具體實(shí)例形式分析了java日期時(shí)間字符串的解析操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04
Java必會(huì)的Synchronized底層原理剖析
synchronized作為Java程序員最常用同步工具,很多人卻對(duì)它的用法和實(shí)現(xiàn)原理一知半解,以至于還有不少人認(rèn)為synchronized是重量級(jí)鎖,性能較差,盡量少用。但不可否認(rèn)的是synchronized依然是并發(fā)首選工具,本文就來(lái)詳細(xì)講講2022-10-10
Flink實(shí)現(xiàn)往Kafka中多個(gè)topic發(fā)送消息
文章介紹了使用Flink 1.13.2 和 Kafka 2.6.2 從Kafka讀取數(shù)據(jù),并根據(jù)邏輯將數(shù)據(jù)分配到不同的topic,提到了需要重寫(xiě)FlinkKafka的Key序列化器,并加入自定義邏輯以發(fā)送消息到指定的topic,文中還包括了配置Kafka信息和如何連接FlinkKafka的步驟2025-10-10
SpringBoot利用jpa連接MySQL數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了SpringBoot利用jpa連接MySQL數(shù)據(jù)庫(kù)的方法,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10
詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù)
本篇文章主要介紹了詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Spring 事務(wù)神器TransactionTemplate用法及避坑指南
TransactionTemplate是Spring框架提供的編程式事務(wù)管理模板類(lèi),它結(jié)合了聲明式事務(wù)和編程式事務(wù)的優(yōu)點(diǎn),解決了復(fù)雜場(chǎng)景下的事務(wù)控制問(wèn)題,本文給大家介紹Spring 事務(wù)神器TransactionTemplate 全解析,感興趣的朋友跟隨小編一起看看吧2025-12-12

