mybatis-plus雪花算法自動(dòng)生成機(jī)器id原理及源碼
雪花算法使用一個(gè) 64 bit 的 long 型的數(shù)字作為全局唯一 id。這 64 個(gè) bit 中,其中 1 個(gè) bit 是不用的,然后用其中的 41 bit 作為毫秒數(shù),用 10 bit 作為工作機(jī)器 id,12 bit 作為序列號。
SnowFlake可以保證:
所有生成的id按時(shí)間趨勢遞增整個(gè)分布式系統(tǒng)內(nèi)不會產(chǎn)生重復(fù)id(因?yàn)橛衐atacenterId和workerId來做區(qū)分)如上大概了解了雪花算法的原理,而且也知道機(jī)器號對于雪花算法的重要性。如果機(jī)器號一樣,可能會出現(xiàn)id重復(fù)的情況。
mybatis-plus自3.3.0開始,默認(rèn)使用雪花算法+UUID(不含中劃線),但是它并沒有強(qiáng)制讓開發(fā)者配置機(jī)器號。這一點(diǎn)很是疑惑,這樣可能會讓不了解雪花算法的人埋下了一個(gè)坑。但是這么強(qiáng)大的一個(gè)框架難道真的沒有做優(yōu)化嗎?帶著問題,查看了下mybatis-plus雪花算法源碼com.baomidou.mybatisplus.core.toolkit.Sequence。最終發(fā)現(xiàn)在沒有設(shè)置機(jī)器號的情況下,會通過當(dāng)前物理網(wǎng)卡地址和jvm的進(jìn)程ID自動(dòng)生成。這真的是一個(gè)較好的解決方案。一般在一個(gè)集群中,MAC+JVM進(jìn)程PID一樣的幾率非常小。
2、自動(dòng)生成唯一機(jī)器號源碼核心代碼。有兩個(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 序列號 */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ī)器號時(shí) 有參構(gòu)造 開發(fā)者自行設(shè)置機(jī)器號
protected static long getDatacenterId(long maxDatacenterId) { long id = 0L; try {//獲取本機(jī)(或者服務(wù)器ip地址)//DESKTOP-123SDAD/192.168.1.87InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);//一般不是null會進(jìn)入elseif (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的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. mysql數(shù)據(jù)庫中最常用的時(shí)間轉(zhuǎn)換函數(shù)的用法2. 四種數(shù)據(jù)庫隨機(jī)獲取10條數(shù)據(jù)的方法3. HP-UX rx2600 B.11.22 U ia64 安裝oracle9i 9.2 for ia64 手記4. Mybatis中處理特殊SQL處理邏輯解析5. SQL Server中搜索特定的對象6. 加密你的Access數(shù)據(jù)庫asp打開方法7. MySQL創(chuàng)始人發(fā)郵件尋求中國幫助8. Mysql入門系列:安排預(yù)防性的維護(hù)MYSQL數(shù)據(jù)庫服務(wù)器9. Windwos下MySQL 64位壓縮包的安裝方法學(xué)習(xí)記錄10. DB2專家王云談商業(yè)智能BI
