先定义一个发号器接口
package com.robert.vesta.service.intf;
import com.robert.vesta.service.bean.Id;
import java.util.Date;
public interface IdService {
/**
* 发号器的主要API,用来产生唯一ID
* @return
*/
public long genId();
/**
* 解读ID,人可识别
* @param id
* @return
*/
public Id expId(long id);
/**
* 用来伪造某一时间的ID
* @param time
* @param seq
* @return
*/
public long makeId(long time, long seq);
public long makeId(long time, long seq, long machine);
public long makeId(long genMethod, long time, long seq, long machine);
public long makeId(long type, long genMethod, long time,
long seq, long machine);
public long makeId(long version, long type, long genMethod,
long time, long seq, long machine);
/**
* 将整形时间翻译成格式化时间
* @param time
* @return
*/
public Date transTime(long time);
}因为有3种同步方式,先给一个抽象类,实现共性.分布式ID由机器号+生产方式+版本号+实现号+时间戳+流水号组成
package com.robert.vesta.service.impl;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdMeta;
import com.robert.vesta.service.impl.bean.IdMetaFactory;
import com.robert.vesta.service.impl.bean.IdType;
import com.robert.vesta.service.impl.converter.IdConverter;
import com.robert.vesta.service.impl.converter.IdConverterImpl;
import com.robert.vesta.service.impl.provider.MachineIdProvider;
import com.robert.vesta.service.impl.timer.SimpleTimer;
import com.robert.vesta.service.impl.timer.Timer;
import com.robert.vesta.service.intf.IdService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
public abstract class AbstractIdServiceImpl implements IdService {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* 机器ID
*/
protected long machineId = -1;
/**
* 生产方式
*/
protected long genMethod = 0;
/**
* 版本
*/
protected long version = 0;
/**
* 实现类型
*/
protected IdType idType;
/**
* ID元数据
*/
protected IdMeta idMeta;
/**
* 元数据,长整型转换器
*/
protected IdConverter idConverter;
/**
* 机器ID生成器
*/
protected MachineIdProvider machineIdProvider;
/**
* 时间处理类
*/
protected Timer timer;
public AbstractIdServiceImpl() {
idType = IdType.SECONDS;
}
public AbstractIdServiceImpl(String type) {
idType = IdType.parse(type);
}
public AbstractIdServiceImpl(long type) {
idType = IdType.parse(type);
}
public AbstractIdServiceImpl(IdType type) {
idType = type;
}
/**
* 实现共有属性
*/
public void init() {
if (this.idMeta == null) {
setIdMeta(IdMetaFactory.getIdMeta(idType));
}
if (this.idConverter == null) {
setIdConverter(new IdConverterImpl());
}
if (this.timer == null) {
setTimer(new SimpleTimer());
}
this.timer.init(idMeta, idType);
this.machineId = machineIdProvider.getMachineId();
validateMachineId(this.machineId);
}
/**
* 生成ID
* @return
*/
public long genId() {
Id id = new Id();
id.setMachine(machineId);
id.setGenMethod(genMethod);
id.setType(idType.value());
id.setVersion(version);
//抽象方法,由子类各自实现,意思就是由不同的方法进行同步
populateId(id);
long ret = idConverter.convert(id, this.idMeta);
// Use trace because it cause low performance
if (log.isTraceEnabled())
log.trace(String.format("Id: %s => %d", id, ret));
return ret;
}
public void validateMachineId(long machineId){
if (machineId < 0) {
log.error("The machine ID is not configured properly (" + machineId + " < 0) so that Vesta Service refuses to start.");
throw new IllegalStateException(
"The machine ID is not configured properly (" + machineId + " < 0) so that Vesta Service refuses to start.");
} else if (machineId >= (1 << this.idMeta.getMachineBits())) {
log.error("The machine ID is not configured properly ("
+ machineId + " >= " + (1 << this.idMeta.getMachineBits()) + ") so that Vesta Service refuses to start.");
throw new IllegalStateException("The machine ID is not configured properly ("
+ machineId + " >= " + (1 << this.idMeta.getMachineBits()) + ") so that Vesta Service refuses to start.");
}
}
protected abstract void populateId(Id id);
public Date transTime(final long time) {
return timer.transTime(time);
}
public Id expId(long id) {
return idConverter.convert(id, this.idMeta);
}
public long makeId(long time, long seq) {
return makeId(time, seq, machineId);
}
public long makeId(long time, long seq, long machine) {
return makeId(genMethod, time, seq, machine);
}
public long makeId(long genMethod, long time, long seq, long machine) {
return makeId(idType.value(), genMethod, time, seq, machine);
}
public long makeId(long type, long genMethod, long time,
long seq, long machine) {
return makeId(version, type, genMethod, time, seq, machine);
}
public long makeId(long version, long type, long genMethod,
long time, long seq, long machine) {
Id id = new Id(machine, seq, time, genMethod, type, version);
return idConverter.convert(id, this.idMeta);
}
public void setMachineId(long machineId) {
this.machineId = machineId;
}
public void setGenMethod(long genMethod) {
this.genMethod = genMethod;
}
public void setVersion(long version) {
this.version = version;
}
public void setIdConverter(IdConverter idConverter) {
this.idConverter = idConverter;
}
public void setIdMeta(IdMeta idMeta) {
this.idMeta = idMeta;
}
public void setMachineIdProvider(MachineIdProvider machineIdProvider) {
this.machineIdProvider = machineIdProvider;
}
public void setTimer(Timer timer) {
this.timer = timer;
}
}实现类,再根据不同的参数进行不同的调用
package com.robert.vesta.service.impl;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdType;
import com.robert.vesta.service.impl.populater.AtomicIdPopulator;
import com.robert.vesta.service.impl.populater.IdPopulator;
import com.robert.vesta.service.impl.populater.LockIdPopulator;
import com.robert.vesta.service.impl.populater.SyncIdPopulator;
import com.robert.vesta.util.CommonUtils;
public class IdServiceImpl extends AbstractIdServiceImpl {
/**
* 同步锁
*/
private static final String SYNC_LOCK_IMPL_KEY = "vesta.sync.lock.impl.key";
/**
* 无锁
*/
private static final String ATOMIC_IMPL_KEY = "vesta.atomic.impl.key";
protected IdPopulator idPopulator;
public IdServiceImpl() {
super();
}
public IdServiceImpl(String type) {
super(type);
}
public IdServiceImpl(long type) {
super(type);
}
public IdServiceImpl(IdType type) {
super(type);
}
@Override
public void init() {
super.init();
initPopulator();
}
/**
* 根据不同的方式调用不同的同步机制
*/
public void initPopulator() {
if (idPopulator != null){
log.info("The " + idPopulator.getClass().getCanonicalName() + " is used.");
} else if (CommonUtils.isPropKeyOn(SYNC_LOCK_IMPL_KEY)) {
log.info("The SyncIdPopulator is used.");
idPopulator = new SyncIdPopulator();
} else if (CommonUtils.isPropKeyOn(ATOMIC_IMPL_KEY)) {
log.info("The AtomicIdPopulator is used.");
idPopulator = new AtomicIdPopulator();
} else {
log.info("The default LockIdPopulator is used.");
idPopulator = new LockIdPopulator();
}
}
protected void populateId(Id id) {
idPopulator.populateId(timer, id, idMeta);
}
public void setIdPopulator(IdPopulator idPopulator) {
this.idPopulator = idPopulator;
}
}因为无锁跟重入锁或者synchronized不同,所以会有接口,一个抽象类
package com.robert.vesta.service.impl.populater;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdMeta;
import com.robert.vesta.service.impl.timer.Timer;
public interface IdPopulator {
/**
* 同秒内产生流水号
* @param timer
* @param id
* @param idMeta
*/
void populateId(Timer timer, Id id, IdMeta idMeta);
/**
* 不同秒内重置
*/
void reset();
}package com.robert.vesta.service.impl.populater;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdMeta;
import com.robert.vesta.service.impl.timer.Timer;
public abstract class BasePopulator implements IdPopulator {
/**
* 流水号
*/
protected long sequence = 0;
/**
* 上一次的时间
*/
protected long lastTimestamp = -1;
public BasePopulator() {
super();
}
/**
* 产生流水ID的算法
* @param timer
* @param id
* @param idMeta
*/
public void populateId(Timer timer, Id id, IdMeta idMeta) {
long timestamp = timer.genTime();
timer.validateTimestamp(lastTimestamp, timestamp);
if (timestamp == lastTimestamp) {
sequence++;
sequence &= idMeta.getSeqBitsMask();
if (sequence == 0) {
timestamp = timer.tillNextTimeUnit(lastTimestamp);
}
} else {
lastTimestamp = timestamp;
sequence = 0;
}
id.setSeq(sequence);
id.setTime(timestamp);
}
public void reset() {
this.sequence = 0;
this.lastTimestamp = -1;
}
}其实前面只是铺垫------------------------------
package com.robert.vesta.service.impl.populater;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdMeta;
import com.robert.vesta.service.impl.timer.Timer;
public class SyncIdPopulator extends BasePopulator {
public SyncIdPopulator() {
super();
}
public synchronized void populateId(Timer timer, Id id, IdMeta idMeta) {
super.populateId(timer, id, idMeta);
}
}package com.robert.vesta.service.impl.populater;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdMeta;
import com.robert.vesta.service.impl.timer.Timer;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockIdPopulator extends BasePopulator {
private Lock lock = new ReentrantLock();
public LockIdPopulator() {
super();
}
public void populateId(Timer timer, Id id, IdMeta idMeta) {
lock.lock();
try {
super.populateId(timer, id, idMeta);
} finally {
lock.unlock();
}
}
}以上是两个同步方法的实现,都继承于抽象类
原子类无锁只实现接口,不继承于抽象类
package com.robert.vesta.service.impl.populater;
import com.robert.vesta.service.bean.Id;
import com.robert.vesta.service.impl.bean.IdMeta;
import com.robert.vesta.service.impl.timer.Timer;
import java.util.concurrent.atomic.AtomicReference;
public class AtomicIdPopulator implements IdPopulator {
class Variant {
private long sequence = 0;
private long lastTimestamp = -1;
}
private AtomicReference<Variant> variant = new AtomicReference<Variant>(new Variant());
public AtomicIdPopulator() {
super();
}
public void populateId(Timer timer, Id id, IdMeta idMeta) {
Variant varOld, varNew;
long timestamp, sequence;
while (true) {
// Save the old variant
varOld = variant.get();
// populate the current variant
timestamp = timer.genTime();
timer.validateTimestamp(varOld.lastTimestamp, timestamp);
sequence = varOld.sequence;
if (timestamp == varOld.lastTimestamp) {
sequence++;
sequence &= idMeta.getSeqBitsMask();
if (sequence == 0) {
timestamp = timer.tillNextTimeUnit(varOld.lastTimestamp);
}
} else {
sequence = 0;
}
// Assign the current variant by the atomic tools
varNew = new Variant();
varNew.sequence = sequence;
varNew.lastTimestamp = timestamp;
if (variant.compareAndSet(varOld, varNew)) {
id.setSeq(sequence);
id.setTime(timestamp);
break;
}
}
}
public void reset() {
variant = new AtomicReference<Variant>(new Variant());
}
}