Vesta发号器源码解析——SimpleTimer
这个类是Timer的一个简单的实现,主要负责对时间控制
字段及属性
//日志
protected static final Logger log = LoggerFactory.getLogger(SimpleTimer.class);
//Id元数据
protected IdMeta idMeta;
//Id的类型
protected IdType idType;
//最大时间
protected long maxTime;
//时间压缩的基础,相当于新的时间起点
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的使用日志
记录出能够使用的天数
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);
}
设置时间压缩基础
//设置epoch
public void setEpoch(long epoch) {
this.epoch = epoch;
}
时间转换函数
时间转换函数,将压缩后的时间戳转换为date对象
public Date transTime(long time) {
//做好类型区分,区别到底按照毫秒级计算还是秒级
if (idType == IdType.MILLISECONDS) {
return new Date(time + epoch);
} else {
return new Date(time * 1000 + epoch);
}
}
验证时间戳
校验时间的先后顺序
public void validateTimestamp(long lastTimestamp, long timestamp) {
//发生了时钟回拨
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));
}
}
时间等待
用于在发生次数满了的时候进行时间的等待,等待到了下一个时间周期来的时候返回新的时间戳
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;
}
生成时间
生成压缩后的时间戳,也就是利用最新的时间减去压缩基础
public long genTime() {
long time;
//按类型做好区分
if (idType == IdType.MILLISECONDS) {
time = (System.currentTimeMillis() - epoch);
} else {
time = (System.currentTimeMillis() - epoch) / 1000;
}
//校验生成的时间戳是否有效,主要是看是够超超时
validateTimestamp(time);
return time;
}
时间戳校验
校验时间戳是否已经超过了最大的生成时间
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);
}
}