SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的實(shí)現(xiàn)
場(chǎng)景
yitter-idgenerator 是基于雪花算法進(jìn)行改造的分布式ID自增算法,集成時(shí)需要為每個(gè)服務(wù)設(shè)置唯一的機(jī)器號(hào),才能保證生成的Id不會(huì)重復(fù)
實(shí)現(xiàn)方案
基于服務(wù)啟動(dòng)時(shí)指定唯一機(jī)器號(hào)
在程序服務(wù)啟動(dòng)時(shí)通過(guò)分布式鎖 Redisson(基于Redis實(shí)現(xiàn)),對(duì)每臺(tái)機(jī)器通過(guò)IP 對(duì)應(yīng)一個(gè) 唯一的機(jī)器號(hào)(自增)映射,并保存在Redis中。緩存一次后,下次啟動(dòng)直接讀取緩存即可

基于注冊(cè)中心指定唯一機(jī)器號(hào)
從注冊(cè)中心讀取服務(wù),增加多一個(gè)機(jī)器號(hào)服務(wù)來(lái)統(tǒng)一分配

基于第一種實(shí)現(xiàn)方案
Maven依賴
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.10.6</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.7.19</version>
</dependency>
<dependency>
<groupId>com.github.yitter</groupId>
<artifactId>yitter-idgenerator</artifactId>
<version>1.0.6</version>
</dependency>
關(guān)鍵部分代碼
/**
* Redisson分布式鎖工具類
*/
@Component
public class RedissonUtil {
@Autowired
private RedissonClient redissonClient;
/**
* 加鎖
* @param lockKey
* @return
*/
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
/**
* 帶超時(shí)的鎖
* @param lockKey
* @param timeout 超時(shí)時(shí)間 單位:秒
*/
public RLock lock(String lockKey, long timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
/**
* 帶超時(shí)的鎖
* @param lockKey
* @param unit 時(shí)間單位
* @param timeout 超時(shí)時(shí)間
*/
public RLock lock(String lockKey, TimeUnit unit ,long timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
/**
* 嘗試獲取鎖
* @param lockKey
* @param waitTime 最多等待時(shí)間
* @param unit TimeUnit時(shí)間單位
* @return
*/
public boolean tryLock(String lockKey,long waitTime, TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, unit);
} catch (InterruptedException e) {
return false;
}
}
/**
* 嘗試獲取鎖
* @param lockKey
* @param waitTime 最多等待時(shí)間
* @param leaseTime 上鎖后自動(dòng)釋放鎖時(shí)間
* @return
*/
public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
/**
* 嘗試獲取鎖
* @param lockKey
* @param unit 時(shí)間單位
* @param waitTime 最多等待時(shí)間
* @param leaseTime 上鎖后自動(dòng)釋放鎖時(shí)間
* @return
*/
public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
/**
* 釋放鎖
* @param lockKey
*/
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
/**
* 若沒(méi)用鎖情況下,就不調(diào)用釋放鎖的代碼,若有鎖情況下才調(diào)用釋放鎖
* @param lockKey
*/
public void unlockIgnore(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
if ( !lock.isLocked() ) {
return ;
}
lock.unlock();
}
/**
* 釋放鎖
* @param lock
*/
public void unlock(RLock lock) {
lock.unlock();
}
}
啟動(dòng)配置代碼如下
@Slf4j
@Component
@Order(0)
public class SystemInitConfig implements CommandLineRunner {
@Autowired
private RedissonUtil redissonUtil;
@Autowired
private RedisTemplate redisTemplate;
/**
* 分布式鎖Key
*/
private static final String CACHE_ID_GENERATOR = "LOCK_ID_GENERATOR";
/**
* 最大機(jī)器號(hào)Key
*/
private static final String CACHE_WORKERID_MAXID= "CACHE_WORKERID_MAXID";
/**
* 已分配的機(jī)器號(hào)Key
*/
private static final String CACHE_ID_IP = "CACHE_ID_IP";
@Override
public void run(String... args) throws Exception {
//獲取mac地址
String macAddress = NetUtil.getLocalhost().getHostAddress();
log.info("{} 配置分布式Id Work緩存========開始",macAddress);
boolean existWorkerId = redisTemplate.opsForHash().hasKey(CACHE_ID_IP, macAddress);
//若已緩存在緩存中,直接跳過(guò)不設(shè)置
if (existWorkerId) {
log.info("{} 已配置分布式Id Work...",macAddress);
return ;
}
try {
//分布式鎖等待120秒,執(zhí)行時(shí)長(zhǎng)最大120秒
boolean locked = redissonUtil.tryLock(CACHE_ID_GENERATOR, 120, 120);
if (!locked) {
throw new RuntimeException(macAddress+"設(shè)置分布式Id機(jī)器號(hào)失敗");
}
ValueOperations <String,Integer> stringOperation = redisTemplate.opsForValue();
boolean initWorkerId = stringOperation.setIfAbsent(CACHE_WORKERID_MAXID, 1);
if( !initWorkerId ) {
//若已存在key,對(duì)最大的機(jī)器號(hào)自增1
stringOperation.increment(CACHE_WORKERID_MAXID);
}
Integer workerId = stringOperation.get(CACHE_WORKERID_MAXID);
IdGeneratorOptions options = new IdGeneratorOptions( workerId.shortValue());
YitIdHelper.setIdGenerator(options);
//設(shè)置mac地址 - workerid 到hash結(jié)構(gòu)
redisTemplate.opsForHash().put(CACHE_ID_IP,macAddress,workerId);
log.info("已配置分布式Id Work,{} - {}",macAddress,workerId);
} finally {
redissonUtil.unlock(CACHE_ID_GENERATOR);
log.info("{} 配置分布式Id Work緩存========結(jié)束",macAddress);
}
}
}直接在代碼使用即可
YitIdHelper.nextId()
到此這篇關(guān)于SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot 分布式Id自增內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis useGeneratedKeys參數(shù)用法及問(wèn)題小結(jié)
這篇文章主要介紹了Mybatis useGeneratedKeys參數(shù)用法及遇到的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
Java中的JSONObject使用及錯(cuò)誤處理詳解
這篇文章主要給大家介紹了關(guān)于Java中的JSONObject使用及錯(cuò)誤處理的相關(guān)資料,文中講解了Java中的JSONObject創(chuàng)建、基本操作、高級(jí)特性和錯(cuò)誤處理,通過(guò)示例代碼和方法說(shuō)明,使讀者能夠理解和掌握J(rèn)SONObject的使用技巧,需要的朋友可以參考下2024-12-12
全網(wǎng)最新Log4j?漏洞修復(fù)和臨時(shí)補(bǔ)救方法
Apache?Log4j?遠(yuǎn)程代碼執(zhí)行漏洞,如何快速修復(fù)log4j2漏洞,本文給大家介紹下Log4j?漏洞修復(fù)和臨時(shí)補(bǔ)救方法,感興趣的朋友跟隨小編一起看看吧2021-12-12
java實(shí)現(xiàn)jdbc批量插入數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)jdbc批量插入數(shù)據(jù),三種JDBC批量插入編程方法進(jìn)行比較,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
JDBC實(shí)現(xiàn)Mysql自動(dòng)重連機(jī)制的方法詳解
最近在工作中發(fā)現(xiàn)了一個(gè)問(wèn)題,通過(guò)查找相關(guān)的資料終于解決了,下面這篇文章主要給大家介紹了關(guān)于JDBC實(shí)現(xiàn)Mysql自動(dòng)重連機(jī)制的相關(guān)資料,文中給出多種解決的方法,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-07-07
springboot中自定義異常以及定制異常界面實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了springboot中自定義異常以及定制異常界面實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
SpringBoot集成Graphql Query實(shí)戰(zhàn)示例
這篇文章主要為大家介紹了SpringBoot集成Graphql Query實(shí)戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Spring框架基于xml實(shí)現(xiàn)自動(dòng)裝配流程詳解
自動(dòng)裝配就是指?Spring?容器在不使用?<constructor-arg>?和<property>?標(biāo)簽的情況下,可以自動(dòng)裝配(autowire)相互協(xié)作的?Bean?之間的關(guān)聯(lián)關(guān)系,將一個(gè)?Bean?注入其他?Bean?的?Property?中2022-11-11

