SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的實現(xiàn)
場景
yitter-idgenerator 是基于雪花算法進行改造的分布式ID自增算法,集成時需要為每個服務(wù)設(shè)置唯一的機器號,才能保證生成的Id不會重復(fù)
實現(xiàn)方案
基于服務(wù)啟動時指定唯一機器號
在程序服務(wù)啟動時通過分布式鎖 Redisson(基于Redis實現(xiàn)),對每臺機器通過IP 對應(yīng)一個 唯一的機器號(自增)映射,并保存在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)文章
Springboot遷移到Micronaut實現(xiàn)過程詳解
這篇文章主要為大家?介紹了Springboot遷移到Micronaut實現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05SpringBoot整合RedisTemplate實現(xiàn)緩存信息監(jiān)控的步驟
這篇文章主要介紹了SpringBoot整合RedisTemplate實現(xiàn)緩存信息監(jiān)控,一步一步的實現(xiàn)?Springboot?整合?Redis?來存儲數(shù)據(jù),讀取數(shù)據(jù),需要的朋友可以參考下2022-01-01Java中關(guān)于優(yōu)先隊列PriorityQueue的使用及相關(guān)方法
這篇文章主要介紹了Java中關(guān)于優(yōu)先隊列PriorityQueue的使用及相關(guān)方法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08Idea創(chuàng)建多模塊maven聚合項目的實現(xiàn)
這篇文章主要介紹了Idea創(chuàng)建多模塊maven聚合項目的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12