Vesta發(fā)號器源碼解析——SimpleTimer
這個類是Timer的一個簡單的實現(xiàn),主要負責對時間控制
字段及屬性
//日志
protected static final Logger log = LoggerFactory.getLogger(SimpleTimer.class);
//Id元數(shù)據(jù)
protected IdMeta idMeta;
//Id的類型
protected IdType idType;
//最大時間
protected long maxTime;
//時間壓縮的基礎(chǔ),相當于新的時間起點
protected long epoch = EPOCH
初始化方法
初始化方法
public void init(IdMeta idMeta, IdType idType) {
this.idMeta = idMeta;
//利用移位操作計算出時間的長度能夠標示的最大時間
this.maxTime = (1L << idMeta.getTimeBits()) - 1;
this.idType = idType;
this.genTime();
this.timerUsedLog();
}
timer的使用日志
記錄出能夠使用的天數(shù)
public void timerUsedLog(){
//最大的時間計算
Date expirationDate = transTime(maxTime);
//計算出最大的值所能標示的具體時間
long days = ((expirationDate.getTime() - System.currentTimeMillis())/(1000 * 60 * 60 * 24));
//記錄日志
log.info("The current time bit length is {}, the expiration date is {}, this can be used for {} days.",
idMeta.getTimeBits(), expirationDate, days);
}
設(shè)置時間壓縮基礎(chǔ)
//設(shè)置epoch
public void setEpoch(long epoch) {
this.epoch = epoch;
}
時間轉(zhuǎn)換函數(shù)
時間轉(zhuǎn)換函數(shù),將壓縮后的時間戳轉(zhuǎn)換為date對象
public Date transTime(long time) {
//做好類型區(qū)分鸯屿,區(qū)別到底按照毫秒級計算還是秒級
if (idType == IdType.MILLISECONDS) {
return new Date(time + epoch);
} else {
return new Date(time * 1000 + epoch);
}
}
驗證時間戳
校驗時間的先后順序
public void validateTimestamp(long lastTimestamp, long timestamp) {
//發(fā)生了時鐘回撥
if (timestamp < lastTimestamp) {
if (log.isErrorEnabled())
//記錄日志,時鐘回撥了把敢,拒絕生成id寄摆,拋出異常
log.error(String
.format("Clock moved backwards. Refusing to generate id for %d second/milisecond.",
lastTimestamp - timestamp));
throw new IllegalStateException(
String.format(
"Clock moved backwards. Refusing to generate id for %d second/milisecond.",
lastTimestamp - timestamp));
}
}
時間等待
用于在發(fā)生次數(shù)滿了的時候進行時間的等待,等待到了下一個時間周期來的時候返回新的時間戳
public long tillNextTimeUnit(final long lastTimestamp) {
//記錄日志
if (log.isInfoEnabled())
log.info(String
.format("Ids are used out during %d. Waiting till next second/milisencond.",
lastTimestamp));
//生成新的時間戳
long timestamp = genTime();
//新的時間戳如果沒有比之前的大修赞,說明仍然處于老時間
//自旋鎖等待
while (timestamp <= lastTimestamp) {
timestamp = genTime();
}
//時間更新婶恼,記錄日志
if (log.isInfoEnabled())
log.info(String.format("Next second/milisencond %d is up.",
timestamp));
//返回新的時間戳
return timestamp;
}
生成時間
生成壓縮后的時間戳桑阶,也就是利用最新的時間減去壓縮基礎(chǔ)
public long genTime() {
long time;
//按類型做好區(qū)分
if (idType == IdType.MILLISECONDS) {
time = (System.currentTimeMillis() - epoch);
} else {
time = (System.currentTimeMillis() - epoch) / 1000;
}
//校驗生成的時間戳是否有效,主要是看是夠超超時
validateTimestamp(time);
return time;
}
時間戳校驗
校驗時間戳是否已經(jīng)超過了最大的生成時間
protected void validateTimestamp(long timestamp){
if (timestamp > maxTime) {
String error = String.format(
"The current timestamp (%s >= %s) has overflowed, Vesta Service will be terminate.", timestamp, maxTime);
log.error(error);
throw new RuntimeException(error);
}
}