Vesta發(fā)號器源碼解析——AtomicIdPopulator
這個類是核心的,用于生成ID的關鍵類之一,是一個實現(xiàn)了IdPopulator, ResetPopulator接口的ID生成類
內(nèi)部類Variant
這個類用于持有在一個生成周期內(nèi)的上一次時間戳以及當前的序列值
class Variant {
private long sequence = 0;
private long lastTimestamp = -1;
}
//利用AtomicReference引用Variant進行操作保證原子性
private AtomicReference<Variant> variant = new AtomicReference<Variant>(new Variant());
構造方法
public AtomicIdPopulator() {
super();
}
populateId方法
核心方法,生成Id中的主要動態(tài)部分,時間和序列號
public void populateId(Timer timer, Id id, IdMeta idMeta) {
//新老兩個準備好
Variant varOld, varNew;
//臨時性的變量存儲時間戳和序列值
long timestamp, sequence;
//不斷嘗試 直到出現(xiàn)退出條件break
while (true) {
//先存好舊的variant
varOld = variant.get();
// 生成當前的variant
//首先是當前周期的時間戳,區(qū)分毫秒級和秒級,在timer中實現(xiàn)
timestamp = timer.genTime();
//校驗時間戳,具體實現(xiàn)在timer中,用于確保使用時間沒有超限制
timer.validateTimestamp(varOld.lastTimestamp, timestamp);
//記錄原始的sequence
sequence = varOld.sequence;
//判斷是否位于同一個周期內(nèi),是的話累加sequ否則重置sequence
if (timestamp == varOld.lastTimestamp) {
//sequence累加
sequence++;
//確保sequence沒有超過限制,超限會導致sequence變成0
sequence &= idMeta.getSeqBitsMask();
if (sequence == 0) {
//超過限制了,等待下一個周期來臨,直到來臨后返回新的時間戳
timestamp = timer.tillNextTimeUnit(varOld.lastTimestamp);
}
} else {
//不在同一個周期,重置sequence
sequence = 0;
}
// 利用原子操作類的CAS特性更新variant
varNew = new Variant();
varNew.sequence = sequence;
varNew.lastTimestamp = timestamp;
if (variant.compareAndSet(varOld, varNew)) {
//更新成功后,組裝傳進來的id
id.setSeq(sequence);
id.setTime(timestamp);
//ID生成成功,退出循環(huán)
break;
}
}
}
Reset方法
用于在下個時間周期來臨的時候重置當先的variant,從而能夠為后續(xù)的周期服務
public void reset() {
variant = new AtomicReference<Variant>(new Variant());
}