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分布式鎖工具類(lèi) */ @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緩存========開(kāi)始",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-12Springboot遷移到Micronaut實(shí)現(xiàn)過(guò)程詳解
這篇文章主要為大家?介紹了Springboot遷移到Micronaut實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05SpringBoot整合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-01Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法
這篇文章主要介紹了Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Idea創(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