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)文章
java中實(shí)現(xiàn)分頁(yè)的幾種常見(jiàn)方式總結(jié)
在項(xiàng)目中經(jīng)常會(huì)查詢大量數(shù)據(jù),這就要用到分頁(yè)展示,下面這篇文章主要給大家介紹了關(guān)于java中實(shí)現(xiàn)分頁(yè)的幾種常見(jiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
Springboot遷移到Micronaut實(shí)現(xiàn)過(guò)程詳解
這篇文章主要為大家?介紹了Springboot遷移到Micronaut實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
SpringBoot整合RedisTemplate實(shí)現(xiàn)緩存信息監(jiān)控的步驟
這篇文章主要介紹了SpringBoot整合RedisTemplate實(shí)現(xiàn)緩存信息監(jiān)控,一步一步的實(shí)現(xiàn)?Springboot?整合?Redis?來(lái)存儲(chǔ)數(shù)據(jù),讀取數(shù)據(jù),需要的朋友可以參考下2022-01-01
Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法
這篇文章主要介紹了Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Idea創(chuàng)建多模塊maven聚合項(xiàng)目的實(shí)現(xiàn)
這篇文章主要介紹了Idea創(chuàng)建多模塊maven聚合項(xiàng)目的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12

