mybatis-plus雪花算法自動(dòng)生成機(jī)器id原理及源碼
1、雪花算法原理
雪花算法使用一個(gè) 64 bit 的 long 型的數(shù)字作為全局唯一 id。這 64 個(gè) bit 中,其中 1 個(gè) bit 是不用的,然后用其中的 41 bit 作為毫秒數(shù),用 10 bit 作為工作機(jī)器 id,12 bit 作為序列號(hào)。
- 1bit,不用,因?yàn)槎M(jìn)制中最高位是符號(hào)位,1表示負(fù)數(shù),0表示正數(shù)。生成的id一般都是用整數(shù),所以最高位固定為0。
- 41bit-時(shí)間戳,用來記錄時(shí)間戳,毫秒級(jí)。
- 10bit-工作機(jī)器id,用來記錄工作機(jī)器id。
- 12bit-序列號(hào),序列號(hào),用來記錄同毫秒內(nèi)產(chǎn)生的不同id。即可以用0、1、2、3、…4094這4095個(gè)數(shù)字,來表示同一機(jī)器同一時(shí)間截(毫秒)內(nèi)產(chǎn)生的4095個(gè)ID序號(hào)。
SnowFlake可以保證:
所有生成的id按時(shí)間趨勢(shì)遞增
整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生重復(fù)id(因?yàn)橛衐atacenterId和workerId來做區(qū)分)
如上大概了解了雪花算法的原理,而且也知道機(jī)器號(hào)對(duì)于雪花算法的重要性。如果機(jī)器號(hào)一樣,可能會(huì)出現(xiàn)id重復(fù)的情況。
mybatis-plus自3.3.0開始,默認(rèn)使用雪花算法+UUID(不含中劃線),但是它并沒有強(qiáng)制讓開發(fā)者配置機(jī)器號(hào)。這一點(diǎn)很是疑惑,這樣可能會(huì)讓不了解雪花算法的人埋下了一個(gè)坑。
但是這么強(qiáng)大的一個(gè)框架難道真的沒有做優(yōu)化嗎?帶著問題,查看了下mybatis-plus雪花算法源碼com.baomidou.mybatisplus.core.toolkit.Sequence
。最終發(fā)現(xiàn)在沒有設(shè)置機(jī)器號(hào)的情況下,會(huì)通過當(dāng)前物理網(wǎng)卡地址和jvm的進(jìn)程ID自動(dòng)生成。這真的是一個(gè)較好的解決方案。一般在一個(gè)集群中,MAC+JVM進(jìn)程PID
一樣的幾率非常小。
2、自動(dòng)生成唯一機(jī)器號(hào)源碼
核心代碼。有兩個(gè)構(gòu)造方法,一個(gè)無參構(gòu)造,一個(gè)有參構(gòu)造。
public Sequence() { //通過當(dāng)前物理網(wǎng)卡地址獲取datacenterId this.datacenterId = getDatacenterId(maxDatacenterId); //物理網(wǎng)卡地址+jvm進(jìn)程pi獲取workerId this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); } /** * 有參構(gòu)造器 * * @param workerId 工作機(jī)器 ID * @param datacenterId 序列號(hào) */ public Sequence(long workerId, long datacenterId) { Assert.isFalse(workerId > maxWorkerId || workerId < 0, String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); Assert.isFalse(datacenterId > maxDatacenterId || datacenterId < 0, String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); this.workerId = workerId; this.datacenterId = datacenterId; }
- 無參構(gòu)造 開發(fā)者沒有設(shè)置機(jī)器號(hào)時(shí)
- 有參構(gòu)造 開發(fā)者自行設(shè)置機(jī)器號(hào)
protected static long getDatacenterId(long maxDatacenterId) { long id = 0L; try { //獲取本機(jī)(或者服務(wù)器ip地址) //DESKTOP-123SDAD/192.168.1.87 InetAddress ip = InetAddress.getLocalHost(); NetworkInterface network = NetworkInterface.getByInetAddress(ip); //一般不是null會(huì)進(jìn)入else if (network == null) { id = 1L; } else { //獲取物理網(wǎng)卡地址 byte[] mac = network.getHardwareAddress(); if (null != mac) { id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6; id = id % (maxDatacenterId + 1); } } } catch (Exception e) { logger.warn(" getDatacenterId: " + e.getMessage()); } return id; }
/** * 獲取 maxWorkerId */ protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { StringBuilder mpid = new StringBuilder(); mpid.append(datacenterId); //獲取jvm進(jìn)程信息 String name = ManagementFactory.getRuntimeMXBean().getName(); if (StringUtils.isNotBlank(name)) { /* * 獲取進(jìn)程PID */ mpid.append(name.split(StringPool.AT)[0]); } /* * MAC + PID 的 hashcode 獲取16個(gè)低位 */ return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); }
以上就是mybatis-plus雪花算法自動(dòng)生成機(jī)器id原理的詳細(xì)內(nèi)容,更多關(guān)于mybatis plus雪花id的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
String split方法實(shí)現(xiàn)過程圖解
這篇文章主要介紹了String split方法實(shí)現(xiàn)過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用
這篇文章主要為大家詳細(xì)介紹了OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08idea上提交項(xiàng)目到gitee 最后出現(xiàn) Push rejected的問題處理方法
這篇文章主要介紹了idea上面提交項(xiàng)目到gitee 最后出現(xiàn) Push rejected的問題處理方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09JSP 開發(fā)之hibernate的hql查詢多對(duì)多查詢
這篇文章主要介紹了JSP 開發(fā)之hibernate的hql查詢多對(duì)多查詢的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09java使用dom4j解析xml配置文件實(shí)現(xiàn)抽象工廠反射示例
本文主要介紹了java使用dom4j讀取配置文件實(shí)現(xiàn)抽象工廠和反射的示例,在Java中也可以同Donet一樣,將差異配置在配置文件里面。另外,我們采用下面的方式實(shí)現(xiàn),將會(huì)更加便捷2014-01-01解決feign微服務(wù)間的文件上傳報(bào)錯(cuò)問題
這篇文章主要介紹了解決feign微服務(wù)間的文件上傳報(bào)錯(cuò)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06

Java實(shí)現(xiàn)級(jí)聯(lián)下拉結(jié)構(gòu)的示例代碼