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

基于注冊中心指定唯一機器號
從注冊中心讀取服務(wù),增加多一個機器號服務(wù)來統(tǒng)一分配

基于第一種實現(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;
}
/**
* 帶超時的鎖
* @param lockKey
* @param timeout 超時時間 單位:秒
*/
public RLock lock(String lockKey, long timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
/**
* 帶超時的鎖
* @param lockKey
* @param unit 時間單位
* @param timeout 超時時間
*/
public RLock lock(String lockKey, TimeUnit unit ,long timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
/**
* 嘗試獲取鎖
* @param lockKey
* @param waitTime 最多等待時間
* @param unit TimeUnit時間單位
* @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 最多等待時間
* @param leaseTime 上鎖后自動釋放鎖時間
* @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 時間單位
* @param waitTime 最多等待時間
* @param leaseTime 上鎖后自動釋放鎖時間
* @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();
}
/**
* 若沒用鎖情況下,就不調(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();
}
}
啟動配置代碼如下
@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";
/**
* 最大機器號Key
*/
private static final String CACHE_WORKERID_MAXID= "CACHE_WORKERID_MAXID";
/**
* 已分配的機器號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);
//若已緩存在緩存中,直接跳過不設(shè)置
if (existWorkerId) {
log.info("{} 已配置分布式Id Work...",macAddress);
return ;
}
try {
//分布式鎖等待120秒,執(zhí)行時長最大120秒
boolean locked = redissonUtil.tryLock(CACHE_ID_GENERATOR, 120, 120);
if (!locked) {
throw new RuntimeException(macAddress+"設(shè)置分布式Id機器號失敗");
}
ValueOperations <String,Integer> stringOperation = redisTemplate.opsForValue();
boolean initWorkerId = stringOperation.setIfAbsent(CACHE_WORKERID_MAXID, 1);
if( !initWorkerId ) {
//若已存在key,對最大的機器號自增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自增的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot 分布式Id自增內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis useGeneratedKeys參數(shù)用法及問題小結(jié)
這篇文章主要介紹了Mybatis useGeneratedKeys參數(shù)用法及遇到的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
java實現(xiàn)jdbc批量插入數(shù)據(jù)
這篇文章主要為大家詳細介紹了java實現(xiàn)jdbc批量插入數(shù)據(jù),三種JDBC批量插入編程方法進行比較,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-05-05
springboot中自定義異常以及定制異常界面實現(xiàn)過程解析
這篇文章主要介紹了springboot中自定義異常以及定制異常界面實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-09-09
SpringBoot集成Graphql Query實戰(zhàn)示例
這篇文章主要為大家介紹了SpringBoot集成Graphql Query實戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09

