生活随笔
收集整理的這篇文章主要介紹了
雪花算法之唯一ID生成器理解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
雪花算法基本情況
- 雪花算法是一個分布式的唯一ID生成器。
- 它應該具有高并發,以及高性能優點。
- 基于時間戳,ID具有有序性,同時分布式下機器間時間差異過大(類似同一臺機器時間回撥,一定會重復),會導致重復ID。
- 基于機器碼和操作中心id,ID具有不可重復性。
- 它的ID是8字節64bit的一個Long長整型數據。
ID基本組成
ID基本組成:
不用: 1bit,因為最高位是符號位,0表示正,1表示負,所以這里固定為0
時間戳: 41bit,服務上線的時間毫秒級的時間戳(為當前時間-服務第一次上線時間),這里為(2^41-1)/1000/60/60/24/365 = 49.7年
工作機器id: 10bit,表示工作機器id,用于處理分布式部署id不重復問題,可支持2^10 = 1024個節點
序列號: 12bit,用于離散同一機器同一毫秒級別生成多條Id時,可允許同一毫秒生成2^12 = 4096個Id,則一秒就可生成4096*1000 = 400w個Id
這樣看,在分布式時,通過時間戳+工作機器ID+散列序列號,幾乎不會重復,當然你必須保證工作機器ID的準確配置。
源碼簡易分析以及注意事項
我們以mybatisplus實現的雪花算法為例:
- IdWorker類:
注意:DefaultIdentifierGenerator()這個必須是單例模式的,否者在多線程高并發下,會有重復ID,而且很多。詳見IDENTIFIER_GENERATOR.nextId(entity)這個方法實現
package com.baomidou.mybatisplus.core.toolkit;import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID
;
import java.util.concurrent.ThreadLocalRandom;public class IdWorker {private static IdentifierGenerator IDENTIFIER_GENERATOR
= new DefaultIdentifierGenerator();public static final DateTimeFormatter MILLISECOND
= DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");public IdWorker() {}public static long getId() {return getId(new Object());}public static long getId(Object entity
) {return IDENTIFIER_GENERATOR
.nextId(entity
).longValue();}public static void initSequence(long workerId
, long dataCenterId
) {IDENTIFIER_GENERATOR
= new DefaultIdentifierGenerator(workerId
, dataCenterId
);}
}
- IDENTIFIER_GENERATOR.nextId(entity).longValue() 方法
nextId是一個線程安全的方法,這也是多線程唯一Id生成的必要之一。
synchronized并不會直接轉成重量級鎖,因為java在1.6已經優化,因此在資源上沒有過分占用,是從偏向鎖,輕量級鎖,再到重量級鎖的過程。
public synchronized long nextId() {long timestamp
= this.timeGen();if (timestamp
< this.lastTimestamp
) {long offset
= this.lastTimestamp
- timestamp
;if (offset
> 5L) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset
));}try {this.wait(offset
<< 1);timestamp
= this.timeGen();if (timestamp
< this.lastTimestamp
) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset
));}} catch (Exception var6
) {throw new RuntimeException(var6
);}}if (this.lastTimestamp
== timestamp
) {this.sequence
= this.sequence
+ 1L & 4095L;if (this.sequence
== 0L) {timestamp
= this.tilNextMillis(this.lastTimestamp
);}} else {this.sequence
= ThreadLocalRandom.current().nextLong(1L, 3L);}this.lastTimestamp
= timestamp
;return timestamp
- 1288834974657L << 22 | this.datacenterId
<< 17 | this.workerId
<< 12 | this.sequence
;}
雪花算法很好用,讓我了解了更多的東西,學習了。
總結
以上是生活随笔為你收集整理的雪花算法之唯一ID生成器理解的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。